A ‘joins_many’ relation. This objects is associated with an other using an intermediate join table.
Examples
joins_many :categories joins_many Category joins_many :categories, MyCategory
Methods
Public Instance methods
[ show source ]
# File lib/og/relation/joins_many.rb, line 36
36: def enchant
37: self[:owner_singular_name] = owner_class.to_s.demodulize.underscore.downcase
38: self[:target_singular_name] = target_plural_name.to_s.singular
39:
40: owner_class.ogmanager.with_store do |store|
41: # handle schema_inheritance
42:
43: join_class = owner_class.table_class
44: join_table_info = store.join_table_info(self)
45:
46: if through = self[:through]
47: # A custom class is used for the join. Use the class
48: # table and don't create a new table.
49:
50: through = Relation.symbol_to_class(through, owner_class) if through.is_a?(Symbol)
51: join_table = self[:join_table] = store.table(through)
52:
53: tmp_join_class = through
54: else
55: # Calculate the name of the join table.
56:
57: join_table = self[:join_table] = join_table_info[:table]
58:
59: # Create a join table.
60:
61: owner_class.ann!(:self)[:join_tables] ||= []
62: owner_class.ann!(:self, :join_tables) << join_table_info
63:
64: # Create temporary classes to be able to use ann.descendants to cascade
65: # delete joins_many relations when one side of the relation is removed.
66:
67: tmp_join_class_name = "OgTempJ_#{join_table}"
68:
69: unless self.class.constants.include?(tmp_join_class_name)
70: tmp_join_class = self.class.const_set(tmp_join_class_name, Class.new)
71: tmp_join_class.const_set('OGTABLE', join_table)
72: else
73: tmp_join_class = self.class.const_get(tmp_join_class_name)
74: end
75: end
76:
77: owner_key = join_table_info[:owner_key]
78: target_key = join_table_info[:target_key]
79:
80: # Add join class to ann(:descendants) to be able to use cascade deletes.
81:
82: owner_class.ann!(:self)[:descendants] ||= []
83: owner_class.ann!(:self, :descendants) << [tmp_join_class, owner_key]
84:
85: owner_class.module_eval %{
86: attr_accessor :#{target_plural_name}
87:
88: def #{target_plural_name}(options = nil)
89: reload = options and options[:reload]
90:
91: unless @#{target_plural_name}
92: @#{target_plural_name} = JoinsManyCollection.new(
93: self,
94: #{target_class},
95: :add_#{target_singular_name},
96: :remove_#{target_singular_name},
97: :find_#{target_plural_name},
98: :count_#{target_plural_name},
99: options
100: )
101: end
102:
103: @#{target_plural_name}.find_options = options
104: @#{target_plural_name}.reload(options) if options and options[:reload]
105: @#{target_plural_name}
106: end
107:
108: def add_#{target_singular_name}(obj, options = nil)
109: obj.save if obj.unsaved?
110: obj.class.ogmanager.with_store do |s|
111: s.join(self, obj, "#{join_table}", options)
112: end
113: end
114:
115: def remove_#{target_singular_name}(obj)
116: obj.class.ogmanager.with_store do |s|
117: s.unjoin(self, obj, "#{join_table}")
118: end
119: end
120:
121: def find_#{target_plural_name}(options = {})
122: find_options = {
123: :join_table => "#{join_table}",
124: :join_condition => "#{join_table}.#{target_key}=\#{#{target_class}::OGTABLE}.oid",
125: :condition => "#{join_table}.#{owner_key}=\#\{#{owner_class.primary_key}\}"
126: }
127: if options
128: if condition = options.delete(:condition)
129: find_options[:condition] += " AND (\#{condition})"
130: end
131: find_options.update(options)
132: end
133: #{target_class}.find(find_options)
134: end
135:
136: def count_#{target_plural_name}
137: find_options = {
138: :join_table => "#{join_table}",
139: :join_condition => "#{join_table}.#{target_key}=\#{#{target_class}::OGTABLE}.oid",
140: :condition => "#{join_table}.#{owner_key}=\#\{#{owner_class.primary_key}\}"
141: }
142: #{target_class}.count(find_options)
143: end
144: }
145:
146: if through
147: owner_class.module_eval %{
148: def #{target_singular_name}_join_data(t)
149: #{through}.find_one(:condition => "#{owner_key}=\#{#{owner_class.primary_key}} and #{target_key}=\#{t.pk}")
150: end
151: }
152: end
153: end
154: end
[ show source ]
# File lib/og/relation/joins_many.rb, line 30
30: def resolve_polymorphic
31: target_class.module_eval %{
32: joins_many :#{owner_class.to_s.demodulize.underscore.pluralize}
33: }
34: end