Overriding initialize in active_record Model or after_initialize

Hi,

I am trying to set initial process when instantiating model by overriding initialize() method which takes arguments. The initialize() method overrides the parent ActiveRecord::Base class’s by taking arguments and assign arguments to its instance variables.

class Product < ActiveRecord::Base

def initialize(item = nil)

super

# and then process to assign variables from item argument to instance variables

# ....

end

In order to fully leverage ActiveRecord::Base class functionality, I’m calling super to run the default initialization process (i.e. set up all setter/getter methods). However, the Product class above still can’t find getter/setter methods for its variables. In the meantime, I found the following blog article suggesting use after_initialize instead of overriding Active Record object.

Rails: Don’t override initialize on ActiveRecord objects

http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html

I could not find ways to set arguments for this after_initialize approach.

Can anybody advise should I override initialize() or use after_initialize with some ways to take arguments?

Thanks,

Ryo

Hi,

I am trying to set initial process when instantiating model by
overriding initialize() method which takes arguments. The initialize()
method overrides the parent ActiveRecord::Base class's by taking
arguments and assign arguments to its instance variables.

class Product < ActiveRecord::Base

def initialize(item = nil)
super
# and then process to assign variables from item argument to
instance variables
# ....
end

What does the actual code in there look like? What is the error that
you get ?

Fred

Thanks Fred.

I got the following error.
NoMethodError in ProductsController#search
undefined method `stringify_keys!' for #<Amazon::Element:0x10373c6a8>
/Library/User/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/
base.rb:2731:in `attributes='
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.3/lib/active_record/
base.rb:2434:in `initialize'
/Users/User/Documents/Aptana Studio Workspace/Flatworld/app/models/
product.rb:5:in `initialize'
/Users/User/Documents/Aptana Studio Workspace/Flatworld/app/models/
products.rb:31:in `new'
.... [more]

and actual code for the model class is:

The reason this isn't working is that

super

does not mean 'call the superclass implementation with no
arguments' (which is fine in this case - Active Record just won't set
any attributes). It means 'call the super class implementation with
the same arguments', so you're passing this an amazon search result
object to a method expecting a hash. You can force the superclass to
be called with no arguments by doing super().

I assume that you're trying to set activerecord attributes for the
title and so on. If so, use the accessor functions (ie
self.amazon_asin = ... ). Active Record doesn't store its attributes
in instance variables, so what you're doing won't work.

Lastly while you can make the above work, I think that you'll be
making life for yourself more difficult by requiring that Products be
initialized with an amazon search result object (eg for creating
objects in tests). another approach is to leave initialize alone and
write

class Product < ...

  def self.from_amazon_search_result(item)
    new :amazon_asin => item.get('asin'), :manufacturer => item.get
('itemattributes/manufacturer') , ...
  end
end

Fred

It worked perfect as you suggested using class method
"self.from_amazon_search_result".
Does this mean I am instantiating Product object by this new class
method rather than new()?
Sorry this is new approach to me, and I just would like to know for my
learning.

Active Record doesn't store its attributes in instance variables, so what you're doing won't work.

This was also new to me. I was building it on my belief that every
instance of AR-extending class holds its attributes in instance
variable. I will look for some specs on web just so I learn!

Thanks again Fred!