Module: RTM::AR::TraverseAssociations

Included in:
Sugar::Topic::PredefinedAssociations
Defined in:
lib/rtm/activerecord/traverse_associations.rb,
lib/rtm/activerecord.rb

Instance Method Summary collapse

Instance Method Details

#define_association(prop, options = {}) ⇒ Object

defines methods to traverse a specific assocation for all topics



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rtm/activerecord/traverse_associations.rb', line 7

def define_association(prop, options={})
  r = options[:rule]
  module_eval("    def direct_\#{prop}_roles\n      # prefetch typing topics\n      rtype = @ips_\#{prop}_rtype ||= self.topic_map.get(\"\#{r[:role_type]}\")\n      atype = @ips_\#{prop}_atype ||= self.topic_map.get(\"\#{r[:association_type]}\")\n      otype = @ips_\#{prop}_otype ||= self.topic_map.get(\"\#{r[:other_role_type]}\")\n      # return nothing if any of the typing topics does not exist\n      return [] unless rtype && atype && otype\n      # we do that only here and not earlier because some might me nil\n      rtype = rtype.id\n      atype = atype.id\n      otype = otype.id\n      self.__getobj__.roles.map{|r|\n        r.ttype_id != nil &&\n          r.ttype_id == rtype &&\n          r.parent.roles.size == \#{r[:association_arity]} &&\n          r.parent != nil &&\n          r.parent.ttype_id == atype &&\n          (r2 = r.parent.roles.select{|r2| r2.ttype_id != nil &&\n            r2.ttype_id == otype}.first) &&\n          r2}.select{|r2| r2}.map{|r2| AssociationRole.wrap(r2)}\n    end\n    def direct_\#{prop}\n      direct_\#{prop}_roles.map{|r2| r2.player}.uniq\n    end\n  EOS\n  \n  if r[:transitive]\n    module_eval(<<-EOS, \"(__AR_DELEGATOR_DEFINE_ASSOCIATION2__)\", 1)\n      def \#{prop}\n        d = todo = self.direct_\#{prop}\n        while todo.size > 0\n          todo = todo.map{|dt| dt.direct_\#{prop}}.flatten.uniq - d\n          d += todo\n        end\n        d\n        #d2 = self.direct_\#{prop}.map {|dt| dt.\#{prop}}.flatten\n        #(d+d2).uniq\n      end\n    EOS\n  else\n    if r[:infer] && r[:infer_other] # this part is not testet at all!\n      module_eval(<<-EOS, \"(__AR_DELEGATOR_DEFINE_ASSOCIATION3a__)\", 1)\n        def \#{prop}\n          dps = (self + self.\#{r[:infer]}).flatten.uniq\n          dcps = dps.map{|d2| d2.direct_\#{prop}}\n          (dcps + dcps.map{|d2| d2.\#{r[:infer_other]}}).flatten.uniq\n        end\n      EOS\n    elsif r[:infer]\n      module_eval(<<-EOS, \"(__AR_DELEGATOR_DEFINE_ASSOCIATION3__)\", 1)\n        def \#{prop}\n          (self.direct_\#{prop} + self.\#{r[:infer]}.map{|d2| d2.direct_\#{prop}}).flatten.uniq\n        end\n      EOS\n    elsif r[:infer_other]\n      module_eval(<<-EOS, \"(__AR_DELEGATOR_DEFINE_ASSOCIATION4__)\", 1)\n        def \#{prop}\n          d = self.direct_\#{prop}\n          (d + d.map{|d2| d2.\#{r[:infer_other]}}).flatten.uniq\n        end\n      EOS\n    end\n  end\n  if r[:add]\n    module_eval(<<-EOS, \"(__AR_DELEGATOR_DEFINE_ASSOCIATION_ADD_REMOVE__)\", 1)\n      def add_\#{r[:add]}(t)\n        a = self.topic_map.create_association(\"\#{r[:association_type]}\")\n        a.create_role self, \"\#{r[:role_type]}\"\n        a.create_role t, \"\#{r[:other_role_type]}\"\n        a\n        # TODO add_x in define_association needs to trigger reload of the topics somewhere\n      end\n      def remove_\#{r[:add]}(t)\n        direct_\#{prop}_roles.select{|r| r.player == t}.each{|r| r.parent.remove}\n        # TODO remove_x in define_association needs to trigger reload of the topics somewhere\n      end\n    EOS\n  end\nend\n", "(__AR_DELEGATOR_DEFINE_ASSOCIATION__)", 1)