Skip to content

Commit

Permalink
[back_assignments] move CollectionOfProxy class in its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
yann ARMAND committed Mar 13, 2015
1 parent 9d54af6 commit a1d431c
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 79 deletions.
80 changes: 2 additions & 78 deletions lib/couchrest/model/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,15 @@ 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

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
Expand Down Expand Up @@ -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
81 changes: 81 additions & 0 deletions lib/couchrest/model/associations/collection_of_proxy.rb
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions lib/couchrest_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/assocations_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a1d431c

Please sign in to comment.