From a1d431cf88480b303c8e64439a0d6daf0dff1c20 Mon Sep 17 00:00:00 2001 From: yann ARMAND Date: Fri, 13 Mar 2015 22:46:02 +0000 Subject: [PATCH] [back_assignments] move CollectionOfProxy class in its own file --- lib/couchrest/model/associations.rb | 80 +----------------- .../model/associations/collection_of_proxy.rb | 81 +++++++++++++++++++ lib/couchrest_model.rb | 1 + spec/unit/assocations_spec.rb | 2 +- 4 files changed, 85 insertions(+), 79 deletions(-) create mode 100644 lib/couchrest/model/associations/collection_of_proxy.rb diff --git a/lib/couchrest/model/associations.rb b/lib/couchrest/model/associations.rb index 45efead4..02a7885c 100644 --- a/lib/couchrest/model/associations.rb +++ b/lib/couchrest/model/associations.rb @@ -180,7 +180,7 @@ def create_collection_of_getter(attrib, options) def #{attrib}(reload = false) return @#{attrib} unless @#{attrib}.nil? or reload ary = self.#{options[:foreign_key]}.collect{|i| #{options[:proxy]}.get(i)} - @#{attrib} = ::CouchRest::Model::CollectionOfProxy.new(ary, find_property('#{options[:foreign_key]}'), self) + @#{attrib} = ::CouchRest::Model::Associations::CollectionOfProxy.new(ary, find_property('#{options[:foreign_key]}'), self) end EOS end @@ -188,7 +188,7 @@ def #{attrib}(reload = false) def create_collection_of_setter(attrib, options) class_eval <<-EOS, __FILE__, __LINE__ + 1 def #{attrib}=(value) - @#{attrib} = ::CouchRest::Model::CollectionOfProxy.new(value, find_property('#{options[:foreign_key]}'), self) + @#{attrib} = ::CouchRest::Model::Associations::CollectionOfProxy.new(value, find_property('#{options[:foreign_key]}'), self) end EOS end @@ -232,82 +232,6 @@ def save_dirty_association end - # Special proxy for a collection of items so that adding and removing - # to the list automatically updates the associated property. - class CollectionOfProxy < CastedArray - - def initialize(array, property, parent) - (array ||= []).compact! - super(array, property, parent) - casted_by[casted_by_property.to_s] = [] # replace the original array! - array.compact.each do |obj| - check_obj(obj) - casted_by[casted_by_property.to_s] << obj.id - end - end - - def << obj - add_to_collection_with(:<<, obj) - super(obj) - end - - def push(obj) - add_to_collection_with(:push, obj) - super(obj) - end - - def unshift(obj) - add_to_collection_with(:unshift, obj) - super(obj) - end - - def []= index, obj - add_to_collection_with(:[]=, obj, index) - super(index, obj) - end - - def pop - obj = casted_by.send(casted_by_property.options[:proxy_name]).last - casted_by[casted_by_property.to_s].pop - obj.set_back_association(nil, casted_by.class.name, casted_by_property.options[:reverse_association]) - casted_by.register_dirty_association(obj) - super - end - - def shift - obj = casted_by.send(casted_by_property.options[:proxy_name]).first - casted_by[casted_by_property.to_s].shift - obj.set_back_association(nil, casted_by.class.name, casted_by_property.options[:reverse_association]) - casted_by.register_dirty_association(obj) - super - end - - protected - - def check_obj(obj) - raise "Object cannot be added to #{casted_by.class.to_s}##{casted_by_property.to_s} collection unless saved" if obj.new? - end - - def add_to_collection_with(method, obj, index=nil) - check_obj(obj) - args = [ obj.id ] - args = args.insert(0, index) if index - casted_by[casted_by_property.to_s].send(method, *args) - obj.set_back_association(casted_by, casted_by.class.name, casted_by_property.options[:reverse_association]) - casted_by.register_dirty_association(obj) - end - - # Override CastedArray instantiation_and_cast method for a simpler - # version that will not try to cast the model. - def instantiate_and_cast(obj, change = true) - couchrest_parent_will_change! if change && use_dirty? - obj.casted_by = casted_by if obj.respond_to?(:casted_by) - obj.casted_by_property = casted_by_property if obj.respond_to?(:casted_by_property) - obj - end - - end - end end diff --git a/lib/couchrest/model/associations/collection_of_proxy.rb b/lib/couchrest/model/associations/collection_of_proxy.rb new file mode 100644 index 00000000..0e772359 --- /dev/null +++ b/lib/couchrest/model/associations/collection_of_proxy.rb @@ -0,0 +1,81 @@ +module CouchRest + module Model + module Associations + # Special proxy for a collection of items so that adding and removing + # to the list automatically updates the associated property. + class CollectionOfProxy < CastedArray + + def initialize(array, property, parent) + (array ||= []).compact! + super(array, property, parent) + casted_by[casted_by_property.to_s] = [] # replace the original array! + array.compact.each do |obj| + check_obj(obj) + casted_by[casted_by_property.to_s] << obj.id + end + end + + def << obj + add_to_collection_with(:<<, obj) + super(obj) + end + + def push(obj) + add_to_collection_with(:push, obj) + super(obj) + end + + def unshift(obj) + add_to_collection_with(:unshift, obj) + super(obj) + end + + def []= index, obj + add_to_collection_with(:[]=, obj, index) + super(index, obj) + end + + def pop + obj = casted_by.send(casted_by_property.options[:proxy_name]).last + casted_by[casted_by_property.to_s].pop + obj.set_back_association(nil, casted_by.class.name, casted_by_property.options[:reverse_association]) + casted_by.register_dirty_association(obj) + super + end + + def shift + obj = casted_by.send(casted_by_property.options[:proxy_name]).first + casted_by[casted_by_property.to_s].shift + obj.set_back_association(nil, casted_by.class.name, casted_by_property.options[:reverse_association]) + casted_by.register_dirty_association(obj) + super + end + + protected + + def check_obj(obj) + raise "Object cannot be added to #{casted_by.class.to_s}##{casted_by_property.to_s} collection unless saved" if obj.new? + end + + def add_to_collection_with(method, obj, index=nil) + check_obj(obj) + args = [ obj.id ] + args = args.insert(0, index) if index + casted_by[casted_by_property.to_s].send(method, *args) + obj.set_back_association(casted_by, casted_by.class.name, casted_by_property.options[:reverse_association]) + casted_by.register_dirty_association(obj) + end + + # Override CastedArray instantiation_and_cast method for a simpler + # version that will not try to cast the model. + def instantiate_and_cast(obj, change = true) + couchrest_parent_will_change! if change && use_dirty? + obj.casted_by = casted_by if obj.respond_to?(:casted_by) + obj.casted_by_property = casted_by_property if obj.respond_to?(:casted_by_property) + obj + end + + end + end + end +end diff --git a/lib/couchrest_model.rb b/lib/couchrest_model.rb index e66078e7..08c32ab3 100644 --- a/lib/couchrest_model.rb +++ b/lib/couchrest_model.rb @@ -40,6 +40,7 @@ require "couchrest/model/extended_attachments" require "couchrest/model/proxyable" require "couchrest/model/associations" +require "couchrest/model/associations/collection_of_proxy" require "couchrest/model/configuration" require "couchrest/model/connection" require "couchrest/model/design" diff --git a/spec/unit/assocations_spec.rb b/spec/unit/assocations_spec.rb index 2582bf3d..cb2c2eb5 100644 --- a/spec/unit/assocations_spec.rb +++ b/spec/unit/assocations_spec.rb @@ -111,7 +111,7 @@ def SaleInvoice.merge_assoc_opts(*args) it "should create an associated property and collection proxy" do @invoice.respond_to?('entry_ids').should be_true @invoice.respond_to?('entry_ids=').should be_true - @invoice.entries.class.should eql(::CouchRest::Model::CollectionOfProxy) + @invoice.entries.class.should eql(::CouchRest::Model::Associations::CollectionOfProxy) end it "should allow replacement of objects" do