我有一个基本的相关信息和活动的具体相关信息的用户。 比方说,用户是一名足球运动员,其外形看起来像:
User.rb #common infos
firstname
lastname
email
sex
address_id
Footballer.rb #or something accurate
position
team
age
weight
shoe_size
...
但是,如果用户是为义和团,其形象将组成如下:
#User.rb #same as footballer
firstname
lastname
email
sex
address_id
avatar
#Boxer.rb
weight
handicap
league
...
什么是在铁轨这种逻辑整合的最佳方式? 配置文件将在呈现users#show.html
我的应用程序可以方便地注册(仅电子邮件)和多个配置文件组成的团队,所以它看起来很复杂反转逻辑(通过创建一个Footballer has_one :basic_infos
和Boxer has_one :basic_infos
)这将需要对每个模型的基本相关信息亮点(如全名和头像)的呼叫
我在这stucked,所以任何帮助将是非常欢迎
我在这里看到下面的选项。
1.单个表继承( STI )
只是倾倒在一个表中的所有领域,使class Boxer < User
, class Footballer < User
。
优点:实现简单。
缺点:表变得臃肿。 域是共享的,即你的足球运动员将有weight
等领域,反之亦然。
2.移动基站信息到另一个表
这就是你已经列出的选项。
优点:清洁表,字段的适当分离。
缺点:复杂的实现。 你必须确保总有一个且只有一个为每个实例的基本轮廓。 所以,你必须要注意:delete_all/:destroy_all
协会macroses的选择,也许before_create/after_destroy
为好。
下面是关于如何组织在你的代码的例子:
# 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.添加序列化领域
只需添加details
场的具体细节运动员JSON / YAML,并有共同的领域作为单独的数据库字段。
优点:实现简单。 数据库结构保持简单为好。
缺点:你将不能够进行有效的查询特定的运动员的领域,例如,你将需要获取每个记录以了解它的细节。
4.使用PostgreSQL相关序列列
同上,只是没有“缺点”的一部分。 您将能够做出序列化数据高效的查询。
缺点:您需要学习如何使用字段和查询它们。 无法与MySQL。
貌似很适合STI 。 这里有一个坚实的教程中有关单表继承。
从本质上讲,你可以创建你的每一个不同的用户界面,所有从父类继承的子类User
。
# app/models/user.rb
class User < ActiveRecord::Base
# validations, associations, methods, etc.
end
# app/models/footballer.rb
class Footballer < User
# custom validations, methods, etc.
end
# app/models/boxer.rb
class Boxer < User
# custom validations, methods, etc.
end
我会建议使用annotate_models宝石加注释总结了每个型号的当前模式(其它文件中)。 它看起来像这样:
# == Schema Info
#
# Table name: users
#
# id :integer(11) not null, primary key
# firstname :string(255)
# lastname :string(255)
# email :string(255)
# sex :string(255)
# address_id :integer(11)
# avatar :string(255)
# weight :integer(11)
# handicap :string(255)
# league :string(255)
# position :string(255)
# team :string(255)
# age :integer(11)
# weight :float
# shoe_size :float
# weight :float
# handicap :float
# league :string(255)
# type :string(255)
#
class User < ActiveRecord::Base
...
end
注意如何User
模型注释中包含的所有列,包括那些为Footballer
和Boxer
的子类。 这是因为你需要的所有列添加到用户表,其中包括一个名为保留Rails的列type
,这将是正在创建的子类为每个记录的名称。
使用STI会给你处理特定的子类逻辑的灵活性。 我建议你看看我联系的教程,或约Rails内部STI的其他文件。