Weird result for a custom attr reader!

Hi all,

I am having a weird problem reading a value from my model. basicaly, I
have these two models:

class Category < ActiveRecord::Base
acts_as_tree :order => “name”
belongs_to :item_type
has_many :specific_category_names
end

and

class SpecificCategoryName < ActiveRecord::Base
set_table_name “Specific_category_names”

has_many :products
belongs_to :brand
belongs_to :category

#if there is no name, use the name of the category
def name
if @name.nil?
category.name
else
@name
end
end
end

Then, I start to play in the console… In my DB,
specific_category_names.name for canon is = “WIDER” and the
corresponding category.name = “wide”

canon = Brand.find_by_name(“Canon”)
=>#<Brand:0x2429784 @attributes={“name”=>“Canon”, “id”=>“1”}>

Thats OK

canon.specific_category_names.first
=>#<SpecificCategoryName:0x24235a0 @attributes={“name”=>“WIDER”,
“brand_id”=>“1”, “id”=>“1”, “description”=>nil, “category_id”=>“7”}>

then the strange things:

canon.specific_category_names.first.name
=> “Wide”
This should be “WIDER” since that the value from specific_category_name
and it is not null!!!

And even weirder, if I ask again for the specific_category_name array, I
will get the same one as before but this time there is a @category
added…

canon.specific_category_names.first
=> #<SpecificCategoryName:0x24235a0 @attributes={“name”=>“WIDER”,
“brand_id”=>“1”, “id”=>“1”, “description”=>nil, “category_id”=>“7”},
@category=#<Category:0x241557c @attributes={“name”=>“Wide”, “id”=>“7”,
“description”=>nil, “item_type_id”=>“1”, “parent_id”=>“2”}>>

Anyone can tell me what I am doing wrong?!? This is puzzling me to no
end!

Thanks

“Alain Pilon” [email protected] wrote in
message news:[email protected]

Hi all,

I am having a weird problem reading a value from my model. basicaly, I
have these two models:
#if there is no name, use the name of the category

def name
if @name.nil?
category.name
else
@name
end
end
end

ActiveRecord attributes aren’t stored as instance variables in the model
so
you don’t need the @. I’m pretty sure AR uses method_missing to return
attribute values, try something like this:

def name
tmp = super
return tmp || category.name
end

I think (ie untested) you should be able to use

def name
self[:name] || category.name
end

See “Overwriting default accessors” in
http://api.rubyonrails.com/classes/ActiveRecord/Base.html

Chris

self[:name] is essentially the rails equivalent of @name.

if you tried to use self.name, you would invoke the name method on the
current instance, from within… the name method on the current
instance; resulting in an infinite loop

Thx Chris, that solved my problem. But why use self[:name] and not
self.name ???

On 7/20/06, Chris R. [email protected] wrote:

self[:name] is essentially the rails equivalent of @name.

In ruby, this isn’t necessarily true, as @name, self[:name] and
self.name can all be different:

irb(main):001:0> class A
irb(main):002:1> def initialize
irb(main):003:2> super
irb(main):004:2> @p = 2
irb(main):005:2> end
irb(main):006:1> def [] y
irb(main):007:2> @x ||= {}
irb(main):008:2> @x[y]
irb(main):009:2> end
irb(main):010:1> def p
irb(main):011:2> 1
irb(main):012:2> end
irb(main):013:1> def test
irb(main):014:2> puts “@p = #{@p}”
irb(main):015:2> puts “self.p = #{self.p}”
irb(main):016:2> puts “self[:p] = #{self[:p]}”
irb(main):017:2> end
irb(main):018:1> def self.test
irb(main):019:2> new.test
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):022:0> A.test
@p = 2
self.p = 1
self[:p] =
=> nil

For ActiveRecord objects, self[:blah] and self.blah are usually the
same if blah is a column in the associated table (since self.blah will
default to self[:blah]), but that can be (and often is) changed.
However, ActiveRecord doesn’t create @blah instance variables for
columns, AFAIK.

Jeremy