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 ?
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
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
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'
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.
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