Changing method of parameter specification in rails url - ruby-on-rails

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

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

Custom Routing in Rails 5

I'm having some issues with custom routing. What I'm looking to do is remove the model from the route and dynamically use the record name.
so instead of:
site.com/events/my-event
I would like it to be:
site.com/my-event
I hacked this to work with the below code, only issue is I can't access my admin namespace as it's being treated as an event record (and any other route):
get('/:id', to: redirect do |params, request|
id = request.path.gsub("/", "")
"/events/#{id}"
end)
I know this redirect is not right, I'm just not well versed in routing options. How should this be done properly?
routes.rb
Rails.application.routes.draw do
resources :events, param: :id, path: "" do
get 'login', to: 'sessions#new', as: :login
get 'logout', to: 'sessions#destroy', as: :logout
post 'sessions', to: 'sessions#create', as: :session_create
end
namespace 'admin' do
root "events#index"
resources :sessions, only: [:create]
get 'login', to: 'sessions#new', as: :login
get 'logout', to: 'sessions#destroy', as: :logout
resources :events
end
end
Rails lets you specify what a routing URL should look like:
https://guides.rubyonrails.org/routing.html#translated-paths
You don't need redirect.
You need to match all requests to one controller/action.
get '/(*all)', to: 'home#app'
Inside this action check what is coming in params and render appropriate view.
PS: it will capture all requests, even for not found images, js, etc.
(1) To fix /admin to go to the right path, move the namespace line above the events resources so that it is matched first:
Rails routes are matched in the order they are specified 2.2 CRUD, Verbs, and Actions
# routes.rb
namespace :admin do
root "events#index"
#...
resources :events
end
resources :events, param: :name, path: ""
Use :param and :path to match for site.com/myevent instead of site.com/events/:id
Your events controller:
# events_controller.rb
class EventsController < ApplicationController
# ...
private
def set_event
#event = Event.find_by(name: params[:name])
end
end
Your admin events controller:
# admin/events_controller.rb
class Admin::EventsController < ApplicationController
# ...
private
def set_event
#event = Event.find params[:id]
end
end
TIP: To get a complete list of the available routes use rails routes in your terminal 5.1 Listing Existing Routes

What's the best way to redirect controller actions in multilingual Rails app?

In my multilingual Rails 5 app what's the best way to forward a URL like www.myapp.com/things to www.myapp.com/things/new?
This is my routes.rb file:
Rails.application.routes.draw do
scope "(:locale)", :locale => /#{I18n.available_locales.join("|")}/ do
resources :things, :only => [:new, :create]
end
end
I tried doing this in the routes file:
get '/things', :to => redirect('/things/new')
However, I couldn't get this work with locales.
Doing this in the ThingsController does work...
def index
redirect_to new_thing_path
end
... but seems wrong since I have to create an index action in my routes file.
Thanks for any help!

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

Resources