Peter Vandenabeele wrote in post #1042445:
model1.to_json(:include => {:model2 => {:only =>
[:some_other_property]}, :only => [:id])
Can someone please explain to me why it works this way.
The code in active_model/serialization.rb was changed significantly
between 3.1.3 and 3.2.0. On which version are you working? In
my case, the code in 3.2.0 did the right thing 
:only => resulted (correctly) in an empty list in 3.2.0, while in
3.1.3
it resulted in all attributes included.
These 2 commits seem to be most relevant:
https://github.com/rails/rails/commit/5b2eb64c
https://github.com/rails/rails/commit/2a663dcf
HTH,
Peter
Thanks for the reply and the links. I am running on 3.1.3 which may be
the problem but after walking through the commit you sent I believe
3.2.0 is handling it the same way. My problem is the same options are
being used for the parent and included models.
book.to_json( :only => [:id] )
{ “id”: 1 } ← expected
book.to_json(:only => [:id], :include => :chapters)
{ “id”: 1, “chapters”:[ { “id” : 1 } ] } ← sorta expected but shouldn’t
be
book.to_json(:only => [:id, :name], :include => :chapters)
{ “id”: 1, “name”:“The Ruby Way”, “chapters”:[ { “id” : 1,
“name”:“serialization” } ] } ← don’t understand
Notice how name is included for the chapters as well? The reason this
happens is because :only => [:id, :name] is passed to the
serializable_hash call for both book and chapters.
I can confirm your observation (Rails 3.1.3):
Calling user.to_xml with the options:
{:include=>{:address=>{}}, :only=>[:city, :first_name]}
where :city is only in address and :first_name is only in user, I get
<first_name>Jan</first_name>
AND
\n Brussel\n
in the result. The latter was not expected (I did not
specify any "only options in the included :address.
The reason I never bumped into this, is that for each
to_xml of main object and associated objects, I run
through a white_list (that explicitly sets the :only list),
to protect what I will show in the API.
Specifically, this options set
Rails 3.1.3 :
book.to_json(:only => [:id], :include => {:chapters => {:only => :nothing}})
yes, the :nothing looks funny …
Rails 3.2.0 :
book.to_json(:only => [:id], :include => {:chapters => {:only => }})
would be a work-around for your case (if you wanted nothing shown
from the chapters attributes).
My argument is that
the options should only be passed to the parent model (books) but not
the included association (chapters). Let’s expand upon the previous
example and say we added one more attribute to the only option.
book.to_json(:only => [:id, :name, :price], :include => :chapters)
{ “id”: 1, “name”:“The Ruby Way”, “price”:2000, “chapters”:[ { “id” : 1,
“name”:“serialization” } ] }
In the example above, the “price” attribute was added as an :only
option. Since book has a price the value is included in the json. The
problem is chapters doesn’t have a price but the option is still passed
in during serialization anyway. Why not start clean for each included
relationship? Instead of passing the same options along, exclude the
top level options for :only, :except, and :methods when serializing
included associations.
What are your thoughts
I agree (the current behavior seems a bug to me). I did not test this
specific behavior in Rails 3.2.0
HTH,
Peter