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

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

任何帮助是极大的赞赏。

4

3 回答 3

1

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

这是在 RSpec 中定义宏的一种很好且简单的方法(即使对于控制器也是如此)。

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

看,使用缺少的方法,您可以将特定行为记录到记录的宏中,例如,这是一个带有特定存根指令的脚手架控制器规范:

描述客户控制器做

  之前(:每个)做
    mock_filter(:require_user_owner)
  结尾

  # 获取/客户
  得到 :index 做
    默认 :stub => :off

    之前(:每个)做
      Customer.stub(:find_all_by_user_id) { [mock_customer] }
    结尾
  结尾

  # 获取/客户/6
  得到 :show, :id => 6

  # 获取/客户/新
  得到:新

  # 获取/客户/6/编辑
  得到 :edit, :id => 6

  # 发布/客户
  发布:创建

  # 放 /customers/6
  把 :update, :id => 6

  #删除/客户/6
  删除 :destroy, :id => 6

结尾
于 2011-02-07T21:28:12.157 回答
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

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

get 'login' => 'user_sessions#new'
于 2010-10-23T06:15:18.770 回答
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
于 2011-10-10T21:25:42.067 回答