Skip to content

Commit

Permalink
[back_assignments] add reverse_association on collections
Browse files Browse the repository at this point in the history
  • Loading branch information
yann ARMAND committed Mar 13, 2015
1 parent 1fc6cf7 commit 9d54af6
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 20 deletions.
33 changes: 15 additions & 18 deletions lib/couchrest/model/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -247,49 +247,37 @@ def initialize(array, property, parent)
end

def << obj
check_obj(obj)
casted_by[casted_by_property.to_s] << obj.id
obj.set_back_association(casted_by, casted_by.class.name)
casted_by.register_dirty_association(obj)
add_to_collection_with(:<<, obj)
super(obj)
end

def push(obj)
check_obj(obj)
casted_by[casted_by_property.to_s].push obj.id
obj.set_back_association(casted_by, casted_by.class.name)
casted_by.register_dirty_association(obj)
add_to_collection_with(:push, obj)
super(obj)
end

def unshift(obj)
check_obj(obj)
casted_by[casted_by_property.to_s].unshift obj.id
obj.set_back_association(casted_by, casted_by.class.name)
casted_by.register_dirty_association(obj)
add_to_collection_with(:unshift, obj)
super(obj)
end

def []= index, obj
check_obj(obj)
casted_by[casted_by_property.to_s][index] = obj.id
obj.set_back_association(casted_by, casted_by.class.name)
casted_by.register_dirty_association(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)
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)
obj.set_back_association(nil, casted_by.class.name, casted_by_property.options[:reverse_association])
casted_by.register_dirty_association(obj)
super
end
Expand All @@ -300,6 +288,15 @@ 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)
Expand Down
1 change: 1 addition & 0 deletions spec/fixtures/models/parent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ class Parent < CouchRest::Model::Base
belongs_to :lives_with, :class_name => :parent, :reverse_association => :lives_with

collection_of :children, :class_name => 'Kid'
collection_of :pets , :reverse_association => :owner
end
39 changes: 37 additions & 2 deletions spec/unit/assocations_dual_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

let(:father) { Parent.create(name: 'Bob')}
let(:can_fly){ SuperPower.create(description: 'Can fly when there is no cloud')}
let(:mummy) { Parent.create( name: 'Claire')}
let(:kid) { Kid.create( name: 'Vladimir')}
let(:mummy) { Parent.create(name: 'Claire')}
let(:kid) { Kid.create( name: 'Vladimir')}
let(:dog) { Pet.create( name: 'Valdo' )}

describe 'of type belongs_to' do
context 'with the other side also belongs_to (1-1)' do
Expand Down Expand Up @@ -72,6 +73,12 @@
father.children << kid
kid.dad.should eq(father)
end
context 'when reverse_association is specified' do
it 'should populate the belongs_to property' do
father.pets << dog
dog.owner.should eq(father)
end
end
describe 'when object is saved' do
it 'should also save other side' do
father.children << kid
Expand All @@ -86,6 +93,12 @@
father.children.push kid
kid.dad.should eq(father)
end
context 'when reverse_association is specified' do
it 'should populate the belongs_to property' do
father.pets.push dog
dog.owner.should eq(father)
end
end
describe 'when object is saved' do
it 'should also save other side' do
father.children.push kid
Expand All @@ -100,6 +113,10 @@
father.children.unshift kid
kid.dad.should eq(father)
end
it 'should populate the belongs_to property' do
father.pets.unshift dog
dog.owner.should eq(father)
end
describe 'when object is saved' do
it 'should also save other side' do
father.children.unshift kid
Expand All @@ -114,6 +131,10 @@
father.children[3]= kid
kid.dad.should eq(father)
end
it 'should populate the belongs_to property' do
father.pets[3] = dog
dog.owner.should eq(father)
end
describe 'when object is saved' do
it 'should also save other side' do
father.children[4] = kid
Expand All @@ -129,6 +150,13 @@
father.children.pop
kid.dad.should be_nil
end
context 'specifying reverse association' do
it 'should set nil the belongs_to property' do
father.pets.push dog
father.pets.pop
dog.owner.should be_nil
end
end
describe 'when object is saved' do
it 'should also save other side' do
father.children.push kid
Expand All @@ -146,6 +174,13 @@
father.children.shift
kid.dad.should be_nil
end
context 'specifying reverse association' do
it 'should set nil the belongs_to property' do
father.pets.push dog
father.pets.shift
dog.owner.should be_nil
end
end
describe 'when object is saved' do
it 'should also save other side' do
father.children.push kid
Expand Down

0 comments on commit 9d54af6

Please sign in to comment.