我正在设计一个用户登录并创建个人资料的rails应用程序。 我希望用户可以选择3种配置文件类型(提供商,搜索者,专业人士)。
我使用了devise gem进行用户身份验证。 我有个人资料模型,必须遵循协会。
User.rb has_one:个人资料
Profile.rb belongs_to:user
目前,用户可以创建通用配置文件,但我希望对其进行更改,以便每个配置文件类型都有不同的输入字段。
最基本的方法是什么?
答案 0 :(得分:0)
你可以使用STI(单表继承)但我通常会避免它 - 你必须问自己的问题是:"我真的需要为每种配置文件类型定义一个新模型吗?"
实现此目的的最简单方法之一是只设置kind
属性,然后为每个Profile#kind
(您不能使用为STI保留的类型关键字)自己的关联:
class User
has_many :profiles
has_one :provider_profile, -> {where(kind: "provider")}, class_name: "Profile"
has_one :seeker_profile, -> {where(kind: "seeker")}, class_name: "Profile"
has_one :professional_profile, -> {where(kind: "professional")}, class_name: "Profile"
end
答案 1 :(得分:0)
STI
所需的另一个选项是enum
:
#app/models/profile.rb
class Profile < ActiveRecord::Base
enum state: [:provider, :seeker, :professional]
end
这会为您提供int
列(在本例中为state
),表示对象是否具有特定属性(EG provider?
/ seeker?
等)。
它会为STI
提供一组类似的功能,除了给你一个模型来调用(而不是你使用STI模式时得到的3
。)
如果你有需要来调用多个模型,那么STI是好的。
大多数时候,你没有。有一个good writeup about it here.
如果在案件中使用STI
,您最终会得到:
#app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
#app/models/seeker.rb
class Seeker < Profile
end
#app/models/professional.rb
class Professional < Profile
def add_client
...
end
end
需要注意的重要一点是,虽然这在您的模型中看起来很漂亮,但这意味着您的前端需要调用:
#config/routes.rb
resources :professionals, only: [:new, :create]
#app/controllers/professionals_controller.rb
class ProfessionalsController < ApplicationController
def index
@professional = Professional.find params[:id]
end
end
如果您打算致电Profile.find_by type: "professional"
,请忘掉它。那是antipattern&amp;非常低效。
-
确定您是否真的需要遵循STI模式的方法非常简单 - 每个subclass需要额外的方法/属性吗?
如果没有,那么你就可以使用枚举:
#app/models/user.rb
class User < ActiveRecord::Base
has_one :profile
before_create :build_profile #-> creates blank profile with each new user
accepts_nested_attributes_for :profile
end
#app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
enum state: [:provider, :seeker, :professional] #-> defaults to "provider"
end
我个人会在控制器中使用enum
条件:
#app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def edit
@profile = current_user.profile
if @profile.professional?
...
elsif @profile.seeker?
...
end
end
end
-
了解其工作原理的最佳方法是查看object orientated programming,简而言之就是Ruby / Rails。
OOP使用类来创建"objects" ...
这些对象中的每一个都被调用为实例(这是术语“实例变量”和“实例方法”的来源) - 这些实例由应用程序保存在内存中。
OOP程序的工作方式是从用户那里获取输入,确定对象之间的交互并输出结果。这就是所有现代游戏的运作方式。
因此,当您查看Rails时,您必须从您将要调用的对象的角度来看待它。你真的想要拉Professional
个对象吗,还是只是你正在使用的Profile
?