RABL - attributes within child node - ruby-on-rails

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!

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.

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

Related

Simple form with collection select returning a hash

I am trying to get a dropdown list of projects organized according to the owner name. For doing this I am using SimpleForm and the grouped_select method. The issue is that for now it is a hash that is send back to the dropdown list and not the name of the project. How can I get solely the name of the project within this hash ?
This is how I define my collection
def option_clients_projects
unless self.contractor.nil?
opt_clients = self.contractor.construction_projects.map{ |cp| {:construction_project => cp.name, :client_name => cp.client.name} }
opt_clients << {:construction_project =>"Add a new project", :client_name => ""}
opt_clients
end
end
//This is what i get out this method//
[{:construction_project=>"Toilette fr", :client_name=>"Martine depouhon"}, {:construction_project=>"démolition Chateau", :client_name=>"Carla"}]
>
This is my input as grouped_select within my SimpleForm
<%= f.input :construction_project_id, collection: current_user.option_clients_projects.group_by{ |d| d[:client_name] }, as: :grouped_select, group_method: :last, group_label_method: :first %>
//The result of the group_by operation//
{"Martine depouhon"=>[{:construction_project=>"Toilette fr", :client_name=>"Martine depouhon"}], "Carla "=>[{:construction_project=>"démolition Chateau 2 2", :client_name=>"Carla "}]}
>
group_method - The name of a method which, when called on a member of collection, returns an array of child objects representing the tags.

Hide input parameters partially on activeadmin

I have an activeadmin form, in which one of the inputs fields is populated by json data returned by some method as
f.input :tag, :label => 'Tags', :as => :select, :collection => HelperClass.get_json()
The json looks like this:
{
"group_name": "Group1",
"categories": [
{
"category_name": "cat_1",
"score": "120"
},
{
"category_name": "cat_2",
"score": "120"
}
]
}
While this is shown on the form in the UI, I want only the 'group_name' to appear. However, I would want to use the data in 'categories' later on.
Is there anyway I could do this? For eg, hide the remaining json from the form, or parse the json in some other place using 'group_name', or any other way that I can't think of..
PS: Could you also elaborate while you answer this. I am not a ROR developer, but had to modify the code written by someone else.
First convert to array/hash then use Ruby Array/Hash methods. Assuming you meant the JSON is an array of groups:
data = JSON.parse HelperClass.get_json()
f.input :tag, :label => 'Tags', :as => :select,
:collection => data.map {|grp| grp['group_name']}
I suspect you want a multi-level select, which will require you to write your own JavaScript to populate the second select. Maybe https://github.com/blocknotes/activeadmin_selectize will help with that.

How do you render a partial to a hash value in JBuilder?

I have a tree-like object graph that resembles the following:
{
:name => "Grandparent",
:children => {
:child_a => {
:name => "Parent A",
:children => {
:grandchild_a_a => {
:name => "Child A-A",
:children => {}
}
:grandchild_a_b => {
:name => "Child A-B"
:children => {}
}
}
}
:child_b => {
:name => "Parent B",
:children => {}
}
}
}
I want to generate JSON that mirrors this structure. I don't know how deep the child nesting goes, and the attributes are the same for each level. The keys in the children hash are significant and must be preserved.
I want to use a JBuilder partial to represent a level, and then call it recursively. Here's my template thus far:
# _level_partial.json.jbuilder
# passing the above object graph as :level
json.name level[:name]
json.children do
level[:children].each do |key, child|
# How do I map the following to the given key?
json.partial! "level_partial", :level => child
end
end
I can generate the JSON for each child through the partial call easily enough, but that inserts it directly into the JSON output. How do I map the results of the partial to a particular hash/object key?
I've found an answer. Although it appears to be largely undocumented, JBuilder.set! can accept a block instead of an explicit value. That block can call the partial, which is then assigned to the hash.
json.name level[:name]
json.children do
level[:children].each do |key, child|
json.set! key do
json.partial! "level_partial", :level => child
end
end
end

RABL fails for empty query

I have a data tables table which is receiving data via a query that is then formatted using RABL.
It all works great until my search finds no rows.
Then I just get the ....processing message and no update.
I am really confused by RABL. Is there a way to see what it is doing?
This is my data.rabl file
object false
node(:iTotalRecords){#iTotalRecords}
node(:iTotalDisplayRecords){#iTotalDisplayRecords}
child(#aaData, :object_root => false) do
attributes :school_name => "1",
:student_name => "3",
:paid => "4",
:short_name => "5",
:emailed => "6",
:reconciled => "9"
node("6") do |p|
if p.emailed == 0
'false'
else
'true'
end
end
node("0") do |p|
p.created_at.to_date
end
node("2") do |p|
schedule = p.enrollment.schedule
link_to(p.klass_name, schedule_path(schedule))
end
node("3") do |p|
link_to(p.enrollment.student.name, student_path(p.enrollment.student_id))
end
node("7") do |p|
p.enrollment.rate
end
node("8") do |p|
p.enrollment.paid
end
node("10") do |p|
link_to("Edit", edit_payment_path(p), :class => 'btn btn-info btn-mini')
end
end
What I needed to do was to make sure that the json included a field called :payments.
If there was no data the child loop was not being executed and so there was no reason for RABL to generate a :payments field.
I found that you can force this to happen by creating an alias.
So I added the code:
child :payments => :payments
right before the line
child(#aaData, :object_root => false) do
This works great now.

Rewrite JSON structure and include an EACH loop in Rails

I have a list of shows in a database that need to be output in a certain JSON style in order to work with Polymaps.
Part of this includes the need to iterate over one section in order to create a list of points. I'm pretty certain that this needs to be achieved using :include in the render :json => #results bit of the code.
Here's the code as it stands:
def gigs
#gigs = Show.where(:displayname => "Vans Warped Tour 2011")
#giggage = [{
:type => "FeatureCollection",
:features => [
#gigs.each do |gig|
:type => "feature",
:geometry => {
:coordinates => [
gig['lng'],
gig['lat']
],
:type => "Point"
},
:properties => gig
end
]
}]
render :json => #giggage
end
There's an each loop inside a hash which I know you can't do, but that's the best way to illustrate what I'm going for, I'm going in circles on this.
I did try this which got me some of the way there, but only returned the one result because of the structure of the loop:
def gigs
#gigs = Show.where(:displayname => "Vans Warped Tour 2011")
#gigs.each do |gig|
#gigs_to_render = {
:type => "FeatureCollection",
:features => [
:type => "feature",
:geometry => {
:coordinates => [
gig['lng'],
gig['lat']
],
:type => "Point"
},
:properties => gig
]
}
end
render :json => #gigs_to_render
end
Thanks for your help! Anyone. Everyone!
The code as it stands should be very close to working. Just change each to map and surround the body of the block in curlies so it all gets returned as a hash for each gig.

Resources