
"has n, :through..." does not allow saving of model
Reported by Bobby Calderwood | July 26th, 2008 @ 06:56 PM
class Taggable
include DataMapper::Resource
property :id, Integer, :serial => true
has n, :taggings
has n, :tags, :through => :taggings
end
class Tagging
include DataMapper::Resource
property :id, Integer, :serial => true
belongs_to :taggable
belongs_to :tag
end
class Tag
include DataMapper::Resource
property :id, Integer, :serial => true
has n, :taggings
has n, :taggables, :through => :taggings
end
taggable = Taggable.new
taggable.tags
taggable.save
Trying to access the remote association and then saving raises this strange error:
DataMapper::Associations::ImmutableAssociationError: You can not modify this assocation
from /Library/Ruby/Gems/1.8/gems/dm-core-0.9.3/lib/dm-core/associations/one_to_many.rb:247:in `assert_mutable'
from /Library/Ruby/Gems/1.8/gems/dm-core-0.9.3/lib/dm-core/associations/one_to_many.rb:199:in `save'
from /Library/Ruby/Gems/1.8/gems/dm-core-0.9.3/lib/dm-core/resource.rb:272:in `hookable__save_nan_before_advised'
from /Library/Ruby/Gems/1.8/gems/dm-core-0.9.3/lib/dm-core/resource.rb:272:in `each'
from /Library/Ruby/Gems/1.8/gems/dm-core-0.9.3/lib/dm-core/resource.rb:272:in `hookable__save_nan_before_advised'
from /Library/Ruby/Gems/1.8/gems/extlib-0.9.3/lib/extlib/hook.rb:294:in `save!'
from /Library/Ruby/Gems/1.8/gems/extlib-0.9.3/lib/extlib/hook.rb:292:in `catch'
from /Library/Ruby/Gems/1.8/gems/extlib-0.9.3/lib/extlib/hook.rb:292:in `save!'
from /Library/Ruby/Gems/1.8/gems/dm-validations-0.9.3/lib/dm-validations.rb:44:in `save'
from (irb):39
Comments and changes to this ticket
-
nicholaides August 24th, 2008 @ 02:52 PM
I just ran into this bug, too. Looks like the logic in OneToMany#assert_mutable (http://github.com/sam/dm-core/tr...) needs to account for :through associations.
-
Kyle Drake November 10th, 2008 @ 06:38 PM
Is anybody looking into this? This is still a problem.
The first error in this script highlights the problem as well:
-
-
kristian November 17th, 2008 @ 01:41 PM
a workaround is
class Tag include DataMapper::Resource property :id, Serial has n, :taggings has n, :tags, :through => :taggings, :mutable => true end
adding this :mutable option.
I think the opposite default for the mutable option would be a better choice. see the patch to see where to fix it (or apply the patch)
-
José Valim November 22nd, 2008 @ 12:33 PM
The patch sent has the line:
@mutable = options.delete(:mutable) || true
That will always return true. You should something like:
@mutable = options[:mutable] ? options.delete(:mutable) : true
Regards, José Valim.
-
Jonathan Stott (namelessjon) November 30th, 2008 @ 09:22 AM
- State changed from new to hold
- Assigned user cleared.
I'm not sure this is an issue.
The through resource may well be some complex item which cannot be created from defaults. On the other hand, if it can, allowing that to happen is a good thing,
-
Dan Kubb (dkubb) December 4th, 2008 @ 03:14 AM
- State changed from hold to confirmed
I can confirm that has n, :through still exhibits this behavior.
However, this is by design until we can work out the cases when the join record can be automatically created vs where it cannot.
If the join record only contains references to both sides of the association, then no problem. If it contains reference AND properties with default values, also no problem. However, in the case where it references both sides AND has a property without a default, we'd still need to throw an exception because it will be impossible for DM to fill in the missing information when creating the join record.
We just need to codify this so that :through associations can be modified in certain situations. This work will be ongoing in the dkubb/dm-core fork over the next couple of months.
-
Dan Kubb (dkubb) January 7th, 2009 @ 04:26 PM
- Assigned user set to Dan Kubb (dkubb)
-
Dan Kubb (dkubb) January 7th, 2009 @ 04:33 PM
- State changed from confirmed to accepted
-
Marcin Kulik January 8th, 2009 @ 05:22 AM
@José Valim
This:
@@@ruby @mutable = options[:mutable] ? options.delete(:mutable) : true
will also return true ALWAYS. options[:mutable] can return "nil" or "false", if it will return false condition will not be met and will choose "true". Better would be: @@@ruby @mutable = options.key?(:mutable) ? options.delete(:mutable) : true
-
Dan Kubb (dkubb) May 28th, 2009 @ 03:27 AM
- State changed from accepted to resolved
I can confirm this issue is resolved in dm-core/next. Attached is a script to demonstrate the fix.
Please Sign in or create a free account to add a new ticket.
With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »