Why doesn't :readonly => true work on a belongs_to association?
I have the fo开发者_StackOverflowllowing model:
class Question < ActiveRecord::Base
belongs_to :user, :readonly => true
end
I would expect that the :readonly => true attribute would prevent the user from being changed i.e.
# assume we've set up user_1, user_2 and question
# and that question.user == user_1
question.user = user_2
question.save
question.reload
question.user == user_2 # true - why?
Why is this true - I expected that :readonly=> true would prevent this attribute from being changed after initial creation? If it doesn't then what does the :readonly option actually do?
EDIT
Using attr_readonly
will give the non-changeability (immutability?) that I was looking for.
class Question < ActiveRecord::Base
belongs_to :user
attr_readonly :user_id
end
The only problem with it is that it never raises an exception when you try to change the attribute so it's easy to get bugs out of silent fails.
From the doc,
:readonly
If true, the associated object is readonly through the association.
So I suppose that prevents you from doing things such as
question.user.name = 'Hacked'
But let you continue to modify the relation itself.
like @christianblais said, it only affects changing the properties of the object, not replacing it.
to prevent that redefine user= in your model
class Question < ActiveRecord::Base
belongs_to :user, :readonly => true
def user=(new_user)
if self.user.nil?
write_attirbute :user_id , new_user.id
else
return false # or raise your prefrence
end
end
or you could eliminate the conditional and make it always raise an exception, then initialize it with new or create, / update attributes
as far as belongs_to refers to an id-column def user=(new_user) will not fire but def user_id=(new_user_id) will do! So the example would be:
class Question < ActiveRecord::Base
belongs_to :user, :readonly => true
def user_id=(new_user_id)
if self.user.nil?
write_attribute :user_id , new_user_id
else
return false # or raise your preference
end
end
end
Tested here on Rails4 and ruby 1.9.3
精彩评论