2016-05-20 1 views
1

У нас есть две модели: «Devise User» и «Influencer». Influencer - Пользователь, поэтому он должен иметь пользователя (с точки зрения db). Пользователь может быть несколькими другими вещами. Таким образом, мы хотим иметь возможность регистрировать пользователя, не являясь Influencer, и мы хотим зарегистрировать пользователя, когда они захотят зарегистрироваться как Influencer.Создайте пользователя-разработчик из другой формы и контроллера - Ruby on Rails

У меня есть форма, как так:

influencers/new.html.erb

<%= form_for @influencer do |i| %> 
    <%= i.fields_for(resource, as: resource_name, url: registration_path(resource_name)) do |u| %> 
    <div id="registration_fields"> 
     <%= render 'devise/registrations/registration_fields', f: u %> 
    </div> 
    <% end %> 

<div class='field'> 
    <%= i.label :twitter_handle %><br/> 
    <%= i.text_field :twitter_handle %> 
</div> 

<div class='field'> 
    <%= i.label :short_bio %><br/> 
    <%= i.text_area :short_bio %> 
</div> 

/views/devise/registrations/_registration_fields

<%= devise_error_messages! %> 

<div class="field"> 
    <%= f.label :first_name %> <br /> 
    <%= f.text_field :first_name %> 
</div> 

<div class="field"> 
    <%= f.label :last_name %> <br /> 
    <%= f.text_field :last_name %> 
</div> 

<div class="field"> 
    <%= f.label :email %><br /> 
    <%= f.email_field :email, autofocus: true %> 
</div> 
<div class="field"> 
    <%= f.label :password %> 
    <% if @minimum_password_length %> 
    <em>(<%= @minimum_password_length %> characters minimum)</em> 
    <% end %><br /> 
    <%= f.password_field :password, autocomplete: "off" %> 
</div> 

<div class="field"> 
    <%= f.label :password_confirmation %><br /> 
    <%= f.password_field :password_confirmation, autocomplete: "off" %> 
</div> 

Мы изменили ApplicationHelper и 'новый' метод, так что он может сделать эта форма разработки без проблем. К сожалению, мы зациклились на том, как правильно создать метод «create» для нашего InfluencersController.

Это хэш мы получаем:

Parameters: {..., "influencer"=>{"user"=>{"first_name"=>"buddy", "last_name"=>"king", "email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "twitter_handle"=>"@bdking", "short_bio"=>"None"}, "commit"=>"Join as influencer" 

По существу, мы хотим Придумайте для обработки пользовательской информации в то время как мы обрабатываем информацию Influencer. Мы попытались вызвать метод Devise :: RegistrationsController.new.create из InfuencersController # create. Однако это создает свои собственные трудности (даже при использовании нескольких хакеров мы сталкиваемся с различными проблемами, такими как отсутствие «@response» или отсутствие «response.env» или отсутствие «devise.mappings»).

С учетом сказанного, мы считаем, что наследование позволит нам называть «супер» в функции создания. Однако мы не хотим, чтобы InfluencersController наследовал от Devise :: RegistrationsController, поскольку этот контроллер ни в коем случае не является истинным контроллером Devise.

Есть ли способ обойти это?

ответ

0

Я бы использовал проверенный образец users и roles.

В основном ваш класс User отвечает за аутентификацию (идентификатор), и у пользователя есть много Roles, которые могут использоваться для авторизации (разрешений).

class User < ActiveRecord::Base 
    has_many :roles 

    def has_role?(role) 
    roles.where(name: role) 
    end 
end 

class Role < ActiveRecord::Base 
    belongs_to :user 
    validates_uniqueness_of :name, scope: :user_id 
end 

так что «Influencer» действительно только пользователь с ролью (имя: «Influencer»), прикрепленного к нему. Реальная сила и гибкость заключаются в том, что тривиально реализовать предоставление/отмену ролей из веб-интерфейса.

И вам не нужно возиться с тем, как аутентификация Devise/Warden поддерживает несколько классов, которые могут стать действительно грязными.

Лучшая часть состоит в том, что Rolify gem делает ее действительно тривиальной для настройки.

Если вам нужно настроить конкретную конечную точку (influences/registrations), чтобы зарегистрировать «авторитеты» вы можете просто переопределить метод build_resource в контроллере DEViSE:

class InfluencerRegistrationsController < Devise::RegistrationsController 

    def resource_class 
    User 
    end 

    def build_resource 
    super 
    self.resource.roles.new(name: :influencer) 
    end 
end 
+0

Если вы абсолютно необходимо, вы можете использовать STI или MTI. Но минусы довольно огромные с точки зрения сложности и производительности. – max

+0

Что такое STI или MTI?И вы правы, мы используем роли пользователя, где один из них является влиятельным. Однако, поскольку у влиятелей есть дополнительные члены данных, мы делаем их собственной таблицей. Я спрашиваю, есть ли способ, чтобы InfluencersController регистрировал пользователя без его наследования с помощью Devise :: RegistrationsController. –

+0

Наследование отдельных таблиц и наследование нескольких таблиц. Да, вы можете создать контроллер с нуля, который регистрирует пользователей - он не сильно отличается от любого другого контроллера CRUD, кроме того, что вы вызываете 'sign_in @ user', чтобы заставить Warden хранить идентификатор в сеансе перед перенаправлением. – max

Смежные вопросы