完善控制器的 RSpec 宏

发布于 2024-09-28 01:31:08 字数 628 浏览 2 评论 0原文

我正在尝试为使用 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

当然,它只执行get。有人可以告诉我如何为所有操作提供这个宏吗?我假设我需要以某种方式测试特定方法的操作是否正确路由,但我不太确定。

非常感谢任何帮助。

I'm trying to generate an easy macro for a Rails app that uses Devise for authentication. Basically I want to ensure that when a user accesses a page that requires authentication, they're redirected to the login page. So something like this:

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

The desired results here should be obvious. My problem however is that I can't think of the best way to map each action to its appropriate http method (:get, :post etc...)

I started out with this:

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

Which of course only does the get. Can someone tell me how I might provide this macro for all actions? I'm assuming I need to somehow test if the action routes properly for a particular method, but I'm just not really sure.

Any help is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时常饿 2024-10-05 01:31:08

也许老了,但仍然可以帮助一些人。

这是在 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

maybe old, but still can help some.

Here is a nice and easy way to define macros in RSpec (even for controllers).

http://osmose.6spot.com.br/2011/02/better-macros-with-rspec/

Look, using method missing you are able to record specific behavior into your recorded macros, for instance, this is a scaffold controller spec with a specific stub instruction:

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
街角迷惘 2024-10-05 01:31:08

我正在使用以下内容,直到我想出更优雅的东西:

# 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

顺便说一句,我仍然需要扩展它以使用以下路线:

get 'login' => 'user_sessions#new'

I'm using the following until I come up with something more elegant:

# 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 I still have to extend it to work with routes like:

get 'login' => 'user_sessions#new'
蓝礼 2024-10-05 01:31:08

此 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

This Railscast covers exactly what you are looking for: http://railscasts.com/episodes/157-rspec-matchers-macros

It looks like you can just call the get method with your desired action in your controller spec, and it will call the appropriate method in the controller.

Here is my version of the macro:

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文