AntonKrutikov
AntonKrutikov

Reputation: 53

Ruby DataMapper not saving property set in before hook

class Order
  include Datamapper::Resource

  property :birthday_day, String  
  property :birthday_month, String
  property :birthday_year, String
  property :birthday, Date

  before :save do
    @birthday = Date.new(@birthday_year.to_i, @birthday_month.to_i, @birthday_day.to_i)
  end
end

It's a part of model, but it's enouth. When save field (from irb or from sinatra application) :birthday not save in DB. But in irb, i see object, where :birthday exist and it Date format. When change field manual (from irb): f.birthday = Date.new f.save In object and in DB result appear (in obj as Date obj, in DB as "2010-2-3")

Help me please to understand, what wrong with before in model.

Sorry for my not good enlish.

Upvotes: 2

Views: 1338

Answers (2)

Yuri Gadow
Yuri Gadow

Reputation: 1813

DataMapper documentation recommends #attribute_set

Sets the value of the attribute and marks the attribute as dirty if it has been changed so that it may be saved. Do not set from instance variables directly, but use this method.

In your case:

before :save do
  set_attribute(:birthday => Date.new(self.birthday_year.to_i, self.birthday_month.to_i, self.birthday_day.to_i))
end

For what it's worth, unless I needed to use all the fields in SELECT criteria, I would save either the integer fields or the date, not both:

class Order
  include Datamapper::Resource

  property :birthday, Date
end

# change month
o = Order.create(:birthday => Date.new(...))
o.update(:birthday => Date.new(o.birthday.year, new_month, o.birthday.mday))

Or

class Order
  include Datamapper::Resource

  property :birthday_day, String  
  property :birthday_month, String
  property :birthday_year, String

  def birthday
    if self.birthday_day && self.birthday_month && self.birthday_year
      Date.new(self.birthday_day, ...)
    end
  end
end

Upvotes: 3

solnic
solnic

Reputation: 5743

You should use property mutator method. Setting the ivar doesn't trigger dirty tracking. Just do this:

self.birthday = Date.new(birthday_year.to_i, birthday_month.to_i, birthday_day.to_i)

Also it would be better to use Integer as the property type for year, month and day.

Upvotes: 4

Related Questions