How to model nested resources using RABL? - ruby-on-rails

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

Related

Why am I getting an uninitialized constant Api::SessionsController: error?

I keep getting this error message:
NameError - uninitialized constant Api::SessionsController:
But I've double checked and my routes configuration looks correct:
Rails.application.routes.draw do
namespace :api, defaults: {format: :json} do
resources :users, only: :create
resource :session, only: [:create, :destroy]
end
root 'static_pages#root'
end
My controller is also using the singular session:
class Api::SessionController < ApplicationController
def create
#user = User.find_by_credentials(
params[:user][:username],
params[:user][:password]
)
if #user
log_in(#user)
render 'api/users/show'
else
render json: ['Your request failed. Please try again.'], status: 401
end
end
And my folder structure is as follows:
Rails have very good official guide.
Session is a singular resource without referencing an ID.
Because you might want to use the same controller for a singular route (/account) and a plural route (/accounts/45), singular resources map to plural controllers. So that, for example, resource :photo and resources :photos creates both singular and plural routes that map to the same controller (PhotosController).
So you need to rename your controller to Api::SessionsController.
if wanna keep as you have set it up.
post 'session' => 'session#create', as: :session_create
destroy 'session' => 'session#destroy', as: :session_destroy

Rails API - No route matches [POST]

I am experimenting the Rails API with devise.
I am trying to create a POST request so that the user can autenticate using the email and password. To do so, I am using devise and simple token authentication
However, when I submit my POST request using postman, I get the error:
ActionController::RoutingError (No route matches [POST] "/v1/sessions"):
I think the issue is that is sending the post to: /v1/sessions rather than api/v1/sessions.
However, I do not understand why since I declared my routes such as: api-->v1-->sessions
Folder structure of controller
Routes
Rails.application.routes.draw do
# devise_for :users
namespace :api do
namespace :v1 do
resources :sessions, only: [:create, :destroy]
end
end
end
Controller
class V1::SessionsController < ApplicationController
def create
user = User.where(email: params[:email]).first
if user&.valid_password?(params[:password])
render json: user.as_json(only: [:email, :authentication_token]), status: :created
else
head(:unauthorized)
end
end
def destroy
end
end
shoud it be class Api::V1::SessionsController < ApplicationController instead?

Routing Error uninitialized constant rails

I'm getting this error.When I want to run te server on localhost:3000/api/v1/songs.json
Routing Error
uninitialized constant API::V1::SongsController.
Thats my routes.rb file:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :songs, only: [:index, :create, :update, :destroy]
end
end # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Routes
Routes match in priority from top to bottom
Helper HTTP Verb Path Controller#Action
Path / Url
Path Match
api_v1_songs_path GET /api/v1/songs(.:format)
api/v1/songs#index
POST /api/v1/songs(.:format)
api/v1/songs#create
api_v1_song_path PATCH /api/v1/songs/:id(.:format)
api/v1/songs#update
PUT /api/v1/songs/:id(.:format)
api/v1/songs#update
DELETE /api/v1/songs/:id(.:format)
api/v1/songs#destroy
and thats my SongsController:
class Api::V1::SongsController < Api::V1::BaseController
def index
respond_with Song.all
end
def create
respond_with :api, :v1, Song.create(song_params)
end
def destroy
respond_with Song.destroy(params[:id])
end
def update
song = Song.find(params["id"])
song.update_attributes(song_params)
respond_with song, json: song
end
private
def song_params
params.require(:song).permit(:id, :name, :singer_name, :genre, :updated_at, :tag)
end
end
I'm going to copy how we have this running, cause I cannot see a direct difference between your code and our code....
routes.rb
constraints subdomain: Settings.subdomains.api do # you can ignore this
namespace :api do
namespace :v1 do
resources :maps, only: [] do
collection do
get :world_map
end
end
end
end
maps_controller.rb
module Api
module V1
class MapsController < BaseController
def world_map; end
end
end
end
routes output
world_map_api_v1_maps GET /v1/maps/world_map(.:format) api/v1/maps#world_map {:subdomain=>"api"}
The spelling is really crucial from what I can see.
The directort structure for us:
app/controllers/api/v1/maps_controller.rb
So check those points and this should work because it's standard Rails magic.

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?

Resources