разработка и несколько" пользовательских " моделей
Я использую rails 3.2 и devise 2.0, и я совсем новичок в Rails.
требования
Я хотел бы получить следующее:
- есть 2 или более "пользовательских" моделей, например. Участник, Клиент, Администратор
- все модели имеют некоторые обязательные поля (например. электронная почта и пароль)
- каждая модель может иметь несколько уникальных полей (например. компания только для клиента)
- некоторые поля могут быть общими, но не имеют одинаковой проверки (например. имя требуется для клиента, но необязательно для участника)
- все поля должны быть заполнены в процессе регистрации, поэтому формы разные
- форма входа должна быть уникальной
возможные решения
я гуглил и искал StackOverflow довольно долго, но мне ничего не кажется правильным (я парень Java, извините :) и теперь я совсем запутался. Появились два решения:
один пользователь devise
Это самое частый ответ. Просто создать по умолчанию разработать пользователей и создание связей между членом-->пользователей и клиентов-->пользователей. Моя проблема здесь заключается в том, как я могу добиться индивидуального процесса регистрации для каждой модели? Я пробовал разные вещи, но все закончилось как беспорядок!
несколько пользователей devise
Это решает пользовательский процесс регистрации и кажется мне правильным, но уникальная форма входа в систему является блокировщиком. Я нашел ответ на SO (Devise-login от двух моделей), который предлагает переопределить Devise::Models:: Authenticatable.find_for_authentication(условия). Это кажется сложным (?) и поскольку я новичок в rails, я хотел бы знать, может ли это сработать?
Спасибо за ваш совет!
4 ответа:
Добро пожаловать на борт Java guy =), я надеюсь, вам понравится мир Rails. Просто, чтобы решить вашу проблему, у вас есть 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(...)
где точки-это атрибуты администратора, например, электронная почта, имя, ...Я думаю, что это вопрос может помочь вам слишком
Я в такой же обуви, как и вы, попробовав всевозможные подходы, я пошел с одной пользовательской моделью, которая принадлежала бы полиморфным ролям. Это кажется самым простым способом достижения единого входа.
модель пользователя будет содержать информацию, специфичную только для входа в систему.
модель ролей будет хранить поля, специфичные для каждой роли, а также другие ассоциации, специфичные для роли.
новые регистрации будут настроены для каждого типа пользователей (роли) через отдельные контроллеры, а затем создание вложенных атрибутов для пользователя.
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
views / members / new.формат html.Эрб
<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; так как требование заключается в том, что пользователь может принадлежать только к одному типу роли.
я нашел способ пойти, и я вполне доволен этим до сих пор. Я опишу это здесь для других.
я пошел с одним классом "пользователь". Моя проблема заключалась в том, чтобы добиться индивидуального процесса регистрации для каждой псевдо-модели.
модели/пользователя.РБ:
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/маршруты.РБ:
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.РБ:
я создал класс Мастер, который знает поля для проверки на каждом шаге
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