2012-04-03 11 views
0

Ich bin neu bei Rails und Ruby. Aus meiner Sicht habe ich 2 Radioknöpfe, die fragen, ob die Person in den USA wohnhaft ist. Wenn dies der Fall ist, wird eine Statusauswahl angezeigt. Wenn dies nicht der Fall ist, wird eine Länderauswahl angezeigt.Wie validiere ich ein einzelnes Attribut von einem verschachtelten Objekt

Ich versuche zu bestätigen, dass ein Staat ausgewählt wurde, wenn die Person in den USA wohnhaft ist.

Wie kann ich eine Validierung erstellen und auf den Status aus dem address_attributes zugreifen?

Hier ist mein Modell:

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 

Dies sind die relevanten Parameter gesendet werden:

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

Antwort

0

+1 zu @Velles für die Hilfe in mir in die richtige Richtung zeigen. Ich beantworte meine eigene Frage, weil ich @Velles Beispiel ein wenig ändern musste, um es zur Arbeit zu bringen, und ich möchte, dass andere Leute die volle Lösung sehen.

Da ich attr_accessor als ein virtuelles Attribut verwende, wenn der True/False-Wert von der Optionsschaltfläche kommt, wird es als Zeichenfolge gespeichert. Daher wird self.resident = "false" als wahr ausgewertet.

Sie können self.resident == 'false' tun oder zu einem boolean konvertieren und ein neues self.resident hinzufügen? Methode. Ich habe mich für Letzteres entschieden.

Die boolean Umwandlung kam von this blog post, fügen Sie in einer Datei in config/initializers

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 

Meine letzte Code ist:

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 

Bitte lassen Sie mich wissen, ob es eine bessere 'Schienen' Weg, dies zu tun!

1

Sie benötigen eine angepasste Validierungsmethode.

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

Sie können stattdessen mit validates_inclusion_of aussortieren.

Ruby-API sagt:

Wenn Sie das Vorhandensein eines boolean Feld validieren möchten (wo die wirklichen Werte sind wahr und> false), möchten Sie verwenden validates_inclusion_of: field_name,: in => [wahr falsch].

Dies liegt an der Art, wie Objekt leer ist? behandelt boolesche Werte: false.blank? # => Wahr.

Verwandte Themen