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

Nested level is different between JSON and XML formats #324

Open mikhailov opened 12 years ago

mikhailov commented 12 years ago

I was surprised to see that child block fetches an associations instead of instance's variable with the same name, so I was going to use node block to force to use my scoped data-set, not just the associations.

What I have:

child :questions do
  attributes :id, :interview_id, :time
end

What I'd like to have:

child :questions.available do
  attributes :id, :interview_id, :time
end

available is a scope I wanted to provide with API.

I decided to use the node block like the following:

node :questions do
  @questions.map do |q|
     { id: q.id, interview_id: q.interview_id, time: q.time } 
  end
end

It shows the same XML, but invalid nested JSON data set, to make it properly in JSON I do:

node :questions do
  @questions.map do |q|
    { question: { id: q.id, interview_id: q.interview_id, time: q.time }}
  end
end

Now JSON the same as with child, but XML is different, nested level is invalid.

databyte commented 12 years ago

Hmm, I would try something like:

node :questions do |q|
  partial 'questions/index', q.available
end

# questions/index.rabl
attributes :id, :interview_id, :time
mikhailov commented 12 years ago

@databyte I'll check it out, but I would like to see the same data structure across multiple formats XML and JSON for a node block without extra partials.

databyte commented 12 years ago

Well JSON and XML technically have different protocols. The problem with JSON in your case is that the hash itself needs to be labeled. If you had a questions node and embedded an array of hashes, it should work.

valid JSON:

{ "questions": [ {"id": 1}, {"id": 2} ] }
mikhailov commented 12 years ago

@databyte thanks for the answer, but let me explain a little bit more. While I used to have dataset built with child, the XML and JSON responses were identically. Once I tried to use node I can't do the same. The general concern still not answered - Is this possible to use scoped explicit data, but not implicit associations?

databyte commented 12 years ago

So you still want to use:

child :questions.available do
  attributes :id, :interview_id, :time
end

Or are you asking about how you can manipulate node to generate the same output?

In general, I'm a fan of presenters and I don't personally like to make complex RABL template files because it obfuscates my intent. My general answer for complex templates is presenters and decorators but your example seems simple enough that I don't see why it would be needed. I just don't think I understand your question well enough - and that's probably because I have to see the output of your node code in both JSON and XML.

Personally, I just don't have any projects that output both JSON and XML that need to match schemas. In fact, if I were to build a project - I'd guess my JSON would actually be more terse than my XML and my JSON would probably also include RESTful URIs to other resources instead of embedding everything within a single resource. Because I would most likely parse my XML in its entirety or transform it but with the JSON I would manipulate client-side immediately by pulling out what I need or queuing up more async requests. But again, that's just me.

So maybe sample output from node code would highlight the problem better?

databyte commented 11 years ago

Leaving open, v1 gets some XML love.