No route matches {:action=>"show" in RSpec, fine in browser - ruby-on-rails-4

I have a users_controller.rb that includes:
before_action :set_user, only: [:show, :edit, :update, :destroy]
load_and_authorize_resource
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
private
def set_user
#user = User.find(params[:id])
end
My config/routes includes:
devise_for :users
devise_scope :user do
authenticated :user do
root 'switchboard#show', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
resources :users
When I navigate to http://localhost:3000/users I get a list of the users as I expect. But when I run the RSpec test:
require 'rails_helper'
RSpec.describe UsersController, :type => :controller do
describe "GET show" do
it "returns http success" do
get :show
expect(response).to be_success
end
end
end
I get the error No route matches {:action=>"show", :controller=>"users"} on the RSpec line get :show.
I've found countless queries about No route matches {:action=>"show", each one with a different cause, but none of them seems to match mine. What do I do to fix this (other than not test the feature!)

Because you have no route that matches controller user action show
However, you do have a route that matches user/:id (it's the :id you're missing)
So you could do...
get :show, id: 1

Related

Best in place sending routing error

I have a user controller as follows. I want to use the best_in_place gem for editing name and bio in profile page. I have followed Ryan Bates railscast but its not working correctly. When I tried to see the error through the chrome inspector I see best in place is requesting url http://localhost:3001/user/3 and now throwing 404 not found error.
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!, only: [:profile]
respond_to :json, :html
def profile
#user = current_user
end
def show
#user = User.find(params[:id])
end
def update
if current_user.update(user_params)
respond_with current_user
end
end
def edit
#user = current_user
end
private
def user_params
params.require(:user).permit(:name, :bio)
end
end
routes.rb
Rails.application.routes.draw do
resources :user
end
In routes.rb you configured routes as resources :user which gives following routes:
But we can see your controller is UsersController so you have to configured your routes as: resources :users Which gives following routes:
Hope this may solve your problem.

Rails - Adding a "Delete" button to a Users Timetable

Hi I have a rails App where Users can have a timetable with a one to many relationship.
When i add this
<%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
to _user.html it renders a delete link which deletes a user no problem
but when i add this
<%= link_to "delete", timetable, method: :delete,
data: { confirm: "You sure?" } %>
to _timetable.html.erb it throws an error
ActionController::RoutingError (No route matches [DELETE] "/timetable.4"):
My Routes.rb
get 'password_resets/new'
get 'password_resets/edit'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'timetable' => 'timetables#new'
get 'signup' => 'users#new'
get 'mobile' => 'users#mobile'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :timetables
resources :users
resources :projects
Timetable Controller
class TimetablesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#timetables = current_user.timetables.find(current_user)
end
def new
#user = User.find(current_user)
#timetable = Timetable.new
#timetables = #user.timetables.paginate(page: params[:page], per_page: 1)
end
def feed
Timetable.where("user_id = ?", id)
end
def show
#feed_items3 = current_user.feed.paginate(page: params[:page])
#timetable = current_user.timetables.find(params[:id])
end
def create
#timetable = Timetable.new(timetable_params)
#user = User.find(current_user)
if current_user.timetables.create(timetable_params)
flash[:success] = "Timetable created!"
redirect_to timetable_path
else
flash[:success] = "Timetable not created!"
redirect_to timetable_path
end
end
def destroy
#timetable = Timetable.find(params[:id])
#timetable.destroy
redirect_to timetables_path, notice: "The timetable #{#timetable.name} has been deleted."
end
private
def timetable_params
params.require(:timetable).permit(:name, :attachment, :id)
end
def correct_user
#project = current_user.projects.find_by(id: params[:id])
redirect_to root_url if #project.nil?
end
end
Without seeing your Controllers it is hard to be sure, but I would look at a few areas:
Specifying the path & the timetable object to be deleted:
<%= link_to "Delete Timetable", timetable_path(timetable), :method => :delete %>
Ensure that the destroy action for the timetable sits within the timetable_controller
Regarding your routes.rb file I am not sure why you need:
get 'timetable' => 'timetables#new'
and then also
resources :timetables
This is duplication - why not try use 'only' (edit to your preference):
resources :timetables, only: [:index, :new, :create, :destroy]

Devise::InvitationsController reports Unpermitted parameters

I have a problem with devise_invitable 1.4.0 and strong parameters when I add additional custom parameters and I really hope somebody can guide me in the right direction. I am able to send invitations, but when an invited user accepts an invitation and enters a desired username, maiden name, password and confirmed password, the following error is shown:
Processing by Users::InvitationsController#update as HTML
Unpermitted parameters: username, name
The user is created as expected, but the 'username' and 'name' columns in the database are empty.
I have tried all the suggestions I could find for related issues, but none of the worked. I have noticed that if I change the app/controllers/users/invitations_controller.rb file in any way (eg inserting a blank space on an empty line) without restarting the webserver (Thin) the problem disappears - but the problem reappears when the webserver is restarted.
The various relevant files look like this:
routes.rb:
Rails.application.routes.draw do
root to: 'visitors#index'
#Tell rails to use the Devise controllers that were generated with this command:
# > rails generate devise:controllers users
#Using these generated controllers allows us to overwrite anything in the deault controllers.
devise_for :users, :path_names => {:sign_in => 'login', :sign_out => 'logout'}, controllers: {confirmations: "users/confirmations", passwords: "users/passwords", registrations: "users/registrations", sessions: "users/sessions", unlocks: "users/unlocks", :invitations => 'users/invitations'}
resources :users
end
config/initializers/devise.rb
Devise.setup do |config|
...
...
config.scoped_views = true
config.authentication_keys = [ :username ]
...
...
end
app/controllers/users/invitations_controller.rb:
class Users::InvitationsController < Devise::InvitationsController
private
# this is called when creating invitation
# should return an instance of resource class
def invite_resource
## skip sending emails on invite
resource_class.invite!(invite_params, current_inviter) do |u|
u.tenant = current_inviter.tenant
u.role = :user
end
end
def after_invite_path_for(resource)
users_path
end
def resource_params
params.permit(user: [:name, :email,:invitation_token, :username])[:user]
end
end
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
around_filter :scope_current_tenant
before_filter :configure_permitted_parameters, if: :devise_controller?
if Rails.env.development?
# https://github.com/RailsApps/rails-devise-pundit/issues/10
include Pundit
# https://github.com/elabs/pundit#ensuring-policies-are-used
# after_action :verify_authorized, except: :index
# after_action :verify_policy_scoped, only: :index
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
end
#############################################################################
private
#############################################################################
if Rails.env.development?
def user_not_authorized
flash[:alert] = "Access denied." # TODO: make sure this isn't hard coded English.
redirect_to (request.referrer || root_path) # Send them back to them page they came from, or to the root page.
end
end
def current_tenant
#current_tenant ||= current_user.tenant unless current_user.nil?
end
helper_method :current_tenant
def scope_current_tenant(&block)
if current_tenant.nil?
scope_visitor_schema
yield
else
current_tenant.scope_schema("public", &block)
end
end
def scope_visitor_schema()
original_search_path = ActiveRecord::Base.connection.schema_search_path
ActiveRecord::Base.connection.schema_search_path = 'public'
ensure
ActiveRecord::Base.connection.schema_search_path = original_search_path
end
#############################################################################
protected
#############################################################################
def configure_permitted_parameters
# Only add some parameters
devise_parameter_sanitizer.for(:account_update).concat [:name, :email]
# Override accepted parameters
devise_parameter_sanitizer.for(:accept_invitation) do |u|
u.permit(:name, :username, :password, :password_confirmation,
:invitation_token)
end
end
end
app/models/user.rb:
class User < ActiveRecord::Base
enum role: [:user, :admin]
after_initialize :create_tenant, :if => :new_record?
belongs_to :tenant
# has_many :invitations, :class_name => self.to_s, :as => :invited_by
scope :unconfirmed, -> { where(confirmed_at: nil) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
# validate :username, presence: true, uniqueness: true, format: { with: /[a-zA-Z0-9]{4,20}/ }
def displayed_username
username.nil? ? "N/A" : username
end
def displayed_name
name.nil? ? "N/A" : name.titleize
end
def create_tenant
#The create_tenant method will also be called when looking up a user,
#so the following ensures a tenant is only created if it does not already
#exist - and the user has not been invited and assigned to an existing tenant:
if self.tenant.nil?
#Set role to 'admin' if a tenant is about to be created:
self.role = :admin #if self.tenant.nil?
self.tenant = Tenant.new
end
end
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :invitable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
end
I finally found a fix, which was to place the parameter sanitizer directly in users/invitations_controller.rb instead of the application_controller.rb.
class Users::InvitationsController < Devise::InvitationsController
before_filter :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.for(:accept_invitation) do |u|
u.permit(:username, :name, :email, :password, :password_confirmation, :invitation_token)
end
end
end

Add 'clone' route to existing restful controller

I am tryting to add this method to a restful controller (also has working methods for :index, :new, :create, :edit, :update and :destroy):
class Admin::ClassSectionsController < ApplicationController
def clone
#class_section = ClassSection.find(params[:id])
#class_section = ClassSection.new(#class_section.attributes)
render :new
end
end
And the following for the config/routes.rb:
Utg::Application.routes.draw do
devise_for :users
root to: "home#index"
namespace :admin do
resources :class_sections, except: [:show]
end
resources :class_sections, only: [:index, :show]
end
How do I add the route for 'admin/class_section/:id/clone'?
namespace :admin do
get "class_sections/:id/clone", to: "class_sections#clone", as: "class_sections_clone"
end

Routing to different pages based on whether or not user is logged in. - Rails4

in config/routes.rb, I have:
root to: "pages#home"
get "/visitor" => "pages#visitor"
In my controllers/application_controller.rb, I have:
before_filter :route_relative_to_login_state_and_role
private
def route_relative_to_login_state_and_role
if current_user
redirect_to root_path
else
redirect_to visitor_path
end
end
In my controllers/pages_controller.rb, I have:
class PagesController < ApplicationController
before_action :authenticate_user!, :only => [:home]
def home
#page_title = t ('home_page_title')
end
def visitor
#page_title = t ('visitor_page_title')
end
end
Here's my views/pages/home.html.erb
<h1><%= #page_title %></h1>
Here's my views/pages/visitor.html.erb
<h1><%= #page_title %></h1>
This is from the output of rake routes:
visitor GET /visitor(.:format) pages#visitor
When I start the server and point my browser to htp://localhost:3000 the browser tells me that the page is not redirecting properly. Here's what the log file says:
Started GET "/visitor" for 127.0.0.1 at 2014-05-15 10:37:46 -0700
Processing by PagesController#visitor as HTML
Redirected to http://localhost:3000/visitor
Filter chain halted as :route_relative_to_login_state_and_role rendered or redirected
if i understand you correctly if the user logged_in you what to redirect to page and if not to another page, what you did is wrong and you can control it from ApplicationController and do something like:
before_filter :check_user
def check_user
if current_user
## this is logged user
redirect_to first_path
else
## this is unlogged user
redirect_to second_path
end
end
hope that's what you meant.