2012-04-03 3 views
0

Я новичок в Rails и Ruby. По моему мнению, у меня есть 2 переключателя, которые спрашивают, является ли человек резидентом США. Если они есть, отображается выбор состояния. Если это не так, отображается выбор страны.как проверить один атрибут от вложенного объекта

Я пытаюсь проверить, было ли выбрано государство, если оно является резидентом США.

Как я могу создать проверку и получить доступ к состоянию из атрибутов address_attributes?

Вот моя модель:

class Person < ActiveRecord::Base 
    has_many :addresses, :as => :addressable 
    has_one :user 

    accepts_nested_attributes_for :user, :allow_destroy => true 
    accepts_nested_attributes_for :addresses 

    attr_accessor :resident 
    attr_accessible :campaign_id, 
        :first_name, 
        :last_name, 
        :user_attributes, 
        :addresses_attributes, 
        :resident 

    validates :first_name, :presence => true 
    validates :last_name, :presence => true 

    validates_presence_of :resident, :message => "must be selected" 

end 

Этих соответствующие параметры, посылаемый:

"resident"=>"true", 
"addresses_attributes"=>{"0"=>{"country_code"=>"", 
"state"=>""}} 

ответ

0

+1 к @VELLes за помощью, указав меня в правильном направлении. Я отвечаю на свой вопрос, потому что мне пришлось немного изменить пример @VelLes, чтобы заставить его работать, и я хочу, чтобы другие люди увидели полное решение.

Поскольку я использую attr_accessor в качестве виртуального атрибута, когда значение true/false входит из переключателя, оно сохраняется в виде строки. Поэтому, если self.resident = "false", он будет оценен как true.

Вы можете сделать self.resident == 'false' или конвертировать в булево и добавить новый self.resident? метод. Я выбрал последний.

Булева преобразования пришли из this blog post, добавьте в файл конфигурации/Инициализаторы

class String 
    def to_bool 
    return true if self == true || self =~ (/(true|t|yes|y|1)$/i) 
    return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i) 
    raise ArgumentError.new("invalid value for Boolean: \"#{self}\"") 
    end 
end 

Мой окончательный код:

validate :check_state_presence 

def resident? 
    resident.to_bool 
end 

def check_state_presence 
if self.resident? && !self.addresses[0].state.present? 
    #the inline version of the error message 
    self.addresses[0].errors.add(:state, "must be selected") 
end 
end 

Пожалуйста, дайте мне знать, если есть лучше «рельсы» способ сделать это!

1

Вам нужны методы пользовательских проверок.

validate :check_state_presence 

    def check_state_presence 
    if self.resident && !self.addresses.state.present? 
     self.errors[:base] << "You need to Select State if you are a US resident." 
    end 
    end 
1

Вместо этого вы можете отсортировать его с помощью validates_inclusion_of.

Рубин API говорит:

Если вы хотите, чтобы проверить наличие булева поля (где реальные значения истинны и> ложь), вы хотите использовать validates_inclusion_of: field_name,: в => [true, false].

Это связано с тем, что объект # пуст? обрабатывает логические значения: false.blank? # => true.

Смежные вопросы