Первопроходческие ячейки и разработка current_user в RSpec

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'

1 ответ

В документации 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 вам больше подойдет, они несколько похожи на ячейки, но более доступны для интеграции рельсов с рельсами, в то время как trailblazer рассматривает рельсы как необязательные.

https://trailblazer.zulipchat.com/, если кто-то наткнется на эту тему и захочет напрямую спросить основную команду об этом подходе, они довольно активны в zulipchat, но зная их, они просто посоветуют не делать этого, поскольку это против для чего был разработан инструмент, как указано в документации.

Другие вопросы по тегам