Rails 3.0.9 + Devise + Cucumber + Capybara 臭名昭著的“没有路线匹配 /users/sign_out”

2024-03-25

我正在使用 devise 1.4.2 和 Rails 3.0.9、cucumber-rails 1.0.2、capybara 1.0.0。我有No route matches "/users/sign_out"当我点击注销时出现错误。我添加了:method => :delete经历这个之后到 link_to 标签所以问题(无路由匹配用户注销-devise-rails-3 https://stackoverflow.com/questions/6557311/no-route-matches-users-sign-out-devise-rails-3 ).

由于我用jquery替换了prototype,所以我也不得不改变

config.action_view.javascript_expansions[:defaults] = %w(jquery rails)

to

config.action_view.javascript_expansions[:defaults] = %w(jquery jquery_ujs)

解决rails.js not found 错误。

尽管通过上述更改,我能够成功注销并重定向到 root,但当我在 FireBug 中查看 localhost:3000/users/sign_out 请求的响应时,它显示相同的路由错误消息单击此处查看带有注释的屏幕截图 http://tardis1.tinygrab.com/auhm

通过设计成功实现对 Rails 3 应用程序的身份验证后,当我按照本教程使用 Cucumber + Capybara + RSpec 添加功能和规格时(github.com/RailsApps/rails3-devise-rspec-cucumber/wiki/Tutorial http://github.com/RailsApps/rails3-devise-rspec-cucumber/wiki/Tutorial),我收到以下错误

When I sign in as "[email protected] /cdn-cgi/l/email-protection/please"                              # features/step_definitions/user_steps.rb:41
Then I should be signed in                                            # features/step_definitions/user_steps.rb:49
And I sign out                                                        # features/step_definitions/user_steps.rb:53
  No route matches "/users/sign_out" (ActionController::RoutingError)
  <internal:prelude>:10:in `synchronize'
  ./features/step_definitions/user_steps.rb:55:in `/^I sign out$/'
  features/users/sign_out.feature:10:in `And I sign out'
And I should see "Signed out"                                         # features/step_definitions/web_steps.rb:105
When I return next time                                               # features/step_definitions/user_steps.rb:60
Then I should be signed out  

使用以下步骤定义“我退出”

Then /^I sign out$/ do
    visit('/users/sign_out')
end

我搜索了很多,发现这是因为 Rails 3 中不引人注目的 javascript 被用于“数据方法”属性,但我也在某处读到 Capybara 确实检查数据方法属性并做出相应的行为。但它对我不起作用,所以按照这篇文章水豚攻击:机架测试、丢失会话和 http 请求方法 http://blog.ardes.com/2010/4/28/capybara-and-rack-test-sessions-and-http-methods我将步骤定义更改为以下:

Then /^I sign out$/ do
    rack_test_session_wrapper = Capybara.current_session.driver
    rack_test_session_wrapper.process :delete, '/users/sign_out'
end

但我得到了未定义的方法process for Capybara::RackTest::Driver (NoMethodError).

遵循这个原则,我将上述步骤定义更改如下:

Then /^I sign out$/ do
    rack_test_session_wrapper = Capybara.current_session.driver
    rack_test_session_wrapper.delete '/users/sign_out'
end

这至少通过了“我注销”步骤,但注销后没有重定向到主页,下一步失败:

And I should see "Signed out"                                         # features/step_definitions/web_steps.rb:105
  expected there to be content "Signed out" in "YasPiktochart\n\n  \n      Signed in as [email protected] /cdn-cgi/l/email-protection. Not you?\n      Logout\n  \n\n    Signed in successfully.\n\n  Home\n  User: [email protected] /cdn-cgi/l/email-protection\n\n\n\n" (RSpec::Expectations::ExpectationNotMetError)
  ./features/step_definitions/web_steps.rb:107:in `/^(?:|I )should see "([^"]*)"$/'
  features/users/sign_out.feature:11:in `And I should see "Signed out"'

毕竟,我不得不在路由文件中添加“GET”方法来注销:

devise_for :users do get 'logout' => 'devise/sessions#destroy' end

修改了我的观点

<%= link_to "Logout", destroy_user_session_path, :method => :delete %>

to

<%= link_to "Logout", logout_path %>

并将我的步骤定义更改为以下:

Then /^I sign out$/ do
    visit('/logout')
end

这显然解决了所有问题,所有测试都通过了,并且 firebug 没有在sign_out上显示任何错误。但我知道使用“get”请求来销毁会话并不是一个好的做法,因为它是一种状态更改行为。

这是否是由于我使用的特定版本或 Rails、Devise、Cucumber-Rails 或 Capybara 造成的?我想使用 Devise 的默认sign_out 路由,而不是使用 get 方法覆盖它,并且能够使用 Cucumber 和 RSpec 执行 BDD。我是使用 Cucumber+Capybara 的新手,是否存在另一种方法来发送 POST 请求,而不是使用仅使用 GET 方法的“visit('/users/sign_out')”?


所以我发现

<%= link_to "Logout", destroy_user_session_path, :method => :delete %>

Rails 助手生成以下 html

<a rel="nofollow" data-method="delete" href="/users/sign_out">Sign out</a>

jquery_ujs.js 有以下方法将带有 data-method="delete" 属性的链接转换为表单并在运行时提交:

// Handles "data-method" on links such as:
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
handleMethod: function(link) {
var href = link.attr('href'),
method = link.data('method'),
csrf_token = $('meta[name=csrf-token]').attr('content'),
csrf_param = $('meta[name=csrf-param]').attr('content'),
form = $('<form method="post" action="' + href + '"></form>'),
metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';
if (csrf_param !== undefined && csrf_token !== undefined) {
metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
}
form.hide().append(metadata_input).appendTo('body');
form.submit();
}

而 Capybara helper Visit('/users/sign_out') 只需单击链接并向没有任何此请求路由的服务器发送 GET 请求即可。

与 link_to 帮助程序相反,button_to 帮助程序在渲染页面时在 html 中添加所需的表单,而不是依赖 javascript:

<%= button_to "Logout", destroy_user_session_path, :method => :delete %>

生成以下 html

<form class="button_to" action="/users/sign_out" method="post">
    <div>
        <input type="hidden" name="_method" value="delete">
        <input type="submit" value="Logout">
        <input type="hidden" name="authenticity_token" value="0Il8D+7hRcWYfl7A1MjNPenDixLYZUkMBL4OOoryeJs=">
    </div>
</form>

这样我就可以在“我退出”步骤定义中轻松使用水豚助手 click_button('Logout') 。

“link_to 使用除 GET 之外的任何方法实际上是一个坏主意,因为可以右键单击链接并在新选项卡/窗口中打开,并且因为这只是复制 url(而不是方法),所以它会因非 get 而中断链接...” http://railsforum.com/viewtopic.php?pid=123023#p123023

As 马克斯·威尔解释道 http://railsforum.com/viewtopic.php?pid=123023#p123023右键单击并在新选项卡中使用非获取数据方法打开 link_to 链接会导致链接损坏。

可以找到有关 link_to helper with ':method => :delete' 和 capybara 问题的一些更有用的讨论在这个链接上 https://github.com/jnicklas/capybara/issues/12

现在,我会坚持使用不带 :method 属性的简单 link_to 帮助程序,如果我想切换到非 get 方法进行删除,我更喜欢使用 button_to 。

同时我认为应该有一个相当于 Visit 的水豚助手来满足 data-method 属性发送 post 请求,这样就可以避免使用基于 javascript 的驱动程序进行集成测试。或者可能已经有一个我不知道的了。如果我错了请纠正我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails 3.0.9 + Devise + Cucumber + Capybara 臭名昭著的“没有路线匹配 /users/sign_out” 的相关文章

  • 如何将附加数据传递给设计邮件程序?

    我有一个可以处理许多子域的 Rails 应用程序 并且有多个使用不同域名运行的实时版本 这会导致 URL 介于 mywebsite com company1 mywebsite com company1 mytestwebsite com
  • FB API 调用中“无法代表此用户调用 API”

    我在调用 facebook API 时遇到问题 我正在使用 Koala 进行服务器端 api 调用 但最近在进 行 api 调用时遇到问题 所以我尝试绕过 koala 调用并使用 call 进行原始 api http 调用 但无济于事 当我
  • 如何检查一个数字是否包含在一个范围内(在一个语句中)?

    我正在使用 Ruby on Rails 3 0 9 我想检查某个数字是否包含在某个范围内 也就是说 如果我有一个变量number 5我想检查一下1 lt number lt 10并检索一个布尔值 如果number值包含在该范围内 我可以这样
  • 为什么“jQuery-Rails”经常位于资产组之外

    为什么我经常看到gem jquery rails之外的 assets group group assets do gem sass rails gt 3 1 0 gem coffee rails gt 3 1 0 gem uglifier
  • 如何在 Rails 3 中强制对 HTML 电子邮件进行字符编码?

    我正在使用 Rails 3 1 3 1 1 RC1 并且我已配置 ActionMailer 以使用windows 1252作为默认编码 外部要求 这与纯文本邮件完美配合 但一旦我发送 HTML 邮件 文本就会转换为UTF 8再次导致乱码文本
  • Rails 3:如何获取特定时区今天的日期?

    为了获得今天的日期 我这样做 Date today gt Fri 20 May 2011 我想获取特定时区的今天日期 例如 Melbourne 我的设置中有以下设置application rb config time zone Melbou
  • Rails 3:实时服务器推送?

    我正在尝试编写一个 Rails 3 应用程序 其中服务器可以将数据实时推送到多个客户端 我听说过 Juggernaut 但我也听说它不能与 Rails 3 一起使用 我尝试过 APE AJAX 推送引擎 但我不太幸运 我对 Rails 很陌
  • 如何验证数值的小数位数?

    我在中间进行了验证 如下所示 validates numericality of shoe size message gt Please input a number 但这还不够 因为用户可以输入一些值 例如 42 222222221212
  • 在代码中的其他地方设计渲染符号=>向上/形式部分

    我刚刚开始使用 Devise 和 Rails3 我已经完成了身份验证并正在工作并了解基础知识 截至目前 在代表我的主页 首页的主控制器中 我有两个链接 一个链接到 注册 gt sign up 另一个链接根据登录 注销 gt sign in
  • 如何使用 RSpec 检查 JSON 响应?

    我的控制器中有以下代码 format json render json gt flashcard gt flashcard lesson gt lesson success gt true 在我的 RSpec 控制器测试中 我想验证特定场景
  • 设备注册控制器获取零资源的自定义操作

    基本上我想要有两个单独的操作来更改密码和更改电子邮件 而不是只有一个 我已经更新了我的路由以指向继承自 Devise RegistrationsController 的新控制器 我的路线 rb devise for users contro
  • save_and_open_page 已停止提供我的 CSS

    我的测试设置工作得很好 每当我打电话时 都能提供正确格式的 css 页面save and open page从测试中 然后 我设置了一些 javascript 测试 并对我的设置进行了一些更改 抱歉 我无法详细说明所有内容 我没有足够详细地
  • 如何在 HAML 中为 Devise 生成视图

    这是我的 Gemfile gem haml group development do gem hpricot gem ruby parser end 然后我在终端 命令窗口中执行以下语句 bundle install rails gener
  • RSpec 请求规范发布一个空数组

    我目前正在 Rails 中开发 API 端点 如果我需要的数据无效 我想确保端点响应具有正确的错误状态 我需要一个 id 数组 无效值之一是空数组 Valid vendor district ids 2 4 5 6 Invalid vend
  • ActiveRecord:向包含的 ON 子句添加条件

    我有一个模型报价和另一个历史报价 一个报价有很多历史报价 现在 我想立即加载一组报价的某一天的历史报价 如果存在 为此 我认为我需要将这一天传递给 ON 子句 而不是 WHERE 子句 以便我获得所有报价 即使在给定日期没有历史报价时也是如
  • Rails 3.1 和图像资源

    我已将管理主题的所有图像放入名为 admin 的文件夹内的资产文件夹中 然后我像平常一样链接到它 Ruby image tag admin file jpg CSS logo background url assets images adm
  • 主页的 RefineryCMS 路线不起作用

    刚刚开始使用RefineryCMS 抱歉新手问题 它在本地运行良好 并幸运地部署在 Heroku Cedar 堆栈上 创建了一个名为 主页 的页面 pages home 响应良好 路线 rb root to gt pages home 并在
  • 如何在两个模型之间建立两个 has_many/belongs_to 关系?

    我有一个Project模型 以及一个Contact模型 项目模型有一个所有者和一个客户 两者都是Contacts 显然我遇到了一些不明确的事情 因为如果我有联系人并询问其项目 Rails 将不知道我询问的是它的项目是客户还是所有者 到目前为
  • 有没有办法使用 Rspec/Capybara/Selenium 将 javascript console.errors 打印到终端?

    当我运行 rspec 时 是否可以让 capybara selenium 向 rspec 报告任何 javascript console errors 和其他异常 我有一大堆测试失败 但当我手动测试它时 我的应用程序正在运行 如果不知道仅在
  • Rails 3 SSL 路由从 https 重定向到 http

    这个问题与此相关SO 问答 rails 3 ssl deprecation https stackoverflow com questions 3634100 rails 3 ssl deprecation建议使用routes rb和类似的

随机推荐