0

I have an after_initialize method that I only want to call if I'm not updating a record. For example, something like the following:

after_initialize :set_some_name, :unless => :updating?

For example, Task.find(123).title should call the after_initialize method. Task.find(123).save!(:title => "something") should not call the after_initialize method.

Of course the "updating?" method doesn't exist in Rails. Is there an equivalent method or a way to do so?

Bonifacio2
  • 3,405
  • 6
  • 34
  • 54
sjsc
  • 4,552
  • 10
  • 39
  • 55
  • after_initialize is called before you save the record, so what do you mean? – Yossi Shasho Mar 27 '14 at 16:58
  • 1
    after_initialize is also called when you find a record - for example, Task.find(123). Is there away to only use it for finding a record and not before saving a record? – sjsc Mar 27 '14 at 16:59
  • true, its called also when retrieving a record, but not before saving a record, so i still don't understand what you need. If you mean that you want `set_some_name` to be triggered only on a persisted record, you can use the method `.new_record?` – Yossi Shasho Mar 27 '14 at 17:01
  • possible duplicate of [Rails after\_initialize only on "new"](http://stackoverflow.com/questions/9610277/rails-after-initialize-only-on-new) – Uelb Mar 27 '14 at 17:03
  • Sorry for the confusion :) For example, if the record already exists, and you update it, after_initialize will be called (which I don't want). To be clearer, I'm trying to do something like: "after_initialize :set_some_name, :unless => :updating?" – sjsc Mar 27 '14 at 17:05
  • You can place all your needed staff into constructor method, don't you? It is called only for records not being found in db, but created via `.new()`. –  Mar 27 '14 at 17:13
  • so I think you'd want to use the `new_record?` method: `after_initialize :set_some_name, if: lambda { self.new_record? }` – Yossi Shasho Mar 27 '14 at 17:15
  • Yossi, thanks for trying to help :) I particularly want to use the after_initialize for existing records too (except when I'm updating the record). For example, Task.find(123).title should call the after_initialize method. Task.find(123).save!(:title => "something") should *not* call the after_initialize method. Is there a way to do that in Rails? – sjsc Mar 27 '14 at 17:20
  • Thanks Arantir :) Do you know have an example of a constructor method to do so? I googled but have no idea where to start. – sjsc Mar 27 '14 at 17:22
  • @sjsc, `initialize` method is a constructor in Ruby. And, as I know, Rails doesn't call it (in case of ActiveRecord) when retrieving records from db. Default `initialize` takes a hash of model fields to be assigned, so you may want to call `super` to execute parent's constructor method as well before your code. –  Mar 27 '14 at 17:35
  • Can you explain why you don't want to call the callback on save? – Doguita Mar 27 '14 at 17:41
  • @sjsc, after your edit I'm finally confused. Rails doesn't know what you want to do further at the moment you're calling `find()`. It looks like you want to override attributes attributes accessors to do what you want when you read some field's value. –  Mar 27 '14 at 17:43
  • @Bulezim, I want to set a record's value without saving it (since I want to keep pre-existing values). The value is set based on a condition (for example, setting a record's price based on today's selling price, without overwriting the original price in db) – sjsc Mar 27 '14 at 17:54
  • 1
    @sjsc, if you want to get, for example, `price` with some special conditions you can just override it's getter (simply define `price` method and return modified price). Rails doesn't call those methods while persisting records to db. –  Mar 27 '14 at 18:04
  • 1
    @sjsc If I understood you only need to override the attribute reader. – Doguita Mar 27 '14 at 18:04
  • Awesome! That's a far better solution than how I solved it :) Thank you Arantir and Belezim!! – sjsc Mar 27 '14 at 18:09

2 Answers2

8

I think you are looking for this method :

http://apidock.com/rails/ActiveRecord/Base/new_record%3F

In your after_initialize function, you can then check if the record has already been saved before doing your treatment.

Maybe

after_initialize :set_some_name, if: :new_record?
Uelb
  • 3,947
  • 2
  • 21
  • 32
  • Sorry about the confusion. I meant "saving" should take into account "updating" as well. I updated the question to make it clearer, meaning that after_initialize should not be called if I'm updating a record. – sjsc Mar 27 '14 at 17:08
1

I solved it like so :)

after_initialize :set_alternative_title, :unless => :name_is_alternative_title?

def set_alternative_title
  self.title = "Alternative title"
end

def name_is_alternative_title?
  self.title == "Alternative title"
end
sjsc
  • 4,552
  • 10
  • 39
  • 55