Haris Krajina
Haris Krajina

Reputation: 15276

attr_accessor, not able to access property

This is probably very stupid question but here we go

class Foo < ActiveRecord::Base
 attr_accessor :group_id
end

From irb

# gets record which has group_id set to 106    
foo = Foo.find(1)
foo.group_id
=> nil

If I go and remove

attr_accessor :group_id

All works as it should

foo = Foo.find(1)
foo.group_id
=> 106

My question is why? Shouldn't attr_accessor create accessor / mutator for property :group_id and that why all should be working. What am I missing?

Update

Good answers bellow, just as explanation for my motivation here is I want to use mass assignment of certain properties (you need this since Rails 3.2.x). For that you need attr_accessible , I find that code is much cleaner that way, of course if used responsibly :)

Upvotes: 1

Views: 2739

Answers (4)

davidrac
davidrac

Reputation: 10738

If you have a column by the name group_id in the table, than ActiveRecord defines the accessor for you. When you overwrite it as you did, your calls simply searches for a regular instance variable named group_id, which returns nil.

Upvotes: 0

Dty
Dty

Reputation: 12273

Looks like group_id is already a property on your Foo object (shown by the fact that it returns 106 when attr_accessor is omitted). By adding attr_accessor you are overriding what's already there and creating a method reader and writer called group_id. The return of the newly defined group_id is nil since you don't define anything.

Conceptually, you're ending up with something like this:

class Foo < ActiveRecord::Base
  def group_id  # overriding previous definition of 'group_id'
    nil
  end
end


Edit:

If your goal is expose properties then yes, use attr_accessible

Upvotes: 4

Alfredo Solano
Alfredo Solano

Reputation: 824

Without the accessor, for sure you have a 'belongs_to :group' in your Foo model, so if you call 'group_id' to an instance of 'Foo' you will get the value of this field.

For instance, if you set an accessor called like that attribute( group_id) it will overwrite the original field and it will return nil, if haven´t assigned any value.

class Foo < ActiveRecord::Base
  attr_accessor :group_id
end

# gets record which has group_id set to 106    
foo = Foo.find(1)
foo.group_id
=> nil
foo.group_id = "wadus"
=> "wadus"
foo.group_id
=> "wadus"

Upvotes: 0

Frost
Frost

Reputation: 11957

This happens because ActiveRecord automatically maps the attributes in your database table to attributes in the actual model. When you add attr_accessor you overshadow the database attribute with you own, newly defined attribute.

Basically, rails automatically defines attr_accessor (or something similar) for all attributes in the corresponding database table.

If you're looking for some way on how to make only certain of your attributes accessible for multi-assignment, you should instead look at attr_accessible.

Upvotes: 4

Related Questions