Validates_presence_of calls after_initialize to call with strange i

I had this model that worked perfectly:

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

I added this line

validates_uniqueness_of :measured_on, :scope => :user_id

and he began to give an error while checking. Not a validation error, but a Ruby error:

>> w.valid?
ActiveRecord::MissingAttributeError: missing attribute: measured_on
    from /Users/pupeno/Projects/sano/app/models/weight.rb:8:in `after_initialize'

I put the debugger expression in after_initialize and I noticed something unexpected. When I create a new weight, it works as expected, and the on_initialize self-object is the expected weight:

>> 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>

When did I start w.valid? this is strange. after_initialize is called again, I'm not sure why, and the object itself did not expect anything:

>> 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)

It seems that another Weight object was created without any attributes, but with an identifier. Any ideas why? Is this a bug or an expected behavior? Am I doing something wrong by setting measure_on to after_initialize?

, , - ,

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

.

+5
3

, , . . , .

, , - rails "select id from tablename", , . , , , "id". , "" , id.

, , , , , , .

, , , after_initialise ActiveRecord:: MissingAttributeError. , , , .

, , .

def after_initialize
  begin
    # ... updates here
    # self.unique_reference = UUIDTools::UUID.random_create.to_s
  rescue ActiveRecord::MissingAttributeError
  end
end

:

def after_initialize
  if self.has_attribute? :measured_on
    self.measured_on ||= Date.today
  end
end
+6

Rails # 3165. , , .

, , , . , , , , :

validates_uniqueness_of :email, :scope => :library_id

def after_initialize
  self.status ||= "Invited"
end

"MissingAttributeError", , validates_uniqueness_of. :

def after_initialize
  self.status ||= "Invited" if new_record?
end

, , .

+2

validates_uniqueness_of . ActiveRecord . , /, , , . , after_initialize.

The work around is to change the @attributes hash directly instead of relying on accessors:

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
    @attributes["measured_on"] ||= Date.today
  end
end
0
source

All Articles