我正在尝试为使用Devise进行身份验证的Rails应用生成一个简单的宏。基本上我想确保当用户访问需要身份验证的页面时,他们会被重定向到登录页面。所以像这样:
it_requires_authentication_for :index, :new, :create, :update
这里期望的结果应该是显而易见的。然而我的问题是我无法想出将每个动作映射到适当的http方法的最佳方法(:get,:post等...)
我从这开始:
def it_should_require_authentication_for(*actions)
actions.each do |action|
it "should require authentication for #{action}" do
get action.to_sym
response.should redirect_to( new_user_session_path )
end
end
end
当然只有获得。有人可以告诉我如何为所有操作提供此宏吗?我假设我需要以某种方式测试动作是否适合特定方法,但我只是不确定。
非常感谢任何帮助。
答案 0 :(得分:1)
可能很老,但仍然可以帮助一些人。
这是在RSpec中定义宏的一种简单方法(即使对于控制器)。
http://osmose.6spot.com.br/2011/02/better-macros-with-rspec/
看,使用缺少的方法,您可以在记录的宏中记录特定的行为,例如,这是一个带有特定存根指令的脚手架控制器规范:
describe CustomersController do before(:each) do mock_filter(:require_user_owner) end # GET /customers get :index do default :stub => :off before(:each) do Customer.stub(:find_all_by_user_id) { [mock_customer] } end end # GET /customers/6 get :show, :id => 6 # GET /customers/new get :new # GET /customers/6/edit get :edit, :id => 6 # POST /customers post :create # PUT /customers/6 put :update, :id => 6 # DELETE /customers/6 delete :destroy, :id => 6 end
答案 1 :(得分:0)
我正在使用以下内容,直到我想出更优雅的东西:
# controller_macros.rb
def it_should_recognize_and_generate_routes_for(controller, routes)
describe "routing" do
routes.each do |route|
action = route[:action].to_s
method = route[:method] || :get
url = controller + (route[:url] || '')
params = route.reject {|k, v| [:action, :method, :url].include?(k) }
expected = { :controller => controller, :action => action }.merge(params)
it "should recognize and generate '#{action}'" do
{ method => url }.should route_to(expected)
end
end
end
end
# posts_controller_spec.rb
describe Forum::PostsController do
it_should_recognize_and_generate_routes_for('forum/posts', [
{ :action => :new, :url => '/new' },
{ :action => :create, :method => :post },
{ :action => :show, :url => '/1', :id => '1' },
{ :action => :index },
{ :action => :edit, :url => '/1/edit', :id => '1' },
{ :action => :update, :method => :put, :url => '/1', :id => '1' },
{ :action => :destroy, :method => :delete, :url => '/1', :id => '1' }
])
end
BTW我仍然需要扩展它以使用以下路线:
get 'login' => 'user_sessions#new'
答案 2 :(得分:0)
此Railscast涵盖了您正在寻找的内容:http://railscasts.com/episodes/157-rspec-matchers-macros
看起来您可以在控制器规范中使用所需的操作调用get方法,它将在控制器中调用相应的方法。
这是我的宏版本:
# Last argument is an optional hash of http arguments
# which is useful when working with nested models
#
# ex it_should_require_login_for_actions(:index,:new,:create, {:parent_id=>1})
#
def it_should_require_login_for_actions(*actions)
request_args = {:id => 1}
#If the last element of the actions list is a hash, then merge it
# with the existing request arguments
if actions[-1].is_a?(Hash)
request_args.merge!(actions.pop())
end
actions.each do |action|
it "#{action} action should require login" do
get action, request_args
response.should redirect_to(login_url)
end
end
end