Module: Replicate::AR::InstanceMethods
- Defined in:
- lib/replicate/active_record.rb
Overview
Mixin for the ActiveRecord instance.
Instance Method Summary collapse
-
#dump_all_association_replicants(dumper, association_type) ⇒ Object
Dump all associations of a given type.
-
#dump_association_replicants(dumper, association) ⇒ Object
Dump objects associated with an AR object through an association name.
-
#dump_has_and_belongs_to_many_replicant(dumper, reflection) ⇒ Object
Dump the special Habtm object used to establish many-to-many relationships between objects that have already been dumped.
-
#dump_replicant(dumper, opts = {}) ⇒ Object
Replicate::Dumper calls this method on objects to trigger dumping a replicant object tuple.
-
#included_associations ⇒ Object
List of associations to explicitly include when dumping this object.
-
#omitted_attributes ⇒ Object
List of attributes and associations to omit when dumping this object.
-
#replicant_attributes ⇒ Object
Attributes hash used to persist this object.
-
#replicant_id ⇒ Object
The replicant id is a two tuple containing the class and object id.
-
#replicate_reflection_info(reflection) ⇒ Object
Retrieve information on a reflection’s associated class and various keys.
Instance Method Details
#dump_all_association_replicants(dumper, association_type) ⇒ Object
Dump all associations of a given type.
dumper - The Dumper object used to dump additional objects. association_type - :has_one, :belongs_to, :has_many
Returns nothing.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/replicate/active_record.rb', line 128 def dump_all_association_replicants(dumper, association_type) self.class.reflect_on_all_associations(association_type).each do |reflection| next if omitted_attributes.include?(reflection.name) # bail when this object has already been dumped next if (info = replicate_reflection_info(reflection)) && (replicant_id = info[:replicant_id]) && dumper.dumped?(replicant_id) next if (dependent = __send__(reflection.name)).nil? case dependent when ActiveRecord::Base, Array dumper.dump(dependent) # clear reference to allow GC if respond_to?(:association) association(reflection.name).reset elsif respond_to?(:association_instance_set, true) association_instance_set(reflection.name, nil) end else warn "warn: #{self.class}##{reflection.name} #{association_type} association " \ "unexpectedly returned a #{dependent.class}. skipping." end end end |
#dump_association_replicants(dumper, association) ⇒ Object
Dump objects associated with an AR object through an association name.
object - AR object instance. association - Name of the association whose objects should be dumped.
Returns nothing.
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/replicate/active_record.rb', line 162 def dump_association_replicants(dumper, association) if reflection = self.class.reflect_on_association(association) objects = __send__(reflection.name) dumper.dump(objects) if reflection.macro == :has_and_belongs_to_many dump_has_and_belongs_to_many_replicant(dumper, reflection) end __send__(reflection.name).reset # clear to allow GC else warn "error: #{self.class}##{association} is invalid" end end |
#dump_has_and_belongs_to_many_replicant(dumper, reflection) ⇒ Object
Dump the special Habtm object used to establish many-to-many relationships between objects that have already been dumped. Note that this object and all objects referenced must have already been dumped before calling this method.
179 180 181 |
# File 'lib/replicate/active_record.rb', line 179 def dump_has_and_belongs_to_many_replicant(dumper, reflection) dumper.dump Habtm.new(self, reflection) end |
#dump_replicant(dumper, opts = {}) ⇒ Object
Replicate::Dumper calls this method on objects to trigger dumping a replicant object tuple. The default implementation dumps all belongs_to associations, then self, then all has_one associations, then any has_many or has_and_belongs_to_many associations declared with the replicate_associations macro.
dumper - Dumper object whose #write method must be called with the
type, id, and attributes hash.
Returns nothing.
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/replicate/active_record.rb', line 22 def dump_replicant(dumper, opts={}) @replicate_opts = opts @replicate_opts[:associations] ||= [] @replicate_opts[:omit] ||= [] dump_all_association_replicants dumper, :belongs_to dumper.write self.class.to_s, id, replicant_attributes, self dump_all_association_replicants dumper, :has_one included_associations.each do |association| dump_association_replicants dumper, association end end |
#included_associations ⇒ Object
List of associations to explicitly include when dumping this object.
35 36 37 |
# File 'lib/replicate/active_record.rb', line 35 def included_associations (self.class.replicate_associations + @replicate_opts[:associations]).uniq end |
#omitted_attributes ⇒ Object
List of attributes and associations to omit when dumping this object.
40 41 42 |
# File 'lib/replicate/active_record.rb', line 40 def omitted_attributes (self.class.replicate_omit_attributes + @replicate_opts[:omit]).uniq end |
#replicant_attributes ⇒ Object
Attributes hash used to persist this object. This consists of simply typed values (no complex types or objects) with the exception of special foreign key values. When an attribute value is [:id, “SomeClass:1234”], the loader will handle translating the id value to the local system’s version of the same object.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/replicate/active_record.rb', line 49 def replicant_attributes attributes = self.attributes.dup omitted_attributes.each { |omit| attributes.delete(omit.to_s) } self.class.reflect_on_all_associations(:belongs_to).each do |reflection| if info = replicate_reflection_info(reflection) if replicant_id = info[:replicant_id] foreign_key = info[:foreign_key].to_s attributes[foreign_key] = [:id, *replicant_id] end end end attributes end |
#replicant_id ⇒ Object
The replicant id is a two tuple containing the class and object id. This is used by Replicant::Dumper to determine if the object has already been dumped or not.
118 119 120 |
# File 'lib/replicate/active_record.rb', line 118 def replicant_id [self.class.name, id] end |
#replicate_reflection_info(reflection) ⇒ Object
Retrieve information on a reflection’s associated class and various keys.
Returns an info hash with these keys:
:class - The class object the association points to.
:primary_key - The string primary key column name.
:foreign_key - The string foreign key column name.
:replicant_id - The [classname, id] tuple the record.
Returns nil when the reflection can not be linked to a model.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/replicate/active_record.rb', line 75 def replicate_reflection_info(reflection) = reflection. if [:polymorphic] reference_class = if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR > 0 attributes[reflection.foreign_type] else attributes[[:foreign_type]] end return if reference_class.nil? klass = Kernel.const_get(reference_class) primary_key = klass.primary_key foreign_key = "#{reflection.name}_id" else klass = reflection.klass primary_key = ([:primary_key] || klass.primary_key).to_s foreign_key = ([:foreign_key] || "#{reflection.name}_id").to_s end info = { :class => klass, :primary_key => primary_key, :foreign_key => foreign_key } if primary_key == klass.primary_key if id = attributes[foreign_key] info[:replicant_id] = [klass.to_s, id] else # nil value in association reference end else # association uses non-primary-key foreign key. no special key # conversion needed. end info end |