class Deferring::DeferredAssociation
Attributes
Public Class Methods
# File lib/deferring/deferred_association.rb, line 13 def initialize(original_association, klass, parent_record, inverse_name, dependent) super(original_association) @load_state = :ghost @klass = klass @parent_record = parent_record @inverse_name = inverse_name @dependent = dependent end
Public Instance Methods
# File lib/deferring/deferred_association.rb, line 119 def <<(*records) # TODO: Do we want to prevent including the same object twice? Not sure, # but it will probably be filtered after saving and retrieving as well. records.flatten.compact.uniq.each do |record| run_deferring_callbacks(:link, record) do if inverse_name && record.class.reflect_on_association(inverse_name) record.send(:"#{inverse_name}=", parent_record) end objects << record end end self end
# File lib/deferring/deferred_association.rb, line 211 def add_callback_listener(event_name, callback_method) (@listeners ||= []) << DeferredCallbackListener.new(event_name, parent_record, callback_method) end
# File lib/deferring/deferred_association.rb, line 156 def build(*args, &block) klass.new(*args, &block).tap do |record| run_deferring_callbacks(:link, record) do if inverse_name && record.class.reflect_on_association(inverse_name) record.send(:"#{inverse_name}=", parent_record) end objects.push(record) end end end
Returns true if there are links that will be created or deleted when saving the parent of the association.
# File lib/deferring/deferred_association.rb, line 207 def changed_for_autosave? links.any? || unlinks.any? end
Delegates Ruby’s Enumerable#count method to the original association.
The delegation has to be explicit in this case, because the inclusion of Enumerable also defines the count-method on DeferredAssociation
.
# File lib/deferring/deferred_association.rb, line 65 def count(*args, &block) if block_given? objects.count(*args, &block) else original_association.count(*args) end end
# File lib/deferring/deferred_association.rb, line 168 def create(*args, &block) association.create(*args, &block).tap do |_| @load_state = :ghost load_objects end end
# File lib/deferring/deferred_association.rb, line 175 def create!(*args, &block) association.create!(*args, &block).tap do |_| @load_state = :ghost load_objects end end
# File lib/deferring/deferred_association.rb, line 137 def delete(*records) records.flatten.compact.uniq.each do |record| run_deferring_callbacks(:unlink, record) { objects.delete(record) } end self end
# File lib/deferring/deferred_association.rb, line 144 def destroy(*records) records.flatten.compact.uniq.each do |record| record = record.to_i if record.is_a? String record = objects.detect { |o| o.id == record } if record.is_a? Integer run_deferring_callbacks(:unlink, record) { objects.delete(record) record.mark_for_destruction if dependent && [:destroy, :delete_all].include?(dependent) } end end
# File lib/deferring/deferred_association.rb, line 31 def each(&block) objects.each(&block) end
Delegates Ruby’s Enumerable#find method to the original association.
The delegation has to be explicit in this case, because the inclusion of Enumerable also defines the find-method on DeferredAssociation
.
# File lib/deferring/deferred_association.rb, line 57 def find(*args) original_association.find(*args) end
# File lib/deferring/deferred_association.rb, line 115 def ids objects.map(&:id) end
# File lib/deferring/deferred_association.rb, line 23 def inspect objects.inspect end
Returns the associated records to which links will be created after saving the parent of the association.
# File lib/deferring/deferred_association.rb, line 191 def links return [] unless objects_loaded? objects - original_objects end
# File lib/deferring/deferred_association.rb, line 93 def objects load_objects @objects end
# File lib/deferring/deferred_association.rb, line 98 def objects=(records) @objects = records.compact.map do |record| if inverse_name && record.class.reflect_on_association(inverse_name) record.send(:"#{inverse_name}=", parent_record) end record end @original_objects = original_association.to_a.clone objects_loaded! pending_deletes.each { |record| run_deferring_callbacks(:unlink, record) } pending_creates.each { |record| run_deferring_callbacks(:link, record) } @objects end
# File lib/deferring/deferred_association.rb, line 182 def reload original_association.reload @load_state = :ghost self end
Delegates Ruby’s Enumerable#select method to the original association when no block has been given. Rails’ select-method does not accept a block, so we know that in that case the select-method has to be called on our deferred association.
The delegation has to be explicit in this case, because the inclusion of Enumerable also defines the select-method on DeferredAssociation
.
# File lib/deferring/deferred_association.rb, line 80 def select(value = nil, &block) if block_given? objects.select { |*block_args| block.call(*block_args) } else original_association.select(value) end end
Rails 3.0 specific, not needed anymore for Rails 3.0+
# File lib/deferring/deferred_association.rb, line 89 def set_inverse_instance(associated_record, parent_record) original_association.__send__(:set_inverse_instance, associated_record, parent_record) end
Returns the associated records to which the links will be deleted after saving the parent of the assocation.
# File lib/deferring/deferred_association.rb, line 199 def unlinks return [] unless objects_loaded? original_objects - objects end
Private Instance Methods
# File lib/deferring/deferred_association.rb, line 217 def association load_objects original_association end
# File lib/deferring/deferred_association.rb, line 222 def load_objects return if objects_loaded? @objects = original_association.to_a.clone @original_objects = @objects.clone.freeze objects_loaded! end
# File lib/deferring/deferred_association.rb, line 249 def notify_callback_listeners(event_name, record) @listeners && @listeners.each do |listener| if listener.event_name == event_name listener.public_send(event_name, record) end end end
# File lib/deferring/deferred_association.rb, line 234 def objects_loaded! @load_state = :loaded end
# File lib/deferring/deferred_association.rb, line 230 def objects_loaded? @load_state == :loaded end
# File lib/deferring/deferred_association.rb, line 238 def original_objects load_objects @original_objects end
# File lib/deferring/deferred_association.rb, line 243 def run_deferring_callbacks(event_name, record) notify_callback_listeners(:"before_#{event_name}", record) yield if block_given? notify_callback_listeners(:"after_#{event_name}", record) end