用户的属性取决于用户的类型:在Rails中实现的最佳方法 [英] User's attributes depend on user's type: best way to implement in Rails
问题描述
我有一个具有基本信息和特定于活动的信息的用户. 假设用户是一名足球运动员,其个人资料如下所示:
I have a user with basic infos and activity specific infos. Let's say User is a Footballer, its profile will look like :
User.rb #common infos
firstname
lastname
email
sex
address_id
Footballer.rb #or something accurate
position
team
age
weight
shoe_size
...
但是,如果用户为Boxer,则其个人资料将由以下内容组成:
However, if the user is as Boxer, its profile will be composed of :
#User.rb #same as footballer
firstname
lastname
email
sex
address_id
avatar
#Boxer.rb
weight
handicap
league
...
将这种逻辑集成到rails中的最佳方法是什么?
配置文件将在users#show.html
中呈现
我的应用易于注册(仅电子邮件),并且团队由多个配置文件组成,因此反转逻辑(通过创建Footballer has_one :basic_infos
和Boxer has_one :basic_infos
)似乎很复杂,这需要在每个模型上调用以获取基本信息突出显示(例如全名和头像)
What would be the best way to integrate this logic in rails?
The profile would be rendered in users#show.html
My app has easy registration (only email) and teams composed of multiple profiles, so it seems complicated to invert the logic (by creating a Footballer has_one :basic_infos
and Boxer has_one :basic_infos
), that would require a call on each model for basic infos highlight (such as complete name and avatar)
我对此一无所知,因此非常欢迎您提供任何帮助
I'm stucked on this, so any help would be very welcome
推荐答案
我在这里看到以下选项.
I see the following options here.
1.单表继承( STI )
1. Single table inheritance (STI)
只需将所有字段转储到一个表中,然后将其设为class Boxer < User
,class Footballer < User
.
Just dump all the fields in one table, and make class Boxer < User
, class Footballer < User
.
优点:实施简单.
缺点:表变得肿.字段是共享的,即您的足球运动员将拥有weight
和其他字段,反之亦然.
Cons: Table become bloated. Fields are shared, i.e. your footballer will have weight
and other fields and vice versa.
2.将基本信息移到另一个表
这就是您已经概述的选项.
That's the option you already outlined.
优点:清理表,适当分隔字段.
Pros: Clean tables, proper separation of fields.
缺点:复杂的实现.您将必须确保每个实例始终只有一个基本配置文件.因此,您将必须注意关联宏的:delete_all/:destroy_all
选项,也许也要注意before_create/after_destroy
.
Cons: Complex implementation. You will have to ensure that there is always one and only one basic profile for each instance. So you will have to pay attention to :delete_all/:destroy_all
options of association macroses, and maybe before_create/after_destroy
as well.
以下是有关如何在您的代码中进行组织的示例:
Here is an example on how to organize that in your code:
# models
class Profile < ActiveRecord::Base
# you need to create
# t.integer :user_id
# t.string :user_type
# in a migration for 'profiles' table
belongs_to :user, polymorphic: true
end
class User < ActiveRecord::Base
# This will disable STI
self.abstract_class = true
has_one :profile, as: :user, dependent: :destroy
def some_common_user_method
# ...
end
def pick_profile
self.profile && return self.profile
if self.persisted?
self.create_profile
else
self.build_profile
end
end
end
class Footballer < User
end
# controllers
class UsersController < ApplicationController
before_action :set_klass
before_action :set_user, except: [:index, :create]
# ...
def create
@user = @klass.new
@user.pick_profile
# etc...
end
def destroy
@user.destroy
end
private
def set_klass
# white-list search for class
@klass = User.descendants.find{|k| k == params[:type].camelize.constantize}
end
def set_user
@user = @klass.find(params[:id])
end
end
# routes
# for URLs like /users/1?type=footballer
resources :users
# for URLs like /users/footballer/1
resources :users, path_prefix: '/users/:type'
3.添加序列化字段
3. Adding a serialized field
只需添加具有特定运动员详细信息的JSON/YAML的details
字段,并将公共字段作为单独的数据库字段即可.
Just add details
field with JSON/YAML of specific sportsmen details, and have common fields as separate DB fields.
优点:实施简单.数据库结构也保持简单.
Pros: Simplicity of implementation. Database structure stays simple as well.
缺点:您将无法在特定运动员的字段上进行有效的查询,即您将需要获取每条记录以了解其详细信息.
Cons: You won't be able to make effective queries on specific sportsman's fields, i.e. you will need to fetch each record to know its details.
4. Using Postgresql-specific serialized columns
与上述相同,仅不包含缺点"部分.您将能够对序列化数据进行有效的查询.
Same as above, only without "cons" part. You will be able to make efficient queries on serialized data.
缺点:您将需要学习如何使用该字段并进行查询.使用MySQL无法实现.
Cons: You will need to learn how to use that fields and query them. Not possible with MySQL.
这篇关于用户的属性取决于用户的类型:在Rails中实现的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!