0

I have such model:

class Order < ActiveRecord::Base
  attr_accessible :**** :phone_number, :receiver, :shipping_id, :street, :totalcost, :user_id, :zip, :use_user_data
  attr_accessor :use_user_data
  validates :city, :presence => {:message =>  I18n.t(:city_not_chosen)}
  validates :zip, :presence => {:message =>  I18n.t(:zip_not_chosen)}
  validates :street, :presence => {:message =>  I18n.t(:street__not_chosen)}
  validates :building, :presence => {:message =>  I18n.t(:building_not_chosen)}
  validates :phone_number, :presence => {:message =>  I18n.t(:phone_number_not_chosen)}
  validates :receiver, :presence => {:message =>  I18n.t(:receiver_not_chosen)}
end

As you can see i set in model some field which is non-db field (use_user_data) - virtual attribute...

But how to do, if :use_user_data is false, good and right validate, but when true didn't validate?

i try so:

validates :city, :presence => {:message =>  I18n.t(:city_not_chosen)}, :unless => :use_user_data

and so

with_options :unless => :use_user_data do |order|
    order.validates :city, :presence => {:message =>  I18n.t(:city_not_chosen)}
  end

but it doesn't help me... Why?

Also my form:

= form_for @order do |f|
  %div
    = f.label :use_user_data , "Использовать данные вашего профиля*: "
    = label :use_user_data , "Да"
    = f.radio_button :use_user_data, true, :required => true, :id => "use_user_data", :checked => true
    = label :use_user_data , "Нет"
    = f.radio_button :use_user_data, false, :required => true, :id => "dont_use_user_data"

Also when i write

validates :city, :presence => {:message =>  I18n.t(:city_not_chosen)}, :if => :use_user_data

i get validation messages... But how to do only if false? And why my solution didn't work?

brabertaser19
  • 5,678
  • 16
  • 78
  • 184
  • Not related to your question, but you can clean up your many `:message` parameters using *implict* lookups: http://stackoverflow.com/a/2859275/23368 – Daniel Rikowski Jan 16 '13 at 13:01
  • @DanielRikowski and how to change.... didn't unserstand, delete message? and? – brabertaser19 Jan 16 '13 at 13:58
  • 1
    Just set up your locale files the way described in the Rails I18n guide at "Error Message Scopes" (http://guides.rubyonrails.org/i18n.html#error-message-scopes) and Rails will automatically use them. – Daniel Rikowski Jan 16 '13 at 15:18

2 Answers2

2

The form passes "true" or "false" string to the object, not boolean true or false. Since it's a virtual attribute, no typecasting performed. In Ruby, both "true" and "false" are true, so you need to use something to typecast the value

with_options :unless => Proc.new{ |a| a.use_user_data == 'true' } do |order|
  order.validates ...
end

Or

with_options :unless => :use_user_data? do |order|
  order.validates ...
end

def use_user_data?
  use_user_data == 'true'
end
dimuch
  • 12,728
  • 2
  • 39
  • 23
0

You need to put your :if or :unless conditions in a lambda or Proc.

validates ..., :if => Proc.new { |a| a.use_user_data === false }

This causes the check against :use_user_data to not be evaluated until the above validates line is executed during validation (the Proc is passed as the value to the :if or :unless option to be evaluated by Rails). The Proc will receive the current model attributes as an argument, allowing you to check those attributes (in this case, :use_user_data being false).

deefour
  • 34,974
  • 7
  • 97
  • 90