I want to add to an existing model some attributes that need not be persisted, or even mapped to a database column. Is there a solution to specify such thing ?
5 Answers
Of course use good old ruby's attr_accessor
. In your model:
attr_accessor :foo, :bar
You'll be able to do:
object.foo = 'baz'
object.foo #=> 'baz'

- 114,565
- 26
- 219
- 213
-
19How to get this attribute in object's JSON format? Say, I want this attribute to appear in the JSON of the object on the client side. Will I get it? as of now I am not getting it, even though I set this in my create method. How to do it? – YCN Apr 14 '13 at 03:09
-
1@monteirobrena same thing – apneadiving Mar 25 '14 at 15:45
-
With ActiveModelSerializer I am able to get the attribute in my JSON. – dduft Mar 19 '15 at 09:30
-
1To get the attribute in your json output, say, using "render :json => object" in your rails controller, please take a look at @RustyToms answer below. Worked for me in Rails 4 – BryanP May 14 '15 at 00:14
-
Actually using to_json is not recommended, you should use a json builder or active model serializer – apneadiving May 14 '15 at 06:48
I was having the same problem but I needed to bootstrap the model, so the attribute had to persist after to_json was called. You need to do one extra thing for this.
As stated by apneadiving, the easiest way to start is to go to your model and add:
attr_accessor :foo
Then you can assign the attributes you want. But to make the attribute stick you need to change the attributes method. In your model file add this method:
def attributes
super.merge('foo' => self.foo)
end

- 7,600
- 1
- 27
- 36
In case anyone is wondering how to render this to the view, use the method arguments for the render method, like so:
render json: {results: results}, methods: [:my_attribute]
Please know that this only works if you set the attr_accessor on your model and set the attribute in the controller action, as the selected answer explained.

- 875
- 2
- 12
- 19
From Rails 5.0 onwards you could use attribute
:
class StoreListing < ActiveRecord::Base
attribute :non_persisted
attribute :non_persisted_complex, :integer, default: -1
end
With attribute
the attribute will be created just like the ones being persisted, i.e. you can define the type and other options, use it with the create
method, etc.
If your DB table contains a matching column it will be persisted because attribute
is also used to affect conversion to/from SQL for existing columns.
see: https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute

- 24,254
- 2
- 93
- 76
In my case I wanted to use a left join to populate custom attribute. It works if I don't add anything but I also want to be able to set the attribute on a new object and of course it doesn't exist. If I add attr_accessor
then it always returns nil
after a select
. Here's the approach I've ended up with that works for setting on new object and retrieving from left join.
after_initialize do
self.foo = nil unless @attributes.key?("foo")
end
def foo
@attributes["foo"]
end
def foo=(value)
@attributes["foo"] = value
end

- 11,571
- 4
- 63
- 61
-
Doesn't work anymore in Rails 4.2. `@attributes` is now an `ActiveRecord::AttributeSet` which supports `[]` but not `[]=`. – davogones Feb 06 '16 at 04:45