Использование draper gem с контроллером регистрации devise

Я объявил user_decorator.rb вместо user_helper.rb следующим образом

class UserDecorator < Draper::Decorator
   delegate_all

  def contract_type
    contract_types.keys.collect {|k| [k.humanize, k]}
  end
  def employee_type
    employee_types.keys.collect {|k| [k.humanize, k]}
  end

  def department_role
    department_roles.keys.collect {|k| [k.humanize, k]}
  end
end

и вот мои перечисления, которые объявлены на user.rb

 enum contract_type: [:probationary, :apprenticeship, :six_months_to_one_year,
    :three_years]
  enum department_role: [:ceo, :cto, :coo, :manager, :tl, :gl, :developer]
  enum employee_type: [:full_time, :part_time, :internship]

Я хочу вызвать вспомогательный метод из представления, связанного с контроллером регистрации. Это как

class RegistrationsController < Devise::RegistrationsController

  def new
    super
  end

  def create
    super
  end
end

Но если я вызову вспомогательный метод, например, как показано в views/devise/registrations/new.html.erb

<%= f.select :contract_type, contract_type, {prompt: t(".contract_type",
      default: "Select contract type")} %>

Это не найти contract_type. Нужна помощь о том, как я могу получить доступ к вспомогательным методам из представления, объявленного в user_decorator.rb

2 ответа

Вы можете переопределить ваш new способ украсить ваш ресурс так:

# registrations_controller.rb

def new
  build_resource({})
  yield resource if block_given?
  respond_with resource
end

protected

def build_resource(hash = nil)
  self.resource = resource_class.new_with_session(hash || {}, session).decorate
end

Чтобы получить украшенный пользовательский объект от Devise's current_user метод, вы можете переопределить его:

class ApplicationController < ActionController::Base
  def current_user
    UserDecorator.decorate(super) unless super.nil?
  end
end

Тем не менее, так как ваша проблема на devise/registrations/new.html.erb страница, на данный момент пользователь не будет вход в систему и, следовательно, не будет иметь какой-либо оформленный current_user объект.

Итак, то, что вы, казалось бы, хотите, чтобы получить набор украшенных типов контрактов от вашего User смоделируйте это представление, что вы можете сделать, создав переменную экземпляра на контроллере:

class RegistrationsController < Devise::RegistrationsController
  def new
    @contract_types = User.contract_types.keys.collect {|k| [k.humanize, k]}
    super
  end
end

а затем использовать его в представлении:

<%= f.select :contract_type, 
             @contract_types,
             { prompt: t(".contract_type", default: "Select contract type") } %>

Если вы хотите провести дальнейшие рефакторинги, вы можете создать на своем User Модель, которая выполняет оформление контракта по видам:

class User < ActiveRecord::Base
  def self.humanized_contract_types
    contract_types.keys.collect {|k| [k.humanize, k]}
  end
end

Итак, тогда ваш код контроллера может быть сокращен до:

class RegistrationsController < Devise::RegistrationsController
  def new
    @contract_types = User.humanized_contract_types
    super
  end
end

Или, если вы намереваетесь использовать UserDecorator класс, вы можете посмотреть на вызовы методов класса прокси к нему.

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