rails / jbuilder

Jbuilder: generate JSON objects with a Builder-style DSL
MIT License
4.34k stars 440 forks source link

Data is being overwritten in loop #441

Closed MichaelA59 closed 6 years ago

MichaelA59 commented 6 years ago

I would like to serve up a data structure as outlined below:

{ purchase_id: 1,
  sessions: [
    {...},
    {...}
   ]
},
{ purchase_id: 2,
  sessions: [
    {...}
   ]
}

To do this, I am serving my jbuilder an instance variable @session_groups which is a group of session objects which are grouped by their purchase_id. As such the structure going into jbuilder looks like the following:

{ 1: [ session_obj ], [session_obj ] },
{ 2: [ session_obj ], [session_obj ], [session_obj  },
{ 3: [ session_obj ] }

So, I have the following iteration but what it actually produces is the LAST session object from the last group of sessions (grouped by purchase_id). Code looks like this

json.sessions do
  @session_groups.each do |k, v|
    json.purchase_id k
    json.sessions do
      v.each do |s|
        json.call(s,
          :id,
          :start,
          :status,
          :product_name,
          :total_sessions,
          :duration,
          :feedback,
          :cancellation_reason)
          json.client do
            json.id           s.client.id
            json.name         s.client.name
            json.company_logo s.client.employee ? s.client.employee.company_logo : nil
            json.company_name s.client.employee ? s.client.employee.company_name : nil
          end
        end
    end
  end
end

I was able to use the following code, but what this produced was a straight array of session objects, without keeping them grouped by thier purchase_id into a neat hash. Code looks like this:


json.sessions do
  @session_groups.each_value do |v|
    v.each do |s|
      json.child! {
        json.call(s,
                  :id,
                  :start,
                  :status,
                  :product_name,
                  :product_id,
                  :total_sessions,
                  :duration,
                  :feedback,
                  :cancellation_reason)
        json.client do
          json.id s.client.id
          json.name s.client.name
          json.company_logo s.client.employee ? s.client.employee.company_logo : nil
          json.company_name s.client.employee ? s.client.employee.company_name : nil
        end
      }
    end
  end
end

The first code snippet is where I want to be, minus the overwriting of course. Can anyone offer some guidance on where this is going wrong?

MichaelA59 commented 6 years ago

Got it with the folllowing:

json.sessions do
  json.array!(@session_groups) do |k, v|
    json.purchase_id k
    json.sessions do
      json.array!(v) do |s|
        json.call(s,
                  :id,
                  :start,
                  :status,
                  :product_name,
                  :total_sessions,
                  :duration,
                  :feedback,
                  :cancellation_reason)
        json.client do
          json.id           s.client.id
          json.name         s.client.name
          json.company_logo s.client.employee ? s.client.employee.company_logo : nil
          json.company_name s.client.employee ? s.client.employee.company_name : nil
        end
      end
    end
  end
end
abrambailey commented 5 years ago

I am having a similar problem ... Is there anyway to get multiple filters? Each time they are overwritten.

json.filters do |filters|
  @service_groups.each do |category, services|
    json.category category
    json.options services do |service|
      json.name service.name
      json.id   "service_#{service.id}"
    end
  end
  @brands.each do |brand|
    json.category 'brands'
    json.options @brands do |brand|
      json.name brand.name
      json.id   "brand_#{brand.id}"
    end
  end
end