nesquena / rabl

General ruby templating with json, bson, xml, plist and msgpack support
http://blog.codepath.com/2011/06/27/building-a-platform-api-on-rails/
MIT License
3.65k stars 335 forks source link

How to set node root on mapped partial renders #466

Open praveensharma opened 11 years ago

praveensharma commented 11 years ago

Hi everyone! I have a questions about structuring my RABL JSON output.

I have the following snippet of RABL:

node :subviews do |obj|
  obj.subviews.map do |subview|
    partial 'kb_view/base', object: subview
  end
end

This outputs the following JSON:

"subviews": [
        {
            "frame": "{{1024, 1024}, {1024, 1024}}", 
            "key": "testView", 
            "subviews": [], 
            "type": "View"
        }, 
        {
            "frame": "{{1024, 1024}, {1024, 1024}}", 
            "key": "testView", 
            "subviews": [], 
            "type": "View"
        },...

I need to change this to the following output, using the "subview.key" property:

 "subviews": [
        "key1":{
            "frame": "{{1024, 1024}, {1024, 1024}}", 
            "key": "testView", 
            "subviews": [], 
            "type": "View"
        }, 
        "key2":{
            "frame": "{{1024, 1024}, {1024, 1024}}", 
            "key": "testView", 
            "subviews": [], 
            "type": "View"
        },...

Any ideas? In my partial i have: object :subview => :subview.key, :root => :subview.key

Which I thought should set the root of the partial to be the subview.key property.

nesquena commented 11 years ago

How about this:

node :subviews do |obj|
  obj.subviews.map do |subview|
    { subview.key => partial('kb_view/base', object: subview) }
  end
end

?

praveensharma commented 11 years ago

Ah! Thanks for the quick response. This is extremely close - instead of an array of dictionaries though:

"subviews": [
        {
            "testView1": {
                "frame": "{{1024, 1024}, {1024, 1024}}", 
                "key": "testView", 
                "subviews": [], 
                "type": "View"
            }
        },

How would I create a dictionary of dictionaries? Is this even possible?

{
"subviews": {
    "subview": {
       "frame": "{{1024, 1024}, {1024, 1024}}", 
        "key": "testView",
        "subviews": [],
        "type": "View"
    },
    "subview2": {
        "frame": "{{1024, 1024}, {1024, 1024}}", 
        "key": "testView",
        "subviews": [],
        "type": "View"
    },...
  }
}

Sorry for the multiple somewhat lame questions - theres an extremely specific output structure i've been struggling creating using RABL and I don't have much flexibility in doing it differently.

nesquena commented 11 years ago

Definitely possible with each_with_object:

node :subviews do |obj|
  obj.subviews.each_with_object do |subview, result|
    result[subview.key] = partial('kb_view/base', object: subview)
  end
end

See how close that gets you. I don't mind the questions, I readily admit rabl works much better with "standard-ish" responses and it can get a little tricky with these super custom ones. But almost anything is do-able.

praveensharma commented 11 years ago

Ah that makes sense!

Currently, your snippet is causing a "wrong number of arguments" error on my base RABL class. Might be due to some incorrect extending of RABL templates. Looking into it - I'll let you know if this works.

Thanks again.

nesquena commented 11 years ago

Ok I think that should get you pretty close. Let me know if you get it working.  — Nathan Esquenazi CodePath Co-founder http://thecodepath.com

On Tue, Jun 18, 2013 at 12:25 PM, Praveen Sharma notifications@github.com wrote:

Ah that makes sense! Currently, your snippet is causing a "wrong number of arguments" error on my base RABL class. Might be due to some incorrect extending of RABL templates. Looking into it - I'll let you know if this works.

Thanks again.

Reply to this email directly or view it on GitHub: https://github.com/nesquena/rabl/issues/466#issuecomment-19634637

praveensharma commented 11 years ago

Thanks for all your help Nesquena - the final solution was:

node(:subviews) do |object|
  object.subviews.each_with_object({}) do |subview, result|
    result[subview.key] = partial('kb_view/base', :object => subview)
  end 
end 

The only issue was missing the ({}) at the end of each_with_object

nesquena commented 11 years ago

Ah yeah right, I aircoded it glad you found that missing piece