Thank you for the quick response, Jeremy.
Looks like you were right. I believe it is the association_proxies plugin.
Sorry about the formatting.
Both of the solutions you've offered worked perfectly. Each gave the output
I was expecting.
Thank you, again.
-Patrick
On Monday, May 2, 2016 at 10:37:18 AM UTC-4, Jeremy Evans wrote:
>
> On Sunday, May 1, 2016 at 10:35:24 PM UTC-7, Patrick Kuykendall wrote:
>>
>> Hello,
>>
>> I'm running into a little hiccup with the json_serializer plug-in. If I
>> try to include an association that is an array, the to_json call doesn't
>> process the items in the array, just the array itself. I added the
>> activesupport fixes you mention in the documentation, but I'm still having
>> this issue.
>>
>> Something like this should be able to reproduce it:
>>
>> class User < Sequel::Model(DB[:users])
>> one_to_many :addresses
>> end
>>
>> class Address < Sequel::Model(DB[:addresses])
>> end
>>
>> User.first.to_json(
>> only: [:first_name, :last_name],
>> include: {
>> addresses: { only: [:line_1, :line_2, :city, :state, :zip_code] }
>> }
>> )
>> #=> {first_name: 'John', last_name: 'Doe', addresses: [{address_id: 1,
>> address_type_id: 1, line_1: 'XXX' line_2: nil, city 'XXX', state: 'XXX',
>> zip_code: '12345', created_on: 2016-05-01T01:30:00, updated_on: nil,
>> deleted_on: nil}]}
>>
>>
>> I dove into it a little and I found that InstanceMethods#to_json performs
>> a check to see if the included association is an Array. It seems this isn't
>> catching for me, and it's processing the array object as a whole.
>>
>> Here's the section: [direct link](
>> https://github.com/jeremyevans/sequel/blob/master/lib/sequel/plugins/json_serializer.rb#L303
>> )
>>
>> cols.each{|c| h[c.to_s] = get_column_value(c)}
>> if inc = opts[:include]
>> if inc.is_a?(Hash)
>> inc.each do |k, v|
>> v = v.empty? ? [] : [v]
>> h[k.to_s] = case objs = send(k)
>> when 'Array'
>> objs.map{|obj| Literal.new(Sequel.object_to_json(obj, *v))}
>> else
>> Literal.new(Sequel.object_to_json(objs, *v))
>> end
>> end
>> else
>> Array(inc).each{|c| h[c.to_s] = send(c)}
>> end
>> end
>>
>> I was able to have it properly render the objects contained in the array
>> with this. (Pardon the dirty hack, I was just testing it out)
>>
>> cols.each{|c| h[c.to_s] = get_column_value(c)}
>> if inc = opts[:include]
>> if inc.is_a?(Hash)
>> inc.each do |k, v|
>> v = v.empty? ? [] : [v]
>> objs = send(k)
>> h[k.to_s] = case objs.class.to_s
>> when 'Array'
>> objs.map{|obj| Literal.new(Sequel.object_to_json(obj, *v))}
>> else
>> Literal.new(Sequel.object_to_json(objs, *v))
>> end
>> end
>> else
>> Array(inc).each{|c| h[c.to_s] = send(c)}
>> end
>> end
>>
>> Let me know if I might be doing something wrong here.
>> Thank you.
>>
>
> Unfortunately, this isn't a self contained example, so at most I can give
> an educated guess. From the change your making it looks like you are just
> changing the case statement (please use a diff in the future to make the
> change more obvious). The only situation I can think of where that would
> solve the problem is if you were using the association_proxies plugin, in
> which case the association method returns a proxy and not an array, but
> calling class on the object will return Array.
>
> I think one possible way to get what you want without modifying the
> json_serializer plugin would be to preprocess the addresses:
>
> u = User.first
> u.addresses.each{|a| a.json_serializer_opts(only: [:line_1, :line_2,
> :city, :state, :zip_code])}
> u.to_json(only: [:first_name, :last_name], include: :addresses)
>
> In terms of modifying the json_serializer plugin, we could see if the
> :include value is also an association, and if so if the association returns
> an array, falling back to the current code for detecting arrays if the
> value is not an association. Something like:
>
> diff --git a/lib/sequel/plugins/json_serializer.rb
> b/lib/sequel/plugins/json_serializer.rb
> index c953295..8215548 100644
> --- a/lib/sequel/plugins/json_serializer.rb
> +++ b/lib/sequel/plugins/json_serializer.rb
> @@ -300,8 +300,16 @@ module Sequel
> if inc.is_a?(Hash)
> inc.each do |k, v|
> v = v.empty? ? [] : [v]
> - h[k.to_s] = case objs = send(k)
> - when Array
> +
> + objs = send(k)
> +
> + is_array = if r = model.association_reflection(k)
> + r.returns_array?
> + else
> + objs.is_a?(Array)
> + end
> +
> + h[k.to_s] = if is_array
> objs.map{|obj| Literal.new(Sequel.object_to_json(obj,
> *v))}
> else
> Literal.new(Sequel.object_to_json(objs, *v))
>
> Can you try that out and see if it works for you?
>
> Thanks,
> Jeremy
>
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.