rabl icon indicating copy to clipboard operation
rabl copied to clipboard

allow defining a subnode that doesn't represent a model object

Open mackuba opened this issue 13 years ago • 11 comments

Let's say I want to generate such JSON:

{
  "user": { ... },
  "config": {
    "base_url": "http://server.com",
    "env": "development",
    "location": { "lat": 50, "lng": 20 },
    ...
  }
}

In this case, the config node doesn't represent any model object, it's just a simple hash. The problem is how to add the config node to the parent in the template.

I could do something like this:

node(:config) {{ :base_url => ..., :env => ..., :location => ... }}

I don't like this approach though, because it forces me to drop the RABL DSL used everywhere else and go back to the standard hash syntax. Also, I can't use child() anymore to define a child node that represents a model (if e.g. location was a model object).

I found a way to get around this by writing:

child Object.new => :config do
  ...
end

So my proposed solution is to just add a helper that will let you do this more easily. Something like this:

class Rabl::Engine
  def hash(name, &block)
    child(Object.new => name, &block)
  end
end

And this would let you just write:

hash :config do
  node(:base_url) { "http://server.com" }
  child @location
end

mackuba avatar Feb 28 '12 14:02 mackuba

@nesquena thoughts on this for the 1.0 design in Issue #216?

Allow child to accept 0 arguments?

databyte avatar Apr 06 '12 04:04 databyte

I think the hash thing we will get for free with our new syntax. child with 0 arguments, I am not sure I wouldn't normally use that though in my own apis.

nesquena avatar Apr 06 '12 05:04 nesquena

Ideally would like something like this:

object @obj

node :outer do
  node :inner do
    attribute :title
  end
end

# { :outer => { :inner => "obj.title" } }

quaternion avatar Apr 19 '12 16:04 quaternion

Has this gone anywhere? This is definitely still something that is desired.

ardavis avatar Dec 04 '12 04:12 ardavis

Yep still open, will probably be addressed with our major syntax changes release. Hopefully will tackle that soon.

nesquena avatar Dec 04 '12 04:12 nesquena

Just wondering where this is at? Came across the same need for my API.

fakingfantastic avatar Jan 27 '13 13:01 fakingfantastic

+1 for nested node

mateusmaso avatar Jan 29 '13 20:01 mateusmaso

Why not just a wrapper method? That way the existing API isn't broken.

toxaq avatar Jul 20 '13 14:07 toxaq

What is the status with this.. I'm trying to create a custom layout

object false

node(:request) { 'player' }
node(:outcome) { 'success' }
node(:data) {
  node :default_classes do |obj|
    FactionClass.all.map do |c|
      partial('faction_classes/show.json.rabl', object:c)
    end
  end

Which gives me almost what I want. But it places the "default_classes" as a root node, not a child of data, Also, why does it fill data with that other stuff? Thanks.

{
   "request":"player",
   "outcome":"success",
   "data":[
      {
         "name":"request",
         "options":{

         },
         "block":"#<Proc:0x007f106999a658@(eval):3>"
      },
      {
         "name":"outcome",
         "options":{

         },
         "block":"#<Proc:0x007f106999a5b8@(eval):4>"
      },
      {
         "name":"data",
         "options":{

         },
         "block":"#<Proc:0x007f106999a518@(eval):5>"
      },
      {
         "name":"default_classes",
         "options":{

         },
         "block":"#<Proc:0x007f106999a040@(eval):12>"
      }
   ],
   "default_classes":[
      //the expected array
   ]
}

johnrickman avatar Dec 31 '14 13:12 johnrickman

Avoid nesting node objects like that. It's causing those issues. For example

object false

node(:request) { 'player' }
node(:outcome) { 'success' }
node(:data) do
  result = FactionClass.all.map do |c|
      partial('faction_classes/show.json.rabl', object:c)
  end
  { :default_classes => result }
end

I know it'd be nice to have nodes within nodes but it's not supported properly right now. Once you are in a node block you need to create the response in "pure" ruby.

nesquena avatar Dec 31 '14 18:12 nesquena

Thats epic! Thanks for the tip. How can I provide an empty array node if the result is nil?

johnrickman avatar Dec 31 '14 22:12 johnrickman