测试自定义设计控制器时的ActionController :: RoutingError

时间:2012-10-22 11:44:13

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 rspec-rails

我正在尝试向Devise的注册控制器添加一个自定义操作,允许用户更改其密码(我不能使用默认registrations#edit,因为我需要一个只更改密码的表单,而不是电子邮件/用户名)。我在下面编写的实现在开发模式下工作,但是当我测试控制器时我得到了这个错误。

Failure/Error: get 'password'
ActionController::RoutingError:
  No route matches {:controller=>"registrations", :action=>"password"}

有我的代码(我试图跳过不相关的部分)

spec/controllers/registrations_controller_spec.rb

describe RegistrationsController do
  include Devise::TestHelpers

  before :each do
    request.env["devise.mapping"] = Devise.mappings[:users]
  end

  describe "GET 'password'" do
    it "..." do
                     # The problem is here,
      get 'password' # it raises ActionController::RoutingError
    end
  end
end

app/controllers/registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
  # ...
  def password
  end
end

config/routes.rb

devise_for :users, path: 'account', 
  controllers: { registrations: 'registartions' }, 
  skip: [:registartions, :sessions]

devise_scope :user do
  # ...
  scope '/account' do
    get 'password' => 'devise/registartions#password', as: "change_password
  do
end

spec_helper.rb

# ...
RSpec.configure do |config|
  # ...
  config.include Devise::TestHelpers, :type => :controller
end

3 个答案:

答案 0 :(得分:1)

您是否使用以下内容设置了config / routes.rb。

devise_for :users do
    get 'logout' => 'devise/sessions#destroy'
    get 'changepassword' => 'devise/registrations#edit'
    get 'access' => 'homepages#access'
    get 'history' => 'policies#history'
    get 'future' => 'policies#future'
  end
  devise_for :users, :controllers => { :sessions => :sessions }
  resources :users

我有同样的问题。我设置路线然后它为我工作:)

答案 1 :(得分:1)

我通常会为此添加注释,但是我要包含一个代码块,并且在评论中会变得混乱。

您似乎试图在GET上而不是在/password上预先形成/account/password

从我正在阅读的内容中,您已获得/account/password的映射:

devise_scope :user do # used to remove /users/ part from devise URLs
  # ...
  scope '/account' do # adds /account to URLs
    get 'password' => 'devise/registartions#password', as: "change_password"  
    # this will match /account/passwordAnswer

  do
end

因此,您应该删除范围,或者将测试中的get请求替换为:

get "/account/password", :user => @user

或者

get change_password_path(@user)

其中@userUser的模拟。

运行rake routes进行确认。

答案 2 :(得分:0)

我不喜欢在我的规范中使用get "/account/password"或路径。看似hacky。我在routes.rb文件中使用了更好的语法修复了类似的问题:

  1. path: 'account'
  2. 中使用devise_for选项
  3. 使用controllers: {registrations: 'registrations'}
  4. 明确设置自定义控制器

    所以我的routes.rb看起来像这样:

    devise_for  :users, 
                path: 'account', 
                path_names: {sign_in: 'login', sign_out: 'logout', sign_up: 'register'},                 
                controllers: {registrations: 'registrations'},
                skip: [:passwords]
    

    然后我可以在我的测试中使用get :new。更干净。

    希望这有助于其他人。

    我正在使用设计3.0。