Adding an ID to the :object_root #229

Closed
deanpcmad opened this Issue Apr 23, 2012 · 12 comments

Comments

Projects
None yet
2 participants

In my app I am looking to add the item ID to the end of the :object_root so instead of showing 'pic' it shows 'pic_2' or which ever the ID of that pic is.

My current code in my index.rabl is collection @screens, :root => "images", :object_root => "pic"

And it spits out this code JSON

{
  "images": [
    {
      "pic": {
        "id": 1,
        "name": "my pic123"
    },
    {
      "pic": {
        "id": 2,
        "name": "Yet another pic!"
    }
  ]
}

How would I go about doing this?

Also is it possible for me to have two collections in a single index.json.rabl? When doing so, it only shows the second collection and ignores the first.

Owner

nesquena commented Apr 23, 2012

What you are trying to achieve will need to be done more manually but it won't be too bad. Just use node liberally:

object false # manually create nodes

node :images do
  @screens.map do |screen|
     { "pic_#{screen.id}" => { :id => screen.id, :name => screen.name} }
  end
end

Using this approach you get all the control you need and you can construct your json in ruby.

Excellent, thanks so much! :)

@deanpcmad deanpcmad closed this Apr 23, 2012

@deanpcmad deanpcmad reopened this Apr 24, 2012

Just an update. Would I be able to have it show as this:
Note there is no "images" in the name. The example you showed me is great, I was just wondering if this is possible?

[
 {
    "pic_1": {
      "name": "test",
      "id": "1"
    },
 },
 {    
    "pic_2": {
      "name": "my photo",
      "id": "2",
    },
 },
 {
    "pic_5": {
      "name": "hello",
      "id": "5"
    },
 }
]
Owner

nesquena commented Apr 24, 2012

Sure, try:

object false # manually create nodes

node do
  @screens.map do |screen|
     { "pic_#{screen.id}" => { :id => screen.id, :name => screen.name} }
  end
end
Owner

nesquena commented Apr 24, 2012

Actually that may not work, but worth a shot and we could probably support that in the future. Honestly at that point though we have gotten pretty far away from RABL's strong suit, you may be better off with using a presenter.

Thanks for the fast reply, yeah that doesn't work. So instead of using RABL, use a presenter? I shall take a look, thanks.
Do you recommend any other JSON API templating gem similar to RABL?

Owner

nesquena commented Apr 24, 2012

For this particular use case but you could stick with RABL for more standard object templates. Obviously you can use jbuilder or json_builder for these types of custom situations or to replace rabl. This one case you are describing is a pretty simple one. For this above, I recommend just using a plain old ruby object:

class PicPresenter
  attr_accessor :pics

  def initialize(pics)
    @pics = pics
  end

  def render
     pics.map do |p|
       { "pic_#{p.id}" => { :id => p.id, :name => p.name} }
    end
  end
end

Then in the controller:

render :json => PicPresenter.new(@screens).render

Hope that conveys the idea, but I think often PORO (plain old ruby) can be a good way to do simple presentation like this in cases where RABL doesn't fit exactly. That being said, we could probably support this case pretty easily with node in the future.

Owner

nesquena commented Jul 16, 2012

Also you could probably have done:

@screens.map do |screen|
  node "pic_#{screen.id}" do
    { :id => screen.id, :name => screen.name}
  end
end

Just a FYI. I am sure you found an alternate solution by now.

@nesquena nesquena closed this Jul 16, 2012

Hey there, funnily enough I came back to this issue yesterday to have a look at the code you posted previously. I am trying to add screens and pics into a single node called "devices". Is this possible at all?

I have tried this

node :devices do
  @screens.map do |h|
     { "h_#{h.id}" => { :id => h.id, :name => h.name} }
  end
  @pics.map do |d|
     { "d_#{d.id}" => { :id => d.id, :name => d.name} }
  end
end

But this only shows one set, eg only the @pics and not both :/

All I get is this:

{
  "devices": [
    {
      "d_1": {
        "id": 1,
        "name": "My 27\" iMac"
      }
    }
  ]
}
Owner

nesquena commented Jul 16, 2012

Try this:

node :devices do
  result = @screens.map do |h|
    { "h_#{h.id}" => { :id => h.id, :name => h.name} }
  end
  result += @pics.map do |d|
    { "d_#{d.id}" => { :id => d.id, :name => d.name} }
  end
  result
end

as one example of how to achieve that.

Nice work, that's it! Thanks for your help! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment