Полиморфная ассоциация для многотипной регистрации в рельсах


Я использую devise для аутентификации моего приложения. У меня есть модель User, которая является моделью входа/выхода.

Функциональность заключается в том, что когда клиент, то есть пользователь, регистрируется, он будет заполнять обязательную страницу профиля пользователя. Все работало нормально, используя разработки.

Теперь у меня есть новый функционал, пользователь может быть разных типов( допустим A, B,C)

Если пользователь имеет тип A, то он должен следовать тому же процессу регистрации и та же страница профиля.

Если пользователь имеет тип B, то экран регистрации отличается и ожидает подтверждения от администратора. Различные изменения для типа C тоже.

Все разные типы имеют разные страницы профиля, и поля различаются.

Поэтому я решил иметь полиморфную ассоциацию, и вот как выглядят мои модели

class User < ActiveRecord::Base

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  attr_accessible :email, :password, :password_confirmation, :remember_me

  belongs_to :user_type, :polymorphic => true

end

class A
    has_one :user, :as => :user_type
end

class B
    has_one :user, :as => :user_type
end

class C
    has_one :user, :as => :user_type
end

Я просто хочу знать, является ли это правильным способом реализации сценария или есть лучший способ реализовать это?

2 4

2 ответа:

Вам нужна колонка Rails' magic type.

# user.rb
class User < ActiveRecord::Base
  # create_table 'users' do |t|
  #   t.string :name
  #   t.string :type
  # end
end

# user_a.rb
class UserA < User
end

# user_b.rb
class UserB < User
end

# user_c.rb
class UserC < User
end

UserA.create(name: "bricker")
user_a      = User.where(type: "UserA").first
same_user_a = UserA.all.first

user_a == same_user_a #=> true
user_a.class          #=> UserA
user_a.is_a? User     #=> true

Обновить

class UserLogin < ActiveRecord::Base
  # create_table :user_logins do |t|
  #   t.integer :user_id
  #   t.string  :user_type
  #   t.string  :login
  #   t.string  :encrypted_password
  # end

  # devise ...
  belongs_to :user, polymorphic: true
end

class User < ActiveRecord::Base
  self.abstract_class = true
  has_one :user_login, as: :user
end

class Admin < User
  # create_table :admins do |t|
  #   t.integer :user_login_id
  #   t.string  :admin_name
  # end
end

class Moderator < User
  # create_table :moderators do |t|
  #   t.integer :user_login_id
  #   t.string  :moderator_name
  # end
end

Я уже занимался этим раньше

Я бы настоятельно рекомендовал использовать неполиморфные отдельные модели и делиться общей функциональностью с миксинами.

У меня была та же установка, которую вы описали, и мне пришлось ее рефакторировать позже, так как она стала действительно раздутой и сложной по мере разработки проекта