setup rails-api gem with rabl-rails - ruby-on-rails

Im trying to use the rabl templating system from within rails-api.
rabl looks for templates in the view path, which rails-api omits.
How would i setup rabl-rails, i have included the below lines into my Controller.
include ActionController::MimeResponds
include ActionController::ImplicitRender
respond_to :json
However:
json: #deal uses standard rails rendered.
Renderer.json(#deal) in undefined, i assume it would be available with rabl.
Any help would be appreciated.

Add:
config.view_paths = ['/app/views']
to config/initializers/rabl_init.rb. No need for rabl-rails, use plain rabl, no need for those include's, no need for respond_to.
Render with:
render 'foo/bar' # will render app/views/foo/bar.rabl template

Related

Using mustache templates as partial views in Rails 4?

I'm trying to use mustache views in Rails 4 instead of some old partial views that hosted some HTML templates I am sharing with a javascript application.
Added config/initializers/mustache.rb
# Tell Rails how to render mustache templates
module MustacheTemplateHandler
def self.call(template)
#assigns contains all the instance_variables defined on the controller's view method
"Mustache.render(#{template.source.inspect}, assigns).html_safe"
end
end
# Register a mustache handler in the Rails template engine
ActionView::Template.register_template_handler(:mustache, MustacheTemplateHandler)
I named my template _template.mustache and put it the template in views/sales/_template.mustache and I can render it just fine from normal .html.erb with render partial: 'template'
Where do I put the Template.rb file for it to work with the mustache?
class Template < Mustache
def something
# return something
"WOW"
end
end
So, you can write this variables directly to yours controller.

locate file loaded on respond_with #jobs

On my project I have
respond_to :json
load_and_authorize_resource
def show
respond_with #job_pattern
end
as per tutorial here http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/
it works like this: when a request comes, for example with format xml, it will first search for a template at users/index.xml
so I checked for job_patterns/index.json but didnt find any file with this name
can anyone guide me where i can find the file or how the output is generated here if it is not with the file.
Because respond_to :json does not render a view, rather it calls render json: #job_pattern.
render json:#job_pattern calls #job_pattern.to_json and sets the JSON string as the response body. You can do the same with XML or YML.
This is an example of the rails convention over configuration philosophy - if there is a show.json.[erb|haml] it takes priority. Otherwise rails will look for an instance variable which corresponds with the name of the controller (#job or #jobs for index) and attempt to serialize it as JSON.
Further reading:
Justin Weiss: respond_to Without All the Pain
Rails Guides: Layouts and Rendering in Rails
In your case, your action is show so the template associated with is show.json in views/[namespace]/show.json.
You should create this template, or if this template is not found Rails will automatically invoke to_json on the object passed to respond_with.
Refer to documentation.
Recents version of Rails with generated scaffold use show.json.jbuilder as template file.
For more info about it:
jbuilder

Implementing pagination in a Ruby on Rails 4 API

I'm building an API on Rails using ActiveRecordSerializer for serialization. When I want to render a list of resources I use:
render json: #resources
This automatically detects that there is a serializer for the resource, and uses it.
Now I want to implement pagination, and my idea is having a class called PaginatedResponse, instantiate it and render it as a json like this:
render json: PaginatedResponse.new(#resources, <more meta information of the page>)
The problem is that when I use this, everything works well but the resources are not rendered using ActiveRecordSerializer, but a default serializer. I suspect that this is happening because PaginatedResponse does not extend ActiveRecord.
Any clue how can I solve this?
Rails 4 has introduced a new concept jbuilder by default. So just create index.json.jbuilder and put the json syntex based code. Just refer the default scaffold index json jbuilder below,
json.array!(#users) do |user|
json.extract! user, :name, :email, :phone, :native_place
json.url user_url(user, format: :json)
end
This is for rendering all users with his name, phone, native_place.
So remove the line
render json: #resources
from your code and implement the the new jbuilder concept.
The solution was including ActiveModel::SerializerSupport in PaginatedResponse to indicate ActiveRecordSerializer that a serializer should be used.

Why does Rails render RJS templates within a layout?

I need to do this for a controller which uses the active_scaffold gem. We have a controller that looked something like this:
class Admin::UsersController < ApplicationController
layout 'admin'
active_scaffold :users do |config|
config.search.columns = [:first_name, :last_name]
end
end
That worked great when we were on Rails 2.3.10, but we're upgrading to Rails 3.0.10. As part of the upgrade, I had to upgrade active_scaffold (currently installed from the rails-3.0 branch of git://github.com/activescaffold/active_scaffold) to be compatible. One problem we were having is that searching the table wasn't working. I would see in my log files:
Rendered <snip>/gems/active_scaffold-25b3d724f35b/frontends/default/views/list.js.rjs within layouts/admin (923.5ms)
Notice that it's rendering the RJS template with the layout specified in the controller. That seems like an unreasonable default to me. Shouldn't RJS templates render without a layout by default? Anyway, I fixed it as such:
class Admin::UsersController < ApplicationController
layout :admin_layout
private
def admin_layout
respond_to do |format|
format.js { false }
format.html { 'admin' }
end
end
end
That fixes the issues with search and pagination. (The RJS template is now rendered without a layout, so the browser can execute the resulting Javascript). I guess my question is, why do I have to tell Rails that it shouldn't render RJS templates with layouts? And is there a better solution? This feels like too much of a hack to me (the bad kind of hack---the kind of hack that will break in the future).
Okay, I figured it out. #numbers1311407's comment under my question led me to check the name of the layout template. It was layouts/admin.haml. With Rails 2, that layout was only rendering for HTML requests, but with Rails 3 it applies to all requests (because it doesn't specify a format type). I renamed it to layouts/admin.html.haml and it works with a simple layout 'admin' in my controller (as opposed to the hack that I had come up with in my question).
So the answer to the question, "Why does Rails render RJS templates within a layout?" is that the layout file was named such that it applies to all formats.
Answer your quastions:
1. There is no magic that Rails renderers layout in for JS format. That's bacause it is default to Rails to render layout with any template unless you explicitly tell to avoid it. You can just look into Rails sources in file: actionpack/lib/action_controller/metal/renderers.rb to see :js renderer.
2.Try to use:
respond_to do |format|
format.js { render *your_any_options*, layout: false }
end

Rails 3 rendering template missing without file ending

I have an action in my controller as below:
def show
#post = Post.find_by_setitle(params[:setitle])
if !#post
render 'error_pages/404'
return
end
respond_to do |format|
format.html
end
end
If the render error_pages/404 I get a template missing. Switching it to render error_pages/404.haml.html works fine.
Why is this?
N.B. There is no actual error_pages controller or model. Just a convenient place to keep them.
Edit: I'm using mongoid and hence don't have access to ActiveRecord. Controller base can't be looking for a particular ActiveRecord exception?
From the documentation
The render method can also use a view that’s entirely outside of your application (perhaps you’re sharing views between two Rails applications):
Rails determines that this is a file render because of the leading slash character. To be explicit, you can use the :file option (which was required on Rails 2.2 and earlier):
You need either to pass the :file option, or to start the location string with a slash. Alternatively, you could use the Rails functionality to rescue from errors, and recover from ActiveRecord::RecordNotFound with a 404. See this post for details.
You should probably use render :template => 'error_pages/404'.
I think Rails is looking for a partial called _404.
Try it out 1:
render 'error_pages/404' (and name the file _404.html.erb)
Try it out 2:
render :template => 'error_pages/404' (and name the file 404.html.erb i.e. no leading underscore)

Resources