If user calls an URL application.com, it redirects to application.com/account/1/sessions/new.
I would like to substitute the redirect URL to application.com/sessions/new (host/account/:id -> host)
routes.rb
Rails.application.routes.draw do
get '/', to: 'dashboard#index'
resources :accounts do
resources :sessions
end
end
rails routes:
new_account_session GET /accounts/:account_id/sessions/new(.:format) sessions#new
application_controller.rb
class ApplicationController < ActionController::Base
...
#account has a column host to be identified if the user called URL host belongs to an existing account
def get_account_id
account_id = Account.find_by(host: request.host).id
end
def authorize
if session[:user_id]
redirect_to new_account_session_path(get_account_id)
return
end
end
end
Remove :sessions from inside :accounts
resources :accounts
resources :sessions
When you nest resources like that, you are basically saying that all routes to sessions should be linked to an account.
Related
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?
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
In my application I am using the Devise authentication gem which works really well. I also have built a static landing page which I currently have in the /public directory.
I can of course browser to localhost:3000/landing and see the page (as per the route below) but what I'm trying to achieve but cannot seem to figure out is how to setup my routes.rb file so that the landing.html file is the root, but when a user is logged in, their root becomes companies#index.
Here is my routes.rb file
Rails.application.routes.draw do
devise_for :users
get 'dashboard/index'
get '/landing', :to => redirect('/landing.html')
root 'companies#index'
resources :companies do
resources :shareholders
resources :captables do
post :subscribe_to_captable
resources :events do
post :lock_event
post :unlock_event
resources :transactions
end
end
end
end
Here is my application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
One way is to put the redirect inside your CompaniesController.rb index method do this.
CompanesController.rb (or whatever it is called)
def index
unless user_signed_in?
redirect_to landing_pages_path (or whatever the name of the route is)
end
end
Then change the route in the routes.rb file.
get '/landing', to: 'companies#landing' * change companies here to the name of the controller holding the landing page's method if it is not in the companies controller.
I have a link on my homepage - directing to my devise sign-in page
<%= link_to "Sign in", new_user_session_path %>
When I press it now I am however getting an error (it says it does not recognizes #user in my userscontroller). But I do not understand why I am redirected to my users controller, I should just go to my log in page right?
My routes are set up like this:
Rails.application.routes.draw do
get 'comments/create'
resources :users, only: [:show]
devise_for :users
resources :topics do
resources :posts, except: [:index]
end
resources :post, only: [] do
resources :comments, only: [:create, :destroy]
resources :favorites, only: [:create, :destroy]
post '/up-vote' => 'votes#up_vote', as: :up_vote
post '/down-vote' => 'votes#down_vote', as: :down_vote
end
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
Your route setup is correct, I believe you're being re-directed to your users controller because you're already signed in.
You can customise the page you're redirected to by modifying your ApplicationController as follows:
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
'/route_or_helper'
end
end
A good way to quickly test this is by opening an Incognito Tab in Chrome or similar (so that you're not logged in) which will then show you the login page.
It looks like there could be 2 conflicting routes.
The URL path for the users controller show action has the format /users/:id, where :id is a dynamic segment. This is configured by the resources :users, only: [:show] line in routes.rb.
The URL path for sign in (new_user_session_path) is /users/sign_in. This is configured by the devise_for :users line in routes.rb.
These 2 URL paths conflict. /users/sign_in matches the users controller format /users/:id, where the :id segment equals sign_in. Currently Rails will route requests for /users/sign_in to the UsersController#show action.
Try moving the devise_for :users line in routes.rb above the resources :users, only: [:show] line to change the routes' priority order. This will mean /users/sign_in URL requests are routed to the correct controller (the controller that's provided by Devise).
I find that when I use users_path(user) it returns /users.id where id is the id of the user but I want it to return /users/id. My config routes.rb looks like the following.
# config/routes.rb
Test::Application.routes.draw do
root to: "static_pages#home"
resources :users, only: [:index, :show]
devise_for :users
end
Use this for a path to a singular user:
user_path(user)
Use this for a path to all the users, or the index page:
users_path # no arguments