I'm using this gem, in my rails-api project.
I'm trying to restrict some routes base on user roles. So I create a constraint
class BackendConstraint
def self.matches?(request)
current_user = request.env['warden'].user
return false if current_user.blank?
current_user.role?(:admin)
end
end
But request.env['warden'].user is always null. Am I'm missing something?
Thanks
I had the same problem with flipper's suggested filter, but found devise has a one liner solution: https://github.com/plataformatec/devise/wiki/How-To:-Define-resource-actions-that-require-authentication-using-routes.rb
eg
authenticate :user do
resources :fjords, only: [:new, :create, :edit, :update, :destroy]
end
resources :fjords, only: [:index, :show]
Related
I'm new in rails, the thing here is that I'm tryin to create a budget with an specific user ID but when I try to create a budget with postman:
{
"name": "Segundo", "description": "segundo"
}
it sends me that message error:
undefined method `budget' for nil:NilClass
Extracted source (around line #14):
def create
#budget = current_user.budget.build(budget_params)
#budget.save
end
My controller:
class BudgetsController < ApplicationController
before_action :find_id, only: [:show, :edit, :update, :destroy]
def budget_params
params.require(:budget).permit(:name, :description)
end
def new
#budget = current_user.budgets.build
render layout: false
end
def create
#budget = current_user.budgets.build(budget_params)
#budget.save
end
def show
render json: #budget
end
def edit
render layout: false
end
def update
#budget.update(budget_params)
end
def destroy
#budget.destroy
end
def find_id
#budget = Budget.find(params[:id])
end
end
My routes:
Rails.application.routes.draw do
resources :sessions, only: [:create]
resources :registrations, only: [:create]
delete :logout, to: "sessions#logout"
get :logged_in, to: "sessions#logged_in"
root to: "static#home"
#budgets
resources :budgets
#expenses
resources :expenses, only: [:create, :show, :edit, :update, :destroy]
#incomes
resources :incomes, only: [:create, :show, :edit, :update, :destroy]
#investments
resources :investments, only: [:create, :show, :edit, :update, :destroy]
end
can anyone help me with this?
If you use postman and want to save something in the database that in normal flow only registered users can save, you need to send user session cookies value with your request.
https://learning.postman.com/docs/sending-requests/cookies/.
If you don't send session cookies with your request that means that request is sent by a guest, not logged user. The current_user is nil, so you get undefined method `budget' for nil:NilClass error.
You don't define current_user anywhere. You should probably set a before_action where you save the current user, or a base controller your budget controller can inherit from (if you are going to have more controllers that utilize current_user).
I have an application that lists all the subaccounts under a main account. However when I click the subaccount, instead of going to do accounts/1/subaccounts/1 I want it to go to subaccounts/1. When I use the for_each statement I get the following error. How can I click on a nested route and have it go to just subaccounts/1 instead of accounts/1/subaccounts/1?
<% #subaccounts.each do |sa| %>
<%= link_to "#{sa.name}", subaccount_path(sa) %>
<% end %>
Routes.rb
resources :subaccounts
resources :accounts do
resources :subaccounts
end
Subaccounts controller
before_action :set_account, only: [:show, :edit, :new, :create]
before_action :set_subaccount, only: [:show, :edit, :update, :destroy]
def show
end
private
def set_account
#account ||= Account.find(params[:account_id])
end
def set_subaccount
#subaccount ||= #account.subaccounts.find(params[:id])
end
def subaccount_params
params.require(:subaccount).permit(:name, :state)
end
The issue you are facing is due to same controller action for 2 different routes. You can fix it by either adding another controller for nested route
resources :accounts do
resources :subaccounts, controller: 'accounts_subaccounts'
end
Or handle exception and check for #account (least preferred way / bad practice)
#account ||= Account.find(params[:account_id]) rescue nil
With handling with rescue you need to handle #account everywhere.
You can also trigger set_account method when params[:account_id].present? which will also work for you.
Hello I'am using clearance gem for user authentication.
So far everything works perfect, but I'am confused why even after setting the root routes for my pages index view, it still redirects me to the sign_in page of clearance gem.
I have looked at github documentation notes, and it list no other work around for this. I'am doing something wrong?
Here is what my routes.rb file looks like:
Rails.application.routes.draw do
resources :passwords, controller: "clearance/passwords", only:
[:create, :new]
resource :session, controller: "clearance/sessions", only: [:create]
resources :users, controller: "clearance/users", only: [:create] do
resource :password,
controller: "clearance/passwords",
only: [:create, :edit, :update]
end
get "/sign_in" => "clearance/sessions#new", as: "sign_in"
delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out"
get "/sign_up" => "clearance/users#new", as: "sign_up"
root 'pages#index'
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
end
the clearance require_login before_action must be active for that route. Did you add that before action to application controller? Does PagesController inherit from ApplicationCobtroller? If so, you need to add skip_before_action :require_login to your pages controller. Perhaps scoped to the particular pages controller action you want unprotected.
Say I have a module name Server that was created with a scaffold. I want the url 'www.example.com/server/' to be redirected to the first Server object that exists. So for example to be redirected to 'www.example.com/server/2'.
How could this be done with routes.rb (or any other way)?
route.rb:
Rails.application.routes.draw do
resources :servers
end
Server controller:
class ServersController < ApplicationController
before_action :set_server, only: [:show, :edit, :update, :destroy]
# GET /servers
# GET /servers.json
def index
#servers = Server.all
end
....
your can put
redirect_to server_path(Server.first) and return
inside your index method it'll redirect you when ever index action is called.
and just to extent #richfisher's answer (which might be a more appropriate way to do it.)
resources :servers, except: [:index] # this won't generate redundant routes
get '/servers/' => 'servers#first' #note this is now accessible via "server_path" instead of "servers_path" helper.
For what it's worth, I'd do this:
#config/routes.rb
resources :servers, except: :index do
get "", action: :show, id: Server.first.id, on: :collection
end
This will allow you to use the show action in place of index in a super efficient setup:
#app/controllers/servers_controller.rb
class ServersController < ApplicationController
def show
#server = Server.find params[:id]
end
end
I have simple controller and routes file.
In my route and controller i have created a module. I wrote a simple method which is redirecting me show. I am not sure why.
Controller
module Seller
class CampaignsController < Seller::BaseController
before_action :confirm_logged_in
def viewAllCampaigns
#campaigns = Campaign.all
end
def show
end
end
end
Routes file
scope module: 'seller' do
#namespace :power do
resources :dashboard, only: [:index]
resources :sessions, only: [:create, :destroy]
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
end
Output
Started GET "/campaigns/viewAllCampaigns" for 127.0.0.1 at 2015-10-12 17:39:43 +0500
Processing by Seller::CampaignsController#show as HTML
Parameters: {"id"=>"viewAllCampaigns"}
Rendered seller/campaigns/show.html.erb (0.1ms)
I am hitting http://localhost:3000/campaigns/viewAllCampaigns in browser.
Ideally your routes should be defined like this.
resources :campaigns, only: [:index, :create, :show, :update, :destroy] do
get 'viewAllCampaigns', on: :collection
end
The first comment on the routes.rb file is The priority is based upon order of creation: first created -> highest priority. This is the reason your route is redirecting to show. Rails is treating this url as campain/:id.
Routes are tested in order, from top to bottom. The show route you've added for the campaigns resource will look for urls matching this pattern:
/campaigns/:id
/campaigns/viewAllCampaigns matches this, so it will do the show action., with params[:id] = "viewAllCampaigns"
Move the special case route up above the resources#campaigns route to fix this, then it will catch the url first.
get 'viewAllCampaigns' => 'campaigns#viewAllCampaigns'
resources :campaigns, only: [:index, :create, :show, :update, :destroy]
It takes the following get request as a show action because show expects campaigns/:id, and it assumes 'viewAllCampaigns' is an id in this instance:
/campaigns/viewAllCampaigns
Your link_to should just be pointing to the following:
'/viewAllCampaigns'
Your route structure isn't really RESTful, but that's a separate topic.