I have a rather complex business logic in a model with associations. I want to allow users to save incomplete (invalid) models for future completion. In my controller, I therefore call instance.save(validate: false)
.
Here are the 3 models, that I have extracted from my application. The models may seen overblown, since I extracted only the relevant part.
1) Container
model:
class Container < ApplicationRecord
Languages = %w(fr en de it es)
belongs_to :name, class_name: "Name", foreign_key: :name_id
accepts_nested_attributes_for :name
validates :name, presence: true
# create an empty model
def self.create_new
c = Container.new
c.name = Name.new
c.name.save
Languages.each do |l|
c.name.translations << NameItem.new(language: l, text: "")
end # Languages.each do |l|
c.description = Description.new
c.description.save
Languages.each do |l|
c.description.translations << DescriptionItem.new(language: l, text: "")
end # Languages.each do |l|
c
end
end
2) Name
model:
class Name < ApplicationRecord
has_many :translations, class_name: "NameItem", foreign_key: :parent_id
accepts_nested_attributes_for :translations
end
3) NameItem
model:
class NameItem < ApplicationRecord
validates :language, presence: true
validate :text_validation
private
def text_validation
return if language.nil?
errors.add(:text, :blank_text, language: language) if text.nil? || text.size == 0
end
end
Given the following sequence of instructions, I am at a loss why the last instruction ( instance.valid?
) returns true. It seems to me that the validation callbacks are disabled, but I'm not sure this is the proper diagnostic. Could this be related to the use of accepts_nested_attributes_for
?:
# create an invalid model (since empty)
instance = Container.create_new
# check that this instance is invalid
instance.valid? # returns false, this is the expected behavior
# save the model, skipping the validations
instance.save(validate: false)
# now instance.valid? will always return true, because it will
# skip the validations. How can I restore the callbacks ?
instance.valid? # returns true, but this is not the desired behavior,
# hence my question
I tried to disable and re-enable the callbacks with instructions like the following, but to no avail.
[:create, :save, :update].each do |action|
Container.skip_callback(action)
end
[:create, :save, :update].each do |action|
Container.set_callback(action)
end
So my question is: after having invoked instance.save(validate: false)
, what instructions do I need to run so that instance.valid?
does indeed perform the validation checks again and return false ?
Running save(validate: false)
doesn't leave callbacks turned off, you must have some other code that runs after save that makes the record pass validation.
Check your before/after_save
callbacks, and maybe post the model.
Edit:
Using nested attributes for new records will give you validation trouble, it really works best with existing records as the association doesn't exist properly on a new record. There's a good explanation of this and a workaround in the last paragraph of this answer .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.