I''m trying to write a helper method similar to attr_accessible but instead it will be used to whitelist which attributes are available for serialization (attr_serializable). My first attempt at this was to override serialized_hash and modify the :only option to include nothing but serializable attributes. I''m facing a problem when nested models are ''included'' using the :include option. The :only options for the parent model are also getting sent to the nested model(s). Here''s an example: model1.to_json(:include => model2, :only => [:id]) First serializable_hash gets called for model1 and is passed an options hash with :only set to an array including :id. This makes sense to me since the :only option was specified as a top level options. Next serializable_hash gets called for model2 and it is also passed an options hash that include :id in the :only option. Why would :only => [:id] be an option for the included model (model2)? Same goes for :methods and :except options set at the top level. I would expect the :only , :except, and :methods options to be removed if they are not specified directly on the included model as such: model1.to_json(:include => {:model2 => {:only => [:some_other_property]}, :only => [:id]) Can someone please explain to me why it works this way. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2012-Jan-25 09:19 UTC
Re: serializable_hash and serializable_add_includes
On Wed, Jan 25, 2012 at 7:35 AM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> I''m trying to write a helper method similar to attr_accessible but > instead it will be used to whitelist which attributes are available for > serialization (attr_serializable). My first attempt at this was to > override serialized_hash and modify the :only option to include nothing > but serializable attributes. I''m facing a problem when nested models > are ''included'' using the :include option. The :only options for the > parent model are also getting sent to the nested model(s). Here''s an > example: > > model1.to_json(:include => model2, :only => [:id]) > > First serializable_hash gets called for model1 and is passed an options > hash with :only set to an array including :id. This makes sense to me > since the :only option was specified as a top level options. Next > serializable_hash gets called for model2 and it is also passed an > options hash that include :id in the :only option. Why would :only => > [:id] be an option for the included model (model2)? Same goes for > :methods and :except options set at the top level. I would expect the > :only , :except, and :methods options to be removed if they are not > specified directly on the included model as such: > > 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 -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele wrote in post #1042445:> On Wed, Jan 25, 2012 at 7:35 AM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: > >> >> 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, > > PeterThanks 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. 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 -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2012-Jan-25 15:55 UTC
Re: Re: serializable_hash and serializable_add_includes
On Wed, Jan 25, 2012 at 4:03 PM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Peter Vandenabeele wrote in post #1042445: > > On Wed, Jan 25, 2012 at 7:35 AM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: > > > >> > >> 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 <address>\n <city>Brussel</city>\n </address> 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 -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2012-Jan-25 17:40 UTC
Re: Re: serializable_hash and serializable_add_includes
On Wed, Jan 25, 2012 at 4:55 PM, Peter Vandenabeele <peter-jNuWw7i2w7syMbTcgqFhxg@public.gmane.org>wrote:> On Wed, Jan 25, 2012 at 4:03 PM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: > >> Peter Vandenabeele wrote in post #1042445: >> > On Wed, Jan 25, 2012 at 7:35 AM, Jacob H. <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: >> > >> >> >> >> 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. > >Could it be that is actually solved in Rails 3.2.0 ? Did you effectively test with 3.2.0? I just tested now in Rails 3.2.0 and found this: 1.9.3-p0 :012 > p.to_xml(:only => :name, :include => :child) => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<parent>\n <name>dad</name>\n <child>\n <created-at type=\"datetime\">2012-01-24T10:05:43Z</created-at>\n <id type=\"integer\">1</id>\n <name>Sarah</name>\n <parent-id type=\"integer\">1</parent-id>\n <updated-at type=\"datetime\">2012-01-24T10:05:43Z</updated-at>\n </child>\n</parent>\n" This seems to indicate that for the child, all attributes are shown, independent of the :only on the parent. There is recent discussion about this on https://github.com/rails/rails/issues/714> 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 >I have the impression now that the issue is resolved in 3.2.0. Peter -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Seemingly Similar Threads
- rails 3.0.9 ArgumentError (redundant UTF-8 sequence):
- Find all association methods
- Proposal for a new ActiveModel::Errors structure
- Creating nested hash from nested active record results
- DEPRECATION WARNING: Passing a template handler in the template name is deprecated. (rspec + haml)