Mam ten model, który działa dobrze:validates_presence_of powoduje after_initialize nazywać siebie z dziwnym
class Weight < ActiveRecord::Base
belongs_to :user
validates_presence_of :weight, :measured_on
attr_accessible :weight, :measured_on
def after_initialize
self.measured_on ||= Date.today
end
end
dodałem mu tę linię
validates_uniqueness_of :measured_on, :scope => :user_id
i zaczęło rzucać błąd na uprawomocnienie. Nie jest to błąd, ale błąd walidacji Ruby:
>> w.valid?
ActiveRecord::MissingAttributeError: missing attribute: measured_on
from /Users/pupeno/Projects/sano/app/models/weight.rb:8:in `after_initialize'
Włożyłam oświadczenie debuggera w after_initialize i zauważyłem coś nieoczekiwanego. Kiedy tworzę nową wagę to działa zgodnie z oczekiwaniami, a obiekt na siebie after_initialize jest spodziewana waga:
>> w = Weight.new
/Users/pupeno/Projects/sano/app/models/weight.rb:9
self.measured_on ||= Date.today
(rdb:1) p self
#<Weight id: nil, user_id: nil, weight: nil, measured_on: nil, created_at: nil, updated_at: nil>
(rdb:1) c
=> #<Weight id: nil, user_id: nil, weight: nil, measured_on: "2009-11-22", created_at: nil, updated_at: nil>
kiedy biegnę w.valid? robi się dziwnie. after_initialize nazywa się znowu, nie jestem pewien, dlaczego, a obiekt ma nic samo się spodziewałem:
>> w.valid?
/Users/pupeno/Projects/sano/app/models/weight.rb:9
self.measured_on ||= Date.today
(rdb:1) p self
#<Weight id: 1>
(rdb:1) p self.inspect
"#<Weight id: 1>"
(rdb:1) p self.class
Weight(id: integer, user_id: integer, weight: float, measured_on: date, created_at: datetime, updated_at: datetime)
(rdb:1) p self.measured_on
ActiveRecord::MissingAttributeError Exception: missing attribute: measured_on
(rdb:1)
Wydaje się, że kolejnym celem Waga został stworzony bez żadnych atrybutów, ale Set ID. Jakieś pomysły, dlaczego? Czy to błąd, czy oczekiwane zachowanie? Czy robię coś nie tak, ustawiając measure_on on after_initialize?
Moje bieżące obejście, w przypadku, ktoś jest ten sam problem, to
class Weight < ActiveRecord::Base
belongs_to :user
validates_presence_of :weight, :measured_on
validates_uniqueness_of :measured_on, :scope => :user_id
attr_accessible :weight, :measured_on
def after_initialize
if self.has_attribute? :measured_on
self.measured_on ||= Date.today
end
end
end
ale chciałbym mieć odpowiednie rozwiązanie.
OP zredagował moją odpowiedź i utworzył sekcję "has_attribute?: Measured_on" - Nie jestem w 100% pewien, że zgadzam się z nią po spojrzeniu na źródło rails - podejrzewam, że działa z powodu efektu ubocznego, a nie przez -projekt). Nie cofam tej części odpowiedzi, bo kto wie, może komuś pomóc. – oskarpearson
Ugryziony przez to dzisiaj. Ten post i twoja odpowiedź uratowały mi bekon. Zapomniałem, że jedną z wad języków dynamicznych jest to, że nie zawsze mają te same atrybuty w obiekcie ... co może być dobre, ale także złe :) –
Dostałem dzisiaj ukąszenie. Wow, to zostało opublikowane tutaj w 2009 roku? Jestem pod wrażeniem, że od tak dawna się nie odblokował. – Trejkaz