4

Trailblazer建议像这样注入current_user细胞

<%= concept(Appointment::Cell::UserStatus,user,current_user: current_user) %>

然后可以使用一种方法使其在单元格内可访问

  def current_user
    options[:current_user]
  end

但是,这意味着在每次调用单元格时添加此注入,而实际上current_user是一个特殊的全局变量。

我已经设法current_user通过创建一个超类单元来解决注入问题,如下所示:

class Template::Cell < Cell::Concept
  include Pundit
  include Devise::Controllers::Helpers

  Devise::Controllers::Helpers.define_helpers(Devise::Mapping.new(:user, {}))
  include Escaped
  include ActionView::Helpers::JavaScriptHelper
end

这很好用,除了我无法在 RSpec 测试期间登录用户。通常的基于控制器的方法不起作用,因为无法访问请求。

顺便说一句,我尝试了“设计模拟”解决方案,但没有奏效:

RSpec.describe Friendship::Cell, type: :cell do
  include Devise::TestHelpers
  include ControllerHelpers
  let!(:user) { create :user }

  describe '#methods' do
    before do
      sign_in(user)
    end
    subject { concept(described_class, user, current_user: user) }
    it { expect(current_user).to eq(user) }
  end
end

module ControllerHelpers
  def sign_in(user = double('user'))
    if user.nil?
      allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
      allow(controller).to receive(:current_user).and_return(nil)
    else
      allow(request.env['warden']).to receive(:authenticate!).and_return(user)
      allow(controller).to receive(:current_user).and_return(user)
    end
  end
end

错误

1) Friendship::Cell cell can be instantiated
     Failure/Error: @request.env['action_controller.instance'] = @controller

     NoMethodError:
       undefined method `env' for nil:NilClass
     # /Users/sean/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/devise-4.3.0/lib/devise/test/controller_helpers.rb:40:in `setup_controller_for_warden'
     # /Users/sean/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/rspec-rails-3.6.0/lib/rspec/rails/adapters.rb:165:in `block (2 levels) in setup'
4

1 回答 1

0

文档https://trailblazer.to/2.0/gems/cells/getting-started.html#discussion-navigation说:

It is important to understand that the cell has no access to global state. You as the cell author have to define the interface and the dependencies necessary to render the cell.

与你的话相反:

However, this means adding this injection on every call to a cell, when in fact current_user is a special global var.

我认为您误解了开拓者细胞的目标。他们不应该有权访问应用程序的全局状态。它们是独立的实体,依赖于依赖注入。

如果您希望单元格能够访问全局状态,您实际上可能正在为此寻找不同的工具。也许https://github.com/github/view_component会更适合您,它们有点类似于单元格,但更易于使用 rails 与 rails 的集成,而 trailblazer 将 rails 视为可选。

https://trailblazer.zulipchat.com/如果有人偶然发现这个话题并想直接向核心团队询问这种方法,他们在 zulipchat 上非常活跃,但知道他们,他们只会建议不要这样做,因为它是反对的该工具的设计目的,由文档指定。

于 2021-07-06T12:07:03.777 回答