Reputation: 12455
I have 2 models
class Variant < ActiveRecord::Base
belongs_to :product
with_options :if => :is_active? do |p_active|
p_active.validates :avatar, :presence => true
end
with_options :if => :isnt_diavoleria? do |p_active|
p_active.validates :color, :presence => true
end
def is_active?
self.product.active
end
def isnt_diavoleria?
a = (self.is_active? and self.product.section_id != 5)
a
end
end
class Product < ActiveRecord::Base
has_many :variants, :autosave => true
accepts_nested_attributes_for :variants
end
If i change the attribute section_id or active of a product and save, the validations of the model variant are executed with the old values of section_id and active. Why?
How can i do the validations with the new values?
Upvotes: 2
Views: 204
Reputation: 84114
The problem is that by default a pair of has_many
and belongs_to
associations don't know that they are the inverse of each other. So when you
product.section_id = 23
product.save
then inside your validation, the variant goes
self.product
and actually fetches that from the database again, which obviously doesn't have your unsaved change.
You should be able to fix this by adding the :inverse_of
flag to your associations, i.e.
class Variant < AR::Base
belongs_to :product, :inverse_of => :variants
end
class Product < AR::Base
has_many :variants, :inverse_of => :products
end
One day rails will have an identity map which should make this sort of stuff less error prone (it is in rails 3.1 but disabled because of subtle associated bugs if i remember correctly)
Upvotes: 3
Reputation:
You probably need to do what @thoferon is suggesting (assuming you aren't doing taking nested attributes for products or something) or make sure all changes to the product are happening through the association object so it is up-to-date.
Upvotes: 0
Reputation: 5001
Maybe you are modifying a product through another Ruby object. The product referenced by the variant is still holding the old values. I don't know if this is what you're doing but it could be the case.
A solution could be to reload the product before validation.
class Variant
before_validation do
self.product.reload
end
end
Upvotes: -1