Creating custom JSON response with Jbuilder - ruby-on-rails

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?

Related

Undefined method `respond_to' for Api::V1::Controller

I already went through the topics here but the solutions mentioned didn't work out for me.
I want to create an API for my rails application and followed the tutorial from Railscast for API versioning. I am using Rails 5.
This is my routes.rb file:
Rails.application.routes.draw do
namespace :api, defaults: { format: 'json' } do
namespace :v1 do
resources :orders
end
end
end
And this the neworders_controller.rb under controllers/api/v1:
module Api
module V1
class OrdersController < ApplicationController
respond_to :json
def index
respond_with Order.all
end
end
end
end
When visiting http://localhost:3000/api/v1/orders I always get the following exception:
undefined method `respond_to' for Api::V1::OrdersController:Class Did you mean? respond_to?
I have already added responder to my gemfile but that didn't work out.
In your orders controller, you made a spelling mistake. Change
repsond_with Order.all
to
respond_with Order.all
Also, you made a spelling mistake in your routes file too. Change:
namespace :api, defaults: { format: 'josn' } do
to
namespace :api, defaults: { format: 'json' } do

Rails resource route under namespace leading to "not a supported controller name."

I'm building an API in Rails and I'd like for it to be versioned. My routes.rb file consists of:
Rails.application.routes.draw do
namespace :V1 do
resources :users
end
end
And I have my controller under /app/controllers/V1/users_controller.rb, which has this content:
module V1
class UsersController < ApplicationController
def index
render json: {message: "This is a test!"}
end
end
end
When I try to run the rails server on the command line I get the following error:
`default_controller_and_action': 'V1/users' is not a supported controller name. This can lead to potential routing problems. See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
I've looked at the link the error message gave me, however it seems to be how to specify a controller to use with a resource. Rather than doing that, can Rails not automatically determine it from my directory structure?
try this one:
Rails.application.routes.draw do
namespace :v1 do
resources :users
end
end

Ruby on Rails route to controller not working

Attempting to create an API using doorkeeper. When I sign into my account and the session user is authenticated and access my API on
http://localhost:3000/api/v1/trials
I get a routing error page saying "uninitialized constant TrialsController" and a rake routes listing. Including:
trials_path GET /api/v1/trials(.:format) trials#index
I am using rails version 4.0.3, ruby 2.0.0. This is my config/routes.rb file:
MyApp::Application.routes.draw do
devise_for :users
use_doorkeeper :scope => 'oauth2' do
end
root :to => 'welcome#index'
scope 'api' do
scope 'v1' do
resources :trials
end
end
end
My app/ dir contains:
app/
controllers/
application_controller.rb
welcome_controller.rb
api/
v1/
trials_controller.rb
My trials_controller.rb is:
module Api::V1
class TrialsController < ::ApplicationController
doorkeeper_for :all
def index
#trials = Trials.all
end
def show
...
end
...
end
end
UPDATE:
When I change the routes.rb to namespace the trails controller like so:
namespace :api do
namespace :v1 do
resources :trails
end
end
I get a "no route matches" error when attempting to access:
http://localhost:3000/api/v1/trials(.json)
(With or without the extension.)
I have also added to trials#index:
def index
#trials = Trials.all
respond_to do |format|
format.json { render :json => #trials }
format.xml { render :xml => #trials }
end
end
Also with no luck.
I'm not sure how it would play out against doorkeeper but I have a similar API structure in an app. I have the following in my routes (matching what Sergio notes)
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :api_controller_1
resources :api_controller_2
end
end
And here's how I build my API classes:
module Api
module V1
class ApiNamedController < ApplicationController
# code
end
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

Render JSON instead of HTML as default?

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

Resources