I’ve got a simple user: **Edited a bit for clarity, and on Sam’s suggestion
class User < ActiveRecord::Base
# <snip other attribs>
has_many :handles
has_one :active_handle, :class_name => "Handle"
validates_each :active_handle, :allow_nil => true do |record, attr, value|
record.errors.add attr, "is not owned by the correct user" unless record.handles.include?(value)
end
end
And a handle model:
class Handle < ActiveRecord::Base
belongs_to :user
attr_accessible :user_id
validates :user_id,
:presence => true,
:numericality => true
attr_accessible :name
validates :name,
#etc...
end
Now I’d like to check, when setting the User.active_handle association, that the handle is owned by the correct Handle.user_id. I’ve tried to do this in a custom validation, and also in a validate method on the User model. Both ways, it does the exact opposite of what I want, it sets the user_id of handle to the User doing the checking.
I’m at the end of my rope, clearly I don’t understand something, and google isn’t getting me anywhere I haven’t already been.
ETA: I have also tried to manipulate the has_one association with conditions, that seems to fail too…
has_one :active_handle,
:class_name => "Handle",
:conditions => ['user_id =?', '#{self.id}']
I’d take a different approach to this problem; the double link is messy, and hard to maintain, as you’ve discovered. Instead, I’d put an active flag in the handle model, and order the
:active_handleassociation on that flag:Now there’s only one link, and it’s the same link that’s already in place to establish the plain
has_many :handlesassociation (namely, theuser_idattribute in the Handle model). Finding the active handle in now just a matter of finding the User’s first Handle with the active flag set. And I’d use:orderrather that:conditions, as that’ll give you a nice fallback: If no Handle for that user has the active flag set, Rails’ll pick one to use as a default.And then, in your handle model, you can have a fairly simple activate function:
Or, if you wanted to be able to call something like
user.handles.activate(hdl), you could put something similar as an association extension. Oruser.active_handle = hdl. Or…Hope this helps!