rabl
General ruby templating with json, bson, xml, plist and msgpack support
Building a Platform API on Rails | CodePath
I'm trying to render a pretty simple data structure using RABL, but I can't figure out how to remove the child root nodes properly. Here are my two templates.
First, the collection index template.
collection @groups, :object_root => false
attributes :id, :name
child :files do
extends 'groups/_file'
end
And next, the file partial template.
object @file
attributes :id
Those two templates end up producing the following JSON:
[
{
"id":"4f57bf67f85544e620000001",
"name":"Some Group",
"files":[
{
"file":{
"id":"4f5aa3fef855441009000007"
}
}
]
}
]
I want to find a way to remove the root "file" key inside of the files collection. Something like:
[
{
"id":"4f57bf67f85544e620000001",
"name":"Some Group",
"files":[
{
"id":"4f5aa3fef855441009000007"
}
]
}
]
Source: (StackOverflow)
I have this template:
# app/views/posts/index.rabl
collection @posts => :posts
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:read) { |post| post.read_by?(@user) }
Witch returns:
{
"posts": [
{
"post": {
"id": 5,
"title": "...",
"subject": "...",
"user": {
"full_name": "..."
},
"read": true
}
}
]
}
And I would like to add to add some pagination params in order to rendering this:
{
"posts": [
{
"post": {
"id": 5,
"title": "...",
"subject": "...",
"user": {
"full_name": "..."
},
"read": true
}
}
],
"total": 42,
"total_pages": 12
}
Any ideas? Many thanks!
Source: (StackOverflow)
I have this rabl template:
object @photo
attributes :id
child :comments do
attributes :id, :body
end
Which gives me this JSON response:
{
photo: {
id: 1,
comments: [
{
comment: {
id: 1,
body: 'some comment'
}
},
{
comment: {
id: 2,
body: 'another comment'
}
}
]
}
}
But I want it to look like this:
{
id: 1,
comments: [
{
id: 1,
body: 'some comment'
},
{
id: 2,
body: 'another comment'
}
]
}
Why does rabl wrap each element in the array with an extra object called comment
. In this way when I access the collection in javascript I have to write:
var comment = image.comments[0].comment
instead of:
var comment = image.comments[0]
I know that if I include :comments
in the attributes list for the @photo
object it works the way I want, but when I want another level of nested associations for each comment
object, there isn't a way to handle that besides using child
, but that gives me the JSON response that I don't want.
Maybe I'm just misunderstanding the whole thing -- can someone explain or help? Thanks!
Source: (StackOverflow)
I am using RABL to output a Sunspot/SOLR result set and the search results object is composed of multiple model types. Currently within the rabl view I have:
object false
child @search.results => :results do
attribute :id, :resource, :upccode
attribute :display_description => :description
code :start_date do |r|
r.utc_start_date.to_i
end
code :end_date do |r|
r.utc_end_date.to_i
end
end
child @search => :stats do
attribute :total
end
The above works for a single model; however, when multiple model types are within the @search.results collection, it fails because both classes do not have the same instance methods. Does anyone know how to have different attributes based on the type? Ultimately, it would be nice to conditionally extend a different template within the results collection based on the type of object. Something like the below pseudo code:
child @search.results => :results do |r|
if r.class == Product
extends "product/base"
else
extends "some other class base"
end
end
Source: (StackOverflow)
I think I have a very basic case when I'm using rabl to return JSON for standard RESTful controller methods...
First let's say I have a typical one to many relationship with parent and child (let's say customer and accounts):
class Customer < ActiveRecord::Base
has_many :accounts
end
In my controller for customer I have index and edit - index where I just want to return all Customers (WITHOUT accounts) and edit where I want to return a specific Customer with all of their Accounts. With index I don't want to return the accounts for obvious performance (N+1) reasons.
In my rabl, I have the following:
#index.rabl (for listing all customers)
collection :@customers
extends "customers/_customer"
and
#edit.rabl (for editing a single customer)
object :@customer
extends "customer/_customer"
I am reusing the _customer.rabl for both the index and the edit.
#_customer.rabl
object :@customer
attributes :name, ......
if @include_accounts
child :accounts do
extends "accounts/_account"
end
end
I set the @include_accounts in my edit (controller) and not the index - but this doesn't work - essentially the instance var here (@include_accounts) never gets passed down. What is the correct pattern to implement this?
Source: (StackOverflow)
I'm trying to do something like this:
cache "api/v1/cars_index/#{I18n.locale}/car/#{car.cache_key}" do
attributes :id, :brand, :model_name, :fuel, :km, :year, :price
node(:color) { |car| car.color.present? ? car.color : '' }
end
Source: (StackOverflow)
I want json output order by id(child id)
Can I solve this problem ?
this is some code in my project
show.json.rabl (I used Rabl)
object @book
attributes :id , :name
child :questions do
attributes :id , :name
end
books_controller.rb
def show
@book = Book.find(params[:id])
end
Sorry for my English , Thank you.
Source: (StackOverflow)
I upgraded to rails4 from 3.2.2 and i now get this undefined method from my rabl template that id didn't get before the upgrade.
the "tooth" paramater on procedures is a set by a getter/setter method that is stored in the postgres database as a hstore hash named properties.
Not sure what has changed in rails4 to make this happen!
Any help would be much appreciated.
ERROR:
Showing /home/action/app/views/procedures/chart.json.rabl where line #1 raised:
undefined method `scan' for {"tooth"=>""}:Hash
Extracted source (around line #1):
1 object @procedures
2 attributes :buccal, :mesial, :occlusal, :distal, :lingual
Trace of template inclusion: app/views/procedures/_procedures_table.html.erb, app/views/procedures/chart.html.erb
Procedures model (getter and setter method for :tooth)
%w[tooth buccal mesial occlusal distal lingual].each do |key|
attr_accessible key
scope "has_#{key}", lambda { |value| where("properties @> (? => ?)", key, value) }
define_method(key) do
properties && properties[key]
end
define_method("#{key}=") do |value|
self.properties = (properties || {}).merge(key => value)
end
end
Gemfile:
source 'http://rubygems.org'
gem 'rails', '4.0.0.rc2'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'pg'
gem "paperclip", "~> 3.0"
gem 'rabl'
gem 'activerecord-postgres-hstore'
gem "bugsnag"
gem 'country_select'
gem 'bullet', group: :development
# Asset template engines
gem 'sass-rails', '~> 4.0.0.rc1'
gem 'coffee-rails', '~> 4.0.0.rc1'
gem 'uglifier', '>= 1.3.0'
gem 'twitter-bootstrap-rails'
gem 'therubyracer', :platform => :ruby
gem 'less-rails'
gem 'jquery-ui-rails'
gem 'jquery-rails'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
# Declarative Authorization
gem 'declarative_authorization'
gem 'protected_attributes'
# Authlogic
gem 'authlogic'
gem 'simple_form', '3.0.0.rc'
group :production do
end
group :test do
# Pretty printed test output
gem 'turn', :require => false
end
gem 'rubber'
gem 'open4'
gem 'gelf'
gem 'graylog2_exceptions', :git => 'git://github.com/wr0ngway/graylog2_exceptions.git'
gem 'graylog2-resque'
Source: (StackOverflow)
I have a collection of articles I want to show in my json response. I would also like to export a node about the type of json request asked.
index.json.rabl
collection @articles => :headlines
extends 'articles/show'
show.json.rabl
object @article
attributes :foo
So going to articles.json gives me:
{"headlines":[{"foo":thing1},{"foo":thing2}]}
What I would like to do is get results like this:
{"rss":{"name":"articles","woot":"what?"},
{"headlines":[{"foo":thing1},{"foo":thing2}]}
I have tried putting node(:rss) { "yadda yadda" } in the index.json.rabl file, but that only adds the node :rss into the each article.
I tried using
glue @article do
node(:rss) { "yadda yadda" }
end
in both the index and show files and neither worked as I was hoping.
I have tried numerous other things, but at this point I am only guess now.
Source: (StackOverflow)
I'm trying to render a rabl view to string in a rails 3.2 rake task. I'm rendering it to string in order to send some JSON through Pusher from a background task. I've looked at various render_to_string from rake task answers but none of them seem to work. Here is what I have thus far:
controller = PostsController.new
av = ActionView::Base.new(MyApp::Application.config.paths['app/views'].first,{},controller)
@post = post
Pusher["some channel"].trigger('new_post', av.render(:template => 'posts/show.json.rabl'))
With this attempt I get a ActionView::Template::Error exception and the error "undefined method `parameters' for nil:NilClass".
Source: (StackOverflow)
I have to following rabl code to generate some JSON data.
object @event
attributes :id, :EID, :name, :address, :description, :latitude, :longitude, :time, :created_at
node(:rsvp_count) { |event| event.rsvp_users.count }
node(:check_in_count) { |event| event.checkedin_users.count }
node(:FID) { |event| event.creater.FID if event.creater}
child :rsvp_users, :object_root => false do
extends 'users/index'
end
child :checkedin_users, :object_root => false do
extends 'users/index'
end
And the data it generates looks like this:
[
{
"event": {
"id": 2,
"EID": 123458,
"name": "event no.2",
"address": "189 elm st",
"description": "awesome event",
"latitude": 10,
"longitude": 10,
"time": "2013-10-20T18:00:00Z",
"created_at": "2013-08-15T21:06:21Z",
"rsvp_count": 3,
"check_in_count": 0,
"FID": 12345678,
"users": [
{
"id": 4,
"FID": 112233445,
"name": "name1",
"using_app": true
},
{
"id": 3,
"FID": 9999,
"name": "name2",
"using_app": false
},
{
"id": 2,
"FID": 123456789,
"name": "name3-robot",
"using_app": true
}
],
"checkedin_users": []
}
}
]
You can ignore the event
hash, the weird stuff is happening at the bottom in the 2 users
array.
So as you can see, the child rsvp_users
array is showing up with the name users
even if I set the root
param to "rsvp_users"
. However, for checkedin_users
array (which is empty right now), I don't need to do anything, and it's name is automatically checkedin_users
. What is happening here? Is it a bug in rabl? Or is it something that I am missing?
Source: (StackOverflow)
I have a scenario where I'd like to pass back a long message with my JSON. Instead of writing it out with string concatenation I'd rather put together an erb template that I can render into my JSON. Below is the code I'm currently trying:
object @invitation
node(:phone_message) do |invitation|
begin
old_formats = formats
self.formats = [:text] # hack so partials resolve with html not json format
view_renderer.render( self, {:template => "invitation_mailer/rsvp_sms", :object => @invitation})
ensure
self.formats = old_formats
end
end
Everything works as expected the first time this code is run, however, I run into problems the second time I run it because it says there is a missing instance variable (which I assume was generated and cached during the first run).
undefined method
_app_views_invitation_mailer_rsvp_sms_text_erb___2510743827238765954_2192068340
for # (ActionView::Template::Error)
Is there a better way to render erb templates into rabl?
Source: (StackOverflow)
Introduction
I have a (mostly) single-page application built with BackboneJS and a Rails backend.
Because most of the interaction happens on one page of the webapp, when the user first visits the page I basically have to pull a ton of information out of the database in one large deeply joined query.
This is causing me some rather extreme load times on this one page.
NewRelic appears to be telling me that most of my problems are because of 457 individual fast method calls.
Now I've done all the eager loading I can do (I checked with the Bullet gem) and I still have a problem.
These method calls are most likely ocurring in my Rabl serializer which I use to serialize a bunch of JSON to embed into the page for initializing Backbone. You don't need to understand all this but suffice to say it could add up to 457 method calls.
object @search
attributes :id, :name, :subscription_limit
# NOTE: Include a list of the members of this search.
child :searchers => :searchers do
attributes :id, :name, :gravatar_icon
end
# Each search has many concepts (there could be over 100 of them).
child :concepts do |search|
attributes :id, :title, :search_id, :created_at
# The person who suggested each concept.
child :suggester => :suggester do
attributes :id, :name, :gravatar_icon
end
# Each concept has many suggestions (approx. 4 each).
node :suggestions do |concept|
# Here I'm scoping suggestions to only ones which meet certain conditions.
partial "suggestions/show", object: concept.active_suggestions
end
# Add a boolean flag to tell if the concept is a favourite or not.
node :favourite_id do |concept|
# Another method call which occurs for each concept.
concept.favourite_id_for(current_user)
end
end
# Each search has subscriptions to certain services (approx. 4).
child :service_subscriptions do
# This contains a few attributes and 2 fairly innocuous method calls.
extends "service_subscriptions/show"
end
So it seems that I need to do something about this but I'm not sure what approach to take. Here is a list of potential ideas I have:
Performance Improvement Ideas
Dumb-Down the Interface
Maybe I can come up with ways to present information to the user which don't require the actual data to be present. I don't see why I should absolutely need to do this though, other single-page apps such as Trello have incredibly complicated interfaces.
Concept Pagination
If I paginate concepts it will reduct the amount of data being extracted from the database each time. Would product an inferior user interface though.
Caching
At the moment, refreshing the page just extracts the entire search out of the DB again. Perhaps I can cache parts of the app to reduce on DB hits. This seems messy though because not much of the data I'm dealing with is static.
Multiple Requests
It is technically bad to serve the page without embedding the JSON into the page but perhaps the user will feel like things are happening faster if I load the page unpopulated and then fetch the data.
Indexes
I should make sure that I have indexes on all my foreign keys. I should also try to think about places where it would help to have indexes (such as favourites?) and add them.
Move Method Calls into DB
Perhaps I can cache some of the results of the iteration I do in my view layer into the DB and just pull them out instead of computing them. Or I could sync things on write rather than on read.
Question
Does anyone have any suggestions as to what I should be spending my time on?
Source: (StackOverflow)
I'm looking to generate some basic documentation for a REST API created using Rails and RABL template views. Ideally what I'd like is a browsable RDoc-like format that shows the various endpoints and parameters as well as what attributes as returned by each request. Is there a tool that can help with this?
Source: (StackOverflow)
I have a RABL template as shown below
object @user
attributes :name
child :contacts do
# does not work
if contact.is_foo?
attributes :a1, :a2
else
attributes :a3, :a4
end
end
How do I access the Contact
object in the child
block of the template? I need to perform some conditional logic on the child instance.
Source: (StackOverflow)