Undeterministically I got a nil
error on saving the object caused by the random order of hash elements of the params hash.
class Feedback
belongs_to :user
def role=(value)
@role = value
self.email = find_email_by_name(user.name)
end
end
This piece of code works well until the object params hash contains a second element when it is updated like this:
@feedback.update_attributes!(params[:feedback])
Now it is no longer ensured that user
was set before name
was set. If the name setter is called before the user setter you will receive an error (no method #email for nil).
Workaround 1: Don't use clever setters
Don't write clever setters. Set inferred attributes before validation instead:
before_validation :set_email_from_name
The callback before_validation
happens after all setters happened.
Workaround 2: Hack the attributes setter
This solution should only be used if you work on a large application where a lot of code depends on the indeterministic behavior above, and it would be too much work to refactor the whole app for a small change.
Using the attached trait you can say
does 'priority_attributes', %w[user_id other_attribute]
This makes sure that user_id
and other_attribute
are set before any other attributes.