Using an anonymous controller
controller
メソッドを使用して、記述されたクラスから継承する匿名コントローラーを定義します。これは、グローバルエラーハンドリングのような振る舞いを指定するのに便利です。
異なるベースクラスを指定する場合は、クラスを controller
メソッドに明示的に渡すことができます:
controller(BaseController)
基本的な型推論を無効にすることもできます。その場合、無名コントローラはデフォルトで述べられたクラスではなくApplicationControllerから継承するようになります:
RSpec.configure do |c|
c.infer_base_class_for_anonymous_controllers = false
end
RSpec.describe BaseController, type: :controller do
controller do
def index; end
# this normally creates an anonymous `BaseController` subclass,
# however since `infer_base_class_for_anonymous_controllers` is
# disabled, it creates a subclass of `ApplicationController`
end
end
Specify error handling in ApplicationController
with redirect
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base
class AccessDenied < StandardError; end
rescue_from AccessDenied, :with => :access_denied
private
def access_denied
redirect_to "/401.html"
end
end
RSpec.describe ApplicationController, type: :controller do
controller do
def index
raise ApplicationController::AccessDenied
end
end
describe "handling AccessDenied exceptions" do
it "redirects to the /401.html page" do
get :index
expect(response).to redirect_to("/401.html")
end
end
end
When I run rspec spec
Then the examples should all pass.
Specify error handling in ApplicationController
with render
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base
class AccessDenied < StandardError; end
rescue_from AccessDenied, :with => :access_denied
private
def access_denied
render "errors/401"
end
end
RSpec.describe ApplicationController, type: :controller do
controller do
def index
raise ApplicationController::AccessDenied
end
end
describe "handling AccessDenied exceptions" do
it "renders the errors/401 template" do
get :index
expect(response).to render_template("errors/401")
end
end
end
When I run rspec spec
Then the examples should all pass.
Specify error handling in a subclass
Given a file named "spec/controllers/application_controller_subclass_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base
class AccessDenied < StandardError; end
end
class FoosController < ApplicationController
rescue_from ApplicationController::AccessDenied,
:with => :access_denied
private
def access_denied
redirect_to "/401.html"
end
end
RSpec.describe FoosController, type: :controller do
controller(FoosController) do
def index
raise ApplicationController::AccessDenied
end
end
describe "handling AccessDenied exceptions" do
it "redirects to the /401.html page" do
get :index
expect(response).to redirect_to("/401.html")
end
end
end
When I run rspec spec
Then the examples should all pass.
Infer base class from the described class
Given a file named "spec/controllers/base_class_can_be_inferred_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base; end
class FoosController < ApplicationController; end
RSpec.describe FoosController, type: :controller do
controller do
def index
render :plain => "Hello World"
end
end
it "creates anonymous controller derived from FoosController" do
expect(controller).to be_a_kind_of(FoosController)
end
end
When I run rspec spec
Then the examples should all pass.
Use name
and controller_name
from the described class
Given a file named "spec/controllers/get_name_and_controller_name_from_described_class_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base; end
class FoosController < ApplicationController; end
RSpec.describe "Access controller names", type: :controller do
controller FoosController do
def index
@name = self.class.name
@controller_name = controller_name
render :plain => "Hello World"
end
end
before do
get :index
end
it "gets the class name as described" do
expect(assigns[:name]).to eq('FoosController')
end
it "gets the controller_name as described" do
expect(assigns[:controller_name]).to eq('foos')
end
end
When I run rspec spec
Then the examples should all pass.
Invoke around_filter
and around_action
in base class
Given a file named "spec/controllers/application_controller_around_filter_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base
around_action :an_around_filter
def an_around_filter
@callback_invoked = true
yield
end
end
RSpec.describe ApplicationController, type: :controller do
controller do
def index
render :plain => ""
end
end
it "invokes the callback" do
get :index
expect(assigns[:callback_invoked]).to be_truthy
end
end
When I run rspec spec
Then the examples should all pass.
Anonymous controllers only create resource routes
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
if defined?(ActionController::UrlGenerationError)
ExpectedRoutingError = ActionController::UrlGenerationError
else
ExpectedRoutingError = ActionController::RoutingError
end
RSpec.describe ApplicationController, type: :controller do
controller do
def index
render :plain => "index called"
end
def create
render :plain => "create called"
end
def new
render :plain => "new called"
end
def show
render :plain => "show called"
end
def edit
render :plain => "edit called"
end
def update
render :plain => "update called"
end
def destroy
render :plain => "destroy called"
end
def willerror
render :plain => "will not render"
end
end
describe "#index" do
it "responds to GET" do
get :index
expect(response.body).to eq "index called"
end
it "also responds to POST" do
post :index
expect(response.body).to eq "index called"
end
it "also responds to PUT" do
put :index
expect(response.body).to eq "index called"
end
it "also responds to DELETE" do
delete :index
expect(response.body).to eq "index called"
end
end
describe "#create" do
it "responds to POST" do
post :create
expect(response.body).to eq "create called"
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :create)
expect(response.body).to eq "create called"
end
end
end
describe "#new" do
it "responds to GET" do
get :new
expect(response.body).to eq "new called"
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :new)
expect(response.body).to eq "new called"
end
end
end
describe "#edit" do
it "responds to GET" do
get :edit, :params => { :id => "anyid" }
expect(response.body).to eq "edit called"
end
it "requires the :id parameter" do
expect { get :edit }.to raise_error(ExpectedRoutingError)
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :edit, :params => {:id => "anyid"})
expect(response.body).to eq "edit called"
end
end
end
describe "#show" do
it "responds to GET" do
get :show, :params => { :id => "anyid" }
expect(response.body).to eq "show called"
end
it "requires the :id parameter" do
expect { get :show }.to raise_error(ExpectedRoutingError)
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :show, :params => {:id => "anyid"})
expect(response.body).to eq "show called"
end
end
end
describe "#update" do
it "responds to PUT" do
put :update, :params => { :id => "anyid" }
expect(response.body).to eq "update called"
end
it "requires the :id parameter" do
expect { put :update }.to raise_error(ExpectedRoutingError)
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :update, :params => {:id => "anyid"})
expect(response.body).to eq "update called"
end
end
end
describe "#destroy" do
it "responds to DELETE" do
delete :destroy, :params => { :id => "anyid" }
expect(response.body).to eq "destroy called"
end
it "requires the :id parameter" do
expect { delete :destroy }.to raise_error(ExpectedRoutingError)
end
# And the rest...
%w{get post put delete}.each do |calltype|
it "responds to #{calltype}" do
send(calltype, :destroy, :params => {:id => "anyid"})
expect(response.body).to eq "destroy called"
end
end
end
describe "#willerror" do
it "cannot be called" do
expect { get :willerror }.to raise_error(ExpectedRoutingError)
end
end
end
When I run rspec spec
Then the examples should all pass.
Draw custom routes for anonymous controllers
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
RSpec.describe ApplicationController, type: :controller do
controller do
def custom
render :plain => "custom called"
end
end
specify "manually draw the route to request a custom action" do
routes.draw { get "custom" => "anonymous#custom" }
get :custom
expect(response.body).to eq "custom called"
end
end
When I run rspec spec
Then the examples should all pass.
Draw custom routes for anonymous controllers which don't inherit from application controller
Given a file named "spec/controllers/other_controller_spec.rb" with:
require "rails_helper"
class OtherController < ActionController::Base
end
RSpec.describe OtherController, type: :controller do
controller do
def custom
render :plain => "custom called"
end
end
specify "manually draw the route to request a custom action" do
routes.draw { get "custom" => "other#custom" }
get :custom
expect(response.body).to eq "custom called"
end
end
When I run rspec spec
Then the examples should all pass.
Draw custom routes for defined controllers
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
class FoosController < ApplicationController; end
RSpec.describe ApplicationController, type: :controller do
controller FoosController do
def custom
render :plain => "custom called"
end
end
specify "manually draw the route to request a custom action" do
routes.draw { get "custom" => "foos#custom" }
get :custom
expect(response.body).to eq "custom called"
end
end
When I run rspec spec
Then the examples should all pass.
Works with namespaced controllers
Given a file named "spec/controllers/namespaced_controller_spec.rb" with:
require "rails_helper"
class ApplicationController < ActionController::Base; end
module Outer
module Inner
class FoosController < ApplicationController; end
end
end
RSpec.describe Outer::Inner::FoosController, type: :controller do
controller do
def index
@name = self.class.name
@controller_name = controller_name
render :plain => "Hello World"
end
end
it "creates anonymous controller derived from the namespace" do
expect(controller).to be_a_kind_of(Outer::Inner::FoosController)
end
it "gets the class name as described" do
expect{ get :index }.to change{
assigns[:name]
}.to eq('Outer::Inner::FoosController')
end
it "gets the controller_name as described" do
expect{ get :index }.to change{
assigns[:controller_name]
}.to eq('foos')
end
end
When I run rspec spec
Then the examples should all pass.
Refer to application routes in the controller under test
Given a file named "spec/controllers/application_controller_spec.rb" with:
require "rails_helper"
Rails.application.routes.draw do
match "/login" => "sessions#new", :as => "login", :via => "get"
end
RSpec.describe ApplicationController, type: :controller do
controller do
def index
redirect_to login_url
end
end
it "redirects to the login page" do
get :index
expect(response).to redirect_to("/login")
end
end
When I run rspec spec
Then the examples should all pass.