rabl
rabl copied to clipboard
allow defining a subnode that doesn't represent a model object
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
@nesquena thoughts on this for the 1.0 design in Issue #216?
Allow child to accept 0 arguments?
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.
Ideally would like something like this:
object @obj
node :outer do
node :inner do
attribute :title
end
end
# { :outer => { :inner => "obj.title" } }
Has this gone anywhere? This is definitely still something that is desired.
Yep still open, will probably be addressed with our major syntax changes release. Hopefully will tackle that soon.
Just wondering where this is at? Came across the same need for my API.
+1 for nested node
Why not just a wrapper method? That way the existing API isn't broken.
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
]
}
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.
Thats epic! Thanks for the tip. How can I provide an empty array node if the result is nil?