Imme22009
Imme22009

Reputation: 4129

RABL - attributes within child node

If I create a child node in RABL using the node() method, how can I control the attributes that are presented?

The JSON output is this:

[
    {
        "location": {
            "latitude": 33333,
            "longitude": 44444,
            "address": "xxxxxxx",
            "title": "yyyy",
            "url": "http://www.google.com",
            "rate": {
                "created_at": "2012-09-02T11:13:13Z",
                "id": 1,
                "location_id": 1,
                "pair": "zzzzzz",
                "updated_at": "2012-09-02T12:55:28Z",
                "value": 1.5643
            }
        }
    }
]

I want to get rid of the created_at, updated_at and location_id attributes.

I have this in my view file:

collection @locations
attributes :latitude, :longitude, :address, :title, :url
node (:rate) do   
  |location| location.rates.where(:pair => @pair).first
end

I tried using a partial and the 'extend' method, but it totally screwed things up. Also, I tried adding attributes to the block but it didn't work (the output was as specified in the attributes but it didn't show the values for each attribute).

Thanks!

Upvotes: 1

Views: 5653

Answers (2)

Chen Fisher
Chen Fisher

Reputation: 1455

Your code: location.rates.where(:pair => @pair).first returns the whole Rate object. If you want specific fields (for example: all, except for create_at, updated_at, etc.) then you have two options:

Manually describe the hash in node():

node (:rate) do |location|  
   loc = location.rates.where(:pair => @pair).first
   { :pair => loc.pair, :value => loc.value, etc... }
end

Or you can do this:

node (:rate) do |location|  
   location.rates.where(:pair => @pair).select('pair, value, etc...').first
end

...and as a side note, I should say that placing logic (rates.where) in your view is not a best practice. see if your controller can do that for the view using the Rate model.

Upvotes: 2

Andrea Singh
Andrea Singh

Reputation: 1613

You wouldn't be able to use attributes within the node block, since "self" in there is still the root object or collection, so in your case @locations. See also RABL wiki: Tips and tricks (When to use Child and Node)

In the node block you could simply create your custom response by only listing the attributes that your interested in:

node :rate do |location|
  rate = location.rates.where(:pair => @pair).first
  {:id => rate.id, :location_id => rate.location_id, :value => rate.value}
end

You can also try the approach using a partial:

In app/views/rates/show.json.rabl

object @rate
attributes :id, :location_id, :value

Then in your @locations rabl view:

node :rate do |location|
  rate = location.rates.where(:pair => @pair).first
  partial("rates/show", :object => rate)
end

Upvotes: 2

Related Questions