Ruby-on-rails – Rails validation context

activerecordruby-on-railsruby-on-rails-3validation

I need help with my ActiveRecord model. I have context based validations (mis)using the build-in context options for validations:

validates :foo, :on => :bar, :presence => true

model = Model.new
model.foo = nil
model.valid? # => true
model.save # works as expected

model.valid?(:bar) # => false
model.save(:context => :bar) # fails and returns false

But using my model in a accepts_nested_attributes_for :model and calling parent.save fails (the validation gets called and returns false), any suggestions or solutions?


Still no answer? To explain more about my problem: I have a model called Form which has many Fields. Users should see validation errors on submit, but the form should be saved anyway (with and without errors). There are different types of Fields, each with global validations (to ensure database consistency) and its own specific user-defined validations (to validate user-entered data). So my Fields look someway like that:

 # Global validations, to ensure database consistency
 # If this validations fail, the record should not be saved!
 validates_associated :form, :on => :global
 ...

 # Specific user-defined validations
 # If this validations fail, the record should be saved but marked as invalid. (Which is done by a before_save filter btw.)
 def validate
   validations.each do |validation| # Array of `ActiveModel::Validations`, defined by the user and stored in a hash in the database
     validation.new(:on => :specific).validate(self)
   end
 end

In my controller:

 # def create
 # ...
 form.attributes = params[:form]
 form.save!(:global)
 form.save(:specific)

Is something similar possible in Rails using the built-in functionality? Btw this not my actual code, which is quite complicated. But I hope, you guys will get the idea.

Best Answer

Try conditional validations

class Customer 
  attr_accessor :managing 

  validates_presence_of :first_name
  validates_presence_of :last_name 

  with_options :unless => :managing do |o|
    o.validates_inclusion_of :city, :in=> ["San Diego","Rochester"]
    o.validates_length_of :biography, :minimum => 100 
  end
end

@customer.managing = true
@customer.attributes = params[:customer]
@customer.save