2010-10-19 39 views
0

我試圖爲使用Devise進行身份驗證的Rails應用程序生成一個簡單的宏。基本上我想確保當用戶訪問需要認證的頁面時,他們被重定向到登錄頁面。所以像這樣:爲控制器完善一個RSpec宏

it_requires_authentication_for :index, :new, :create, :update 

這裏的預期結果應該是顯而易見的。然而,我的問題是,我想不出來映射每個動作到其相應的HTTP方法的最佳途徑(:獲取,張貼等)

我開始了這一點:

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

我用以下,直到我拿出一些更優雅:

# 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' 
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 
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