EzDevInfo.com

rabl

General ruby templating with json, bson, xml, plist and msgpack support Building a Platform API on Rails | CodePath

Removing child root nodes in RABL

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)

How to paginate Rabl's collections

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)

Advertisements

RABL: JSON objects without root key

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)

Rabl Multi-model collection

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)

Conditionally include child nodes with RABL

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)

Is it possible to do a fragment caching in a rabl view?

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)

How to " order by id " JSON with Rabl

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)

undefined method `scan' for {"tooth"=>""}:Hash

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)

Using rabl and a collection, having trouble adding additional child node

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)

how to render a rabl view in a rake task?

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)

wrong child root name in rabl and can't set child root name

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)

Render ERB Template in RABL Template

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)

How to improve performance of single-page application?

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.

load times

NewRelic appears to be telling me that most of my problems are because of 457 individual fast method calls.

fast methid 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)

Generating REST API documentation from RABL view templates

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)

Accessing the child instance in a RABL template

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)