разработать и несколько «пользовательских» моделей - PullRequest
73 голосов
/ 28 февраля 2012

Я использую rails 3.2 и разрабатываю 2.0, и я довольно новичок в Rails.

Требования

Я бы хотел добиться следующего:

  • имеют 2 или более «пользовательских» моделей, например.Участник, клиент, администратор
  • все модели имеют некоторые обязательные поля (например, адрес электронной почты и пароль)
  • каждая модель может иметь несколько уникальных полей (например, компания только для клиента)
  • некоторые поля могут быть общими, но не иметь одинаковую проверку (например, имя требуется для Заказчика, но необязательно для Участника)
  • все поля должны быть заполнены во время процесса регистрации, поэтому формы различаются
  • форма входа должна быть уникальной

Возможные решения

Я довольно долго гуглял и искал StackOverflow, но мне ничего не кажется правильным (я парень из Java,извините :) и теперь я совсем запутался.Пришли два решения:

Пользователь одного устройства

Это самый частый ответ.Просто создайте пользователя по умолчанию и создайте отношения между Участником -> Пользователем и Клиентом -> Пользователем.Меня беспокоит то, как я могу добиться индивидуального процесса регистрации для каждой модели?Я пробовал разные вещи, но все закончилось беспорядком!

Несколько пользователей устройства

Это решает пользовательский процесс регистрации и кажется правильным для меня, но уникальная форма входа является блокирующим устройством.Я нашел ответ на SO ( Devise - логин из двух моделей ), который предлагает переопределить Devise :: Models :: Authenticatable.find_for_authentication (условия).Это кажется сложным (?), И так как я новичок в рельсах, я хотел бы знать, может ли это сработать?

Спасибо за ваш совет!

Ответы [ 4 ]

66 голосов
/ 28 февраля 2012

Добро пожаловать на борт Java! =) Надеюсь, вам понравится мир Rails. Просто, чтобы решить вашу проблему, у вас есть 2 решения:

  1. Для каждого пользователя создайте таблицу в базе данных и соответствующую модель.
  2. Создайте одну таблицу в базе данных и для каждого типа пользователя создайте модель. Это называется наследованием одной таблицы (STI).

Какой выбрать? Это зависит от общих атрибутов ролей. Если они почти обычны (например, у всех есть имя, адрес электронной почты, номер мобильного телефона, ...) и некоторые атрибуты различаются, я настоятельно рекомендую решение STI.

Как сделать ИППП? 1. Просто создайте модель и таблицу пользователя devise с помощью команды rails generate devise User 2. Добавьте столбец с именем type со строковым типом данных в таблицу пользователей в базе данных, используя миграцию. 3. Для каждого типа пользователя создайте модель (например, rails g model admin). 4. Сделать класс Admin наследуемым от модели пользователя

class Admin < User
end

Вот и все, что вы сделали =) ... Yupeee

Чтобы создать администратора, введите команду Admin.create(...), где точки - это атрибуты администратора, например адрес электронной почты, имя, ...

Я думаю, этот вопрос тоже может вам помочь

26 голосов
/ 14 августа 2012

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

Модель User будет содержать информацию, относящуюся только к входу в систему.

Ролевая модель будет хранить поля, специфичные для каждой роли, а также другие ассоциации, специфичные для этой роли.

Новые регистрации будут настраиваться для каждого типа пользователя (роли) через отдельные контроллеры, а затем создавать вложенные атрибуты для пользователя.

class User < ActiveRecord::Base
    #... devise code ...
    belongs_to :role, :polymorphic => true
end

class Member < ActiveRecord::Base
    attr_accessible :name, :tel, :city  #etc etc....
    attr_accessible :user_attributes #this is needed for nested attributes assignment

    #model specific associations like  
    has_many :resumes

    has_one :user, :as => :role, dependent: :destroy
    accepts_nested_attributes_for :user
end 

Маршруты - просто обычные вещи для модели Member.

resources :members
#maybe make a new path for New signups, but for now its new_member_path

Контроллер - вам нужно build_user для вложенных атрибутов

#controllers/members_controller.rb
def new
    @member = Member.new
    @member.build_user
end

def create
    #... standard controller stuff
end

Вид / Участники / new.html.erb

<h2>Sign up for new members!</h2>
<%= simple_form_for @member do |f| %>

    # user fields
    <%= f.fields_for :user do |u| %>
      <%= u.input :email, :required => true, :autofocus => true %>
      <%= u.input :password, :required => true %>
      <%= u.input :password_confirmation, :required => true %>
    <% end %>

    # member fields
    <%= f.input :name %>
    <%= f.input :tel %>
    <%= f.input :city %>

    <%= f.button :submit, "Sign up" %>
<% end %>

Я хотел бы отметить, что НЕТ НЕОБХОДИМОСТИ для достижения гема nested_form; поскольку требование состоит в том, что пользователь может принадлежать только к одному типу роли.

18 голосов
/ 03 марта 2012

Я нашел способ пойти, и я до сих пор доволен этим.Я опишу это здесь для других.

Я пошел с единственным "пользовательским" классом.Моя проблема заключалась в том, чтобы добиться индивидуального процесса регистрации для каждой псевдомодели.

model / user.rb:

class User < ActiveRecord::Base
  devise :confirmable,
       :database_authenticatable,
       :lockable,
       :recoverable,
       :registerable,
       :rememberable,
       :timeoutable,
       :trackable,
       :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :role

  as_enum :role, [:administrator, :client, :member]
  validates_as_enum :role
  ## Rails 4+ for the above two lines
  # enum role: [:administrator, :client, :member]

end

Затем я адаптировал http://railscasts.com/episodes/217-multistep-formsи http://pastie.org/1084054 для двух путей регистрации с переопределенным контроллером:

config / rout.rb:

get  'users/sign_up'   => 'users/registrations#new',        :as => 'new_user_registration'

get  'clients/sign_up' => 'users/registrations#new_client', :as => 'new_client_registration'
post 'clients/sign_up' => 'users/registrations#create',     :as => 'client_registration'

get  'members/sign_up' => 'users/registrations#new_member', :as => 'new_member_registration'
post 'members/sign_up' => 'users/registrations#create',     :as => 'member_registration'

контроллеры / пользователи/registrations_controller.rb:

Я создал класс мастера, который знает поля для проверки на каждом шаге

class Users::RegistrationsController < Devise::RegistrationsController

    # GET /resource/sign_up
    def new
        session[:user] ||= { }
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        respond_with @user
    end

    # GET /clients/sign_up
    def new_client
        session[:user] ||= { }
        session[:user]['role'] = :client
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        render 'new_client'
    end

    # GET /members/sign_up
    def new_member
      # same
    end

    # POST /clients/sign_up
    # POST /members/sign_up
    def create
        session[:user].deep_merge!(params[:user]) if params[:user]
        @user = build_resource(session[:user])
        @wizard = ClientRegistrationWizard.new(current_step)

        if params[:previous_button]
            @wizard.previous
        elsif @user.valid?(@wizard)
            if @wizard.last_step?
                @user.save if @user.valid?
            else
                @wizard.next
            end
        end

        session[:registration_current_step] = @wizard.current_step

        if @user.new_record?
            clean_up_passwords @user
            render 'new_client'
        else
            #session[:registration_current_step] = nil
            session[:user_params] = nil

            if @user.active_for_authentication?
                set_flash_message :notice, :signed_up if is_navigational_format?
                sign_in(:user, @user)
                respond_with @user, :location => after_sign_up_path_for(@user)
            else
                set_flash_message :notice, :"signed_up_but_#{@user.inactive_message}" if is_navigational_format?
                expire_session_data_after_sign_in!
                respond_with @user, :location => after_inactive_sign_up_path_for(@user)
            end
        end

    end

    private

    def current_step
        if params[:wizard] && params[:wizard][:current_step]
            return params[:wizard][:current_step]
        end
        return session[:registration_current_step]
    end

end

, и мои представления:

  • new.rb
  • new_client.rb, включая частичное в соответствии с шагом мастера:
    • _new_client_1.rb
    • _new_client_2.rb
  • new_member.rb включая частичное в соответствии с шагом мастера:
    • _new_member_1.rb
    • _new_member_2.rb
6 голосов
/ 28 февраля 2012

Так что не так?Просто запустите rails g devise:views [model_name], настройте каждую регистрационную форму и в config/initializer/devise.rb просто введите config.scoped_views = true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...