Render JSON instead of HTML as default? - ruby-on-rails

I try to tell rails 3.2 that it should render JSON by default, and kick HTML completely like this:
respond_to :json
def index
#clients = Client.all
respond_with #clients
end
With this syntax, I have to add .json to the URL. How can I achieve it?

You can modify your routes.rb files to specify the default format
routes.rb
resources :clients, defaults: {format: :json}
This will modify the default response format for your entire clients_controller

This pattern works well if you want to use the same controller actions for both. Make a web version as usual, using :html as the default format. Then, tuck the api under a path and set :json as the default there.
Rails.application.routes.draw do
resources :products
scope "/api", defaults: {format: :json} do
resources :products
end
end

If you don't need RESTful responding in your index action then simply render your xml response directly:
def index
render json: Client.all
end

Extending Mark Swardstrom's answer, if your rails app is an API that always returns JSON responses, you could simply do
Rails.application.routes.draw do
scope '/', defaults: { format: :json } do
resources :products
end
end

Related

dynamic urls in rails params

I am practicing to make API in rails. The api has currently only one end point which receives a url via get request. My routes are:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
namespace :api, defaults: { format: :json } do
namespace :v1 do # resources :orders
get "*link" => "application#parse_link"
end
end
end
My Application Controller Code:
require 'open-uri'
class Api::V1::ApplicationController < ActionController::Base
respond_to :json
# protect_from_forgery with: :exception
def parse_link
begin
url = URI.parse(params[:link])
doc = Nokogiri::HTML(open(url).read)
rescue
redirect_to 'http://localhost:3000/'
end
end
end
When I send urls like this:
http://localhost:3000/api/v1/http://stackoverflow.com/questions/41138538/dynamic-urls-in-rails-params
It works fine
But the following type of urls does not work:
http://localhost:3000/api/v1/http://stackoverflow.com/
In this case, it splits the link and give me these params
<ActionController::Parameters {"link"=>"http:/stackoverflow", "format"=>"com"} permitted: true>
As you can see it splits the given url and save half of it in link param and the ".com" part in format params.
Thanks
Try changing defaults to constraints:
Rails.application.routes.draw do
namespace :api, constraints: { format: :json } do
namespace :v1 do # resources :orders
get "*link" => "application#parse_link"
end
end
end
Notice: it will constraint format to be json, not only set it as default. Rails treated .com at end of your URL as response type.

Changing method of parameter specification in rails url

In my API, I've implemented the following way of showing a users account in JSON (very simple).
class API::V1::UsersController < ApplicationController
respond_to :json
def show
respond_with User.find(params[:id])
end
end
This is my routes.rb
Rails.application.routes.draw do
devise_for :users
# Api definition
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :users, :only => [:show]
end
end
end
As of now, this works by allowing my to browse to the URL: http://localhost/api/v1/users/1 to show the user account with ID 1. What I want is to be able to type http://localhost/api/v1/users/show?id=1 to allow for the possibility of specifying more than just the one parameter to the show method.
I've setup a rails application that expects the parameters to be specified in this way in the past but this time around it's not working. I'm assuming it's something to do with the way I've defined the route in my routes.rb (first time I'm using the resource do notation). Any help would be greatly appreciated. thanks!
Figured it out.
Routes.rb:
Rails.application.routes.draw do
devise_for :users
# Api definition
namespace :api, defaults: { format: :json } do
namespace :v1 do
#resources :users, :only => [:show]
get '/users/show/' => 'users#show'
end
end
end

Creating custom JSON response with Jbuilder

I am attempting to create a custom JSON response in Jbuilder. The scheme is pretty simple:
json.name = #locations.name
json.description = #locations.description
However, I am getting a Missing Template error because I have namespaced my route and cannot use the current index.son.jbuilder. Currently, my route is setup as
Rails.application.routes.draw do
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :locations
end
end
root 'locations#index'
resources :locations
...
And my controller is pretty simple:
module Api
module V1
class LocationsController < ApplicationController
respond_to :json
def index
#locations = Location.all
end
end
end
end
It does not currently use my index.son.jbuilder. I have attempted to create a new json file with matches the naming scheme api.v1.index.json.jbuilder but the error persists. What am I missing?

rails, query via url

I created my app using the following scaffold
rails generate scaffold server hostname:string
rails generate scaffold template remote_template_id:integer remote_template_name:string server:belongs_to
I edited the routes to be nested
resources :servers do
resources :templates
end
Now I edited stuff around and my app is working great. However, as this is back-end and not customer facing, I wish to able to run a query such as this, where 'templatename' at the end is an arbitrary string
http://127.0.0.1:3000/servers/1/templates/find_by_remote_template_name/templatename
Essentially, be able to search using the column name remote_template_name .
What would be the best way to approach this problem?
In your routes.rb file:
resources :servers do
resources :templates
match 'templates/search/:template_name', to: 'templates#search', via: :get
end
Then you should be able to query http://localhost:3000/servers/1/templates/search/whatever which will route to the #search action of the TemplatesController passing in params[:template_name]
Special Thanks to Jon.
Solution: the correct routing had to be set and the search function in the controller needed some tweaking
routes.rb:
resources :servers do
resources :templates
match 'templates/search/:template_name', to: 'templates#search', via: :get
end
And I had to add in the column name that is being searched in the TemplatesController
def search
#template = #server.templates.where("remote_template_name = ?", params[:template_name])
respond_to do |format |
format.html
format.json { render json: #template }
end
end

How to model nested resources using RABL?

I want to setup a nested route in my Rails project as illustrated here:
# config/routes.rb
DemoApp::Application.routes.draw do
namespace :api, defaults: {format: :json} do
namespace :v1 do
resources :places, only: [:index]
resources :users do
resource :places
end
end
end
devise_for :users, controllers: { sessions: "sessions" }
ActiveAdmin.routes(self)
end
I use RABL templates to render JSON contents. It might be that I misunderstand the purpose of child elements in RABL. As far as I understand they will not lead me to a RESTful path as show below. On the other hand please tell me if RABL does not support nested resources.
How can I output JSON for a nested route such as ... ? How can I write a RABL template which matches the route users/:id/places?
http://localhost:3000/api/v1/users/13/places.json
I do not want to display the user information. It should not be possible to retrieve user data via the following paths:
http://localhost:3000/api/v1/users/13.json
http://localhost:3000/api/v1/users.json
In the project I use CanCan 1.6.9. and Devise 2.2.3.
I've implemented something similar using before filters in the controller.
class Api::PlacesController < ApplicationController
before_filter :find_user
def index
if #user
#places = #user.places
else
...
end
end
private
def find_user
#user = User.find(params[:user_id]) if params[:user_id]
end
Then in api/places/index.json.rabl
collection #places
attributes :id, :name, etc

Resources