Referencing a non-ActiveRecord attribute

I am trying to access a model's attribute that does not have a column in the model's corresponding table. It exists only through an attr_accessor:

class Widget < ActiveRecord::Base   attr_accessor :attribute_not_in_db end

I can access the attribute directly:

w = Widget.new(:attribute_not_in_db => "foo") w.attribute_not_in_db

=> "foo"

However, I can't seem to access it other ways:

attr_symbol = :attribute_not_in_db w[attr_symbol]

=> nil

attr_name = "attribute_not_in_db" w[attr_name]

=> nil

w.read_attribute(attr_symbol)

=> nil

w.read_attribute(attr_name)

=> nil

This is probably rather basic, but my searching hasn't turned up the answer. Any guidance would be apprecited.

thx.

One way to dynamically add attributes to some model object on the fly is to just directly add the new key(s)/val(s) to the model instance's attributes:

$ ./script/console Loading development environment (Rails 2.2.2)

test = Test.find(:first)

=> #<Test id: 1, name: "Abe">

test.attributes.keys

=> ["id", "name"]

test["favorite_color"] = 'blue'

=> "blue"

test.attributes.keys

=> ["id", "favorite_color", "name"]

test.favorite_color

=> "blue"

Another way, assuming the purpose is to add additional attribs coming from a db qry, ... Note that any additional attribs returned from a db query will be automatically added to the returned model ob(s):

test2 = Test.find_by_sql("select *, 'blue' as favorite_color from tests order by id limit 1").first

=> #<Test id: 1, name: "Abe">

test2.attributes.keys

=> ["id", "favorite_color", "name"]

test2.favorite_color

=> "blue"

Note that neither of the above requires any accessor-related code in your model ob (unless you want/need it for other purposes):

$ cat app/models/test.rb class Test < ActiveRecord::Base end

Jeff

Thanks for the response. I'm afraid my initial post wasn't clear as it could be. I am trying to find a specific syntax to access an accessor getter/setter using a variable, in this example "x":

user = User.new(:login=> "foo", :password=>"bar") # :password is not a column in the db, but defined in the model using "attr_accessor :password" (see initial post)

[:login, :password].each do |x|     original_val = user     user = some_new_val     do_some_test(user)     user = original_val end

It works for :login which is an actual attribute of User. However, since :password was created as an attribute accessor (def password & def password=), the syntax "user[e]" doesn't work. I'm looking for a way to make this work while keeping "attr_accessor :password"

I hope this is clearer. Thanks for the assist.

Okay, I found a solution. It isn't very readable, but it works:

user = User.new(:login=> "foo", :password=>"bar") # :password is not a column in the db, but defined in the model using "attr_accessor :password" (see initial post) [:login, :password].each do |x|     getter = x # => :password     setter = (x.to_s << "=").to_sym # => :password=     original_val = user.method(getter).call     user.method(setter).call(some_new_val)     do_some_test(user)     user.method(setter).call(original_val) end

Any clean up suggestion?

The reason to add extra attributes as shown in my example is to allow for the accessor goodies provided by ActiveRecord for the model ob:

$ cat app/models/hit.rb class Test < ActiveRecord::Base   attr_accessor :foo end

$ ./script/console Loading development environment (Rails 2.2.2)

test = Test.new

=> #<Test id: nil, name: nil>

test.id = 987

=> 987

test[:id]

=> 987

test["id"]

=> 987

test.foo = 'bar'

=> "bar"

test[:foo]

=> nil #huh?

test["foo"]

=> nil #huh?

test.attributes.keys

=> ["id", "name"] #huh?

### add key/val via model ob's attributes:

test['foo'] = 'bar'

=> "bar" #cool.

test.foo

=> "bar" #cool.

test[:foo]

=> "bar" #cool.

test.attributes.keys

=> ["id", "foo", "name"] #cool.

So, for your User example, if you changed the adding of password attrib as:

... user["password"] = "bar" ...

then your orig code should work as you intended.

Hope that helps,

Jeff

This is marginally cleaner IMO:

[:login, :password].each do |getter|     setter = "#{getter}="     original_val = user.send(getter)     user.send(setter, some_new_val)     do_some_test(user)     user.send(setter, original_val) end