
Question:
I have tableless model (like it was shown in #219 railscast):
class MyModel
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :attr1, :attr2, :attr3, :attr4
private
def initialize(attr1 = nil)
self.attr1 = attr1
end
def persisted?
false
end
end
Then I'm trying to render JSON in controller:
@my_model = MyModel.new
render json: @my_model.to_json(only: [:attr1, :attr2])
but it renders JSON with all the attributes of the model.
I've tried to add
include ActiveModel::Serialization
but it didn't change rendered JSON.
How can I render JSON with only necessary attributes of my tableless model?
I'm using Rails 3.2.3
<strong>Update</strong>
Thanks, guys. It seems you're all almost right. I combined your solutions and got this:
Model:
include ActiveModel::Serialization
...
def to_hash
{
attr1: self.attr1,
attr2: self.attr2,
...
}
end
Controller:
render json: @my_model.to_hash.to_json(only: [:attr1, :attr2])
I really don't know whose answer to be accepted.
<strong>Update 2</strong>
Suddenly new strangeness appeared. One of the attributes is array of hashes. It was like this:
attr1: [[{name: "name", image: "image"}, {name: "name", image: "image"}],
[{name: "name", image: "image"}, {name: "name", image: "image"}]]
But now it lost all its content and looks like this:
attr1: [[{}, {}], [{}, {}]]
Maybe anyone know how to fix it?
<strong>Update 3</strong> :)
Erez Rabih's answer helped. Using slice
instead of to_json
solved the problem. So, final solution is:
render json: @my_model.to_hash.slice(:attr1, :attr2)
Answer1:I know it isn't straight forward but how about:
render :json => @my_model.attributes.slice(:attr1, :attr2)
You will also be required to define an attributes method as:
def attributes
{:attr1 => self.attr1.....}
end
Thanks for the comment bender.
Answer2:I believe it's because Object::as_json is calling internally (look at this: <a href="http://apidock.com/rails/Object/as_json" rel="nofollow">http://apidock.com/rails/Object/as_json</a>), and it has no options like :only or :except, so you can overide method to_hash in your class, e.g.:
def to_hash
{:attr1 => self.attr1, :attr2 => self.attr2}
end
and to_json will do exactly what you want.
Certainly, another option is to override method to_json ...
Answer3:You may mix your initial approach (including AM serialization modules) with Erez' one as the <a href="http://api.rubyonrails.org/classes/ActiveModel/Serialization.html" rel="nofollow">documentation</a> suggests.
class MyModel
include ActiveModel::Serialization::JSON
....
def attributes
{:attr1 => self.attr1.....}
end
...
end