Разработать и несколько "пользовательских" моделей
Я использую рельсы 3.2 и разрабатываю 2.0, и я совершенно новый для Rails.
Требования
Я хотел бы сделать следующее:
- имеют 2 или более "пользовательских" моделей, например. Пользователь, Клиент, Администратор
- все модели имеют некоторые обязательные поля (например, адрес электронной почты и пароль).
- каждая модель может иметь несколько уникальных полей (например, только для клиентов)
- некоторые поля могут быть разделены, но не имеют одинаковой проверки (например, имя требуется для Клиента, но необязательно для участника).
- все поля должны быть заполнены во время процесса регистрации, поэтому формы различаются
- форма входа должна быть уникальной.
Возможные решения
Я долго искал и искал StackOverflow, но мне ничего не кажется правильным (я парень Java, извините:) и теперь я совершенно смущен. Появились два решения:
Пользователь с одним дизайном
Это самый частый ответ. Просто создайте созданный по умолчанию пользователь и создайте отношения между Member → User и Customer → User.
Меня беспокоит, как я могу добиться индивидуального процесса регистрации для каждой модели? Я пробовал разные вещи, но все закончилось как беспорядок!
Несколько разработчиков
Это решает процесс пользовательской регистрации и кажется мне правильным, но уникальная форма входа - блокиратор. Я нашел ответ на SO (Devise - логин от двух моделей), который предлагает переопределить Devise:: Models:: Authenticatable.find_for_authentication (условия).
Это кажется сложным (?), И поскольку я новичок в рельсах, я хотел бы знать, может ли это работать?
Спасибо за ваш совет!
Ответы
Ответ 1
Я нашел способ пойти, и я доволен этим до сих пор. Я опишу его здесь для других.
Я пошел с единственным "пользовательским" классом. Моя проблема заключалась в том, чтобы создать индивидуальный процесс регистрации для каждой псевдомодели.
модель /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 иметь два пути регистрации с переопределенным контроллером:
конфиг /routes.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
Ответ 2
Добро пожаловать на борт Java guy =), надеюсь, вам понравится мир Rails.
Просто, чтобы решить вашу проблему, у вас есть 2 решения:
- Для каждого пользователя создайте таблицу в базе данных и соответствующей модели.
- Создайте единую таблицу в базе данных и для каждого типа пользователя создайте модель. Это называется наложением одиночной таблицы (STI).
Какой из них выбрать?
Это зависит от общих атрибутов ролей. Если они почти повсеместны (например, все имеют имя, адрес электронной почты, мобильный,...), и несколько атрибутов разные, я настоятельно рекомендую решение STI.
Как сделать ИППП?
1. Просто создайте модель и таблицу пользователя для разработки с помощью команды rails generate devise User
2. Добавьте столбец с именем type
со строковым типом данных в пользовательскую таблицу в базе данных с помощью переноса.
3. Для каждого типа пользователя создайте модель (например, rails g model admin
)
4. Наследовать класс Admin от модели пользователя.
class Admin < User
end
Что это вы сделали =)... Yupeee
Чтобы создать администратор, запустите команду Admin.create(...)
, где точки - это атрибуты администратора, например, адрес электронной почты, имя,...
Я думаю, что question может вам помочь.
Ответ 3
Я в такой же обуви, как и вы, пробовав всевозможные подходы, я пошел с одной моделью пользователя, которая будет принадлежать полиморфным ролям. Это похоже на самый простой способ добиться единого входа.
Модель User будет содержать информацию, специфичную только для входа в систему.
В модели Role будут храниться поля, специфичные для каждой роли, а также другие ассоциации, специфичные для этой роли.
Новые регистрации будут настраиваться для каждого типа пользователя (ролей) через отдельные контроллеры, а затем для встраивания вложенных атрибутов для пользователя.
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
Маршруты - просто обычные материалы для модели участника.
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 gem; поскольку требование состоит в том, что Пользователь может принадлежать только одному типу Роли.
Ответ 4
Итак, что случилось? Просто запустите rails g devise:views [model_name]
, настройте каждую регистрационную форму и в config/initializer/devise.rb
просто поставьте config.scoped_views = true
.