在 rspec 支持文件的扩展 类 中获取当前设计用户

Get current devise user in extended classes in rspec support file

在我的 rails 应用程序中,我使用 devise 进行用户身份验证。我还在整个网站上使用 i18n,每个用户都可以在用户设置中选择她或他的特定语言。如果用户浏览具有给定语言环境设置的网站,或者它是访客并且使用默认语言环境,我不希望该语言环境显示在 url.

这是一个例子:

客人使用英语(默认)版本,因此 url 类似于 "anything.com/users/42",但如果她或他更改为法语(不是永久在设置中,而是通过单击 link 到法文版),url 变为 "anything.com/fr/users/42"。如果该用户已登录并选择法语作为默认语言,则相反。

这是通过我application_controller

中的以下几行实现的
# app/controllers/application_controller.rb
def default_locale
  current_user ? current_user.locale : I18n.default_locale
end
helper_method :default_locale

def default_url_options options={}
  (I18n.locale.to_s.eql?(default_locale.to_s) ? { locale: nil } : { locale: I18n.locale }).merge options
end

这在我的应用程序中完美无缺。

但是我在测试的时候遇到了问题。在一些测试中,对于名为 League:

的现有模型,我有这样的表达式
visit edit_league_path(@league)
expect(page.current_path).to eq league_path(@league)

检查重定向。联盟的操作 edit 只允许管理员使用。

因为我使用的是设备,所以我之前使用以下方法登录了一个用户(不是管理员):

# spec/support/controller_macros.rb
module ControllerMacros
  def login_user *user_roles
    before(:each) do
      @request.env['devise.mapping'] = Devise.mappings[:user]
      user = FactoryGirl.create(:user, *user_roles)
      user.confirmed_at = Time.zone.now
      user.save
      sign_in user
    end
  end
end

用户工厂使用随机语言环境创建随机用户。

我还有一个支持文件,修复了 rspec 测试的本地化,因为 application_controller 中的 default_url_options 在 rspec 测试中被忽略了(因为讨论 here):

# spec/support/fix_localization.rb
# workaround, to set default locale for ALL spec
class ActionView::TestCase::TestController
  def default_url_options options={}
    { locale: I18n.locale }.merge options
  end
end

class ActionDispatch::Routing::RouteSet
  def default_url_options options={}
    { locale: I18n.locale }.merge options
  end
end

现在我的问题是,当使用默认 i18n 语言环境设置(例如 en)的登录用户访问联赛的编辑页面时,被重定向,因为她或他不被允许访问该页面。重定向考虑了 application_controller 中的 default_url_options 方法,并没有重定向到 /en/leagues/42(如测试所期望的),而是重定向到 /leagues/42.

我解决这个问题的方法是将 spec/support/fix_localization.rb 中的 default_url_options 方法更改为与 application_controller 中相同的方法,但我无法访问当前用户支持文件。

有没有人知道如何访问当前用户或解决我的问题的其他想法或解决方法?

提前致谢!

我找到了无需复制代码的解决方案。我刚刚将 spec/support/fix_localization.rb 文件更改为:

# spec/support/fix_localization.rb
# workaround, to set default locale for ALL spec
class ActionView::TestCase::TestController
  def default_url_options options={}
    subject.default_url_options options
  end
end

所以现在,使用从 ApplicationController 继承的当前使用的控制器 (subject) 的 default_url_options 方法。

这在技术上并没有回答我的问题,但解决了根本问题。要获取当前用户(如最初要求的那样),也可以使用 subject

subject.current_user

但这仅在主题为控制器的支持文件中可用。