也许STI不是我想要的,我对所有建议持开放态度,但为了这个问题,让我们假设以下现实情况:
您希望自己的应用为不同的邮件供应商提供API数据。使用STI,您有以下模型
class MailSetting < ActiveRecord::Base
belongs_to :user
end
class MailChimp < MailSetting
end
class AWeber < MailSetting
end
class PostageApp < MailSetting
end
现在让我们做一些控制台动作:
user = User.first
setting = user.create_mail_setting(:type => "MailChimp")
好的,现在您要添加API密钥设置。 MailChimp只使用api_key。 Aweber可以使用api_key和签名,而Postageapp则使用api_key和令牌系统。
您是否会扩展每个子类以包含数据库中所需的任何列?
你是否会一起废弃STI,只是定期上课,MailChimp
,继承自AR?
我对STI的理由是,我知道我的所有用户都会有一个MailSetting,这种类型可能会随着时间的推移而扩展。但是,我发现以这种方式扩展这些子类是一件很痛苦的事情,导致你不能在不知道它们是什么子类的情况下做user.mail_setting.connect
这样的事情,然后,我需要连接这些人吗?
思想?
答案 0 :(得分:3)
您应该使用Polymorphic类而不是STI
<强> UPD 强>
一些链接:
UPD 2
想象一下,我们需要Post模型。我们有继承Post的文章和主题。
rails g model Post title:string body:text content_type:string content_id:integer
因此title
和body
是主题和文章的常见字段。现在让我们在主题中创建user_id
字段并在文章
link
的其他模型
rails g model Topic user_id:integer
rails g model Article link:string
现在我们将编辑模型:
class Post < ActiveRecord::Base
belongs_to :content, :polymorphic => true, :dependent => :destroy
end
class Topic < ActiveRecord::Base
has_one :post, :as => :content, :dependent => :destroy
end
class Article < ActiveRecord::Base
has_one :post, :as => :content, :dependent => :destroy
end
它可能非常复杂,但是这样挖掘:)
答案 1 :(得分:2)
您可以考虑使用ActiveRecord::Store
中的store_accessor
方法。
STI商店方法given here演示了如何为各个子类提供不同的访问者,这些访问器被序列化到超类的单个列中。
如果您正在使用PostgreSQL&gt; = 9.2,那么这与其JSON类型完美配合,如果没有,那么您可以让Rails进行序列化(使用store
代替store_accessor
。
TLDR(假设PostgreSQL&gt; = 9.2):
添加迁移:
add_column :mail_settings, :vendor_settings, :json
在子类中定义相关属性:
class MailChimp < MailSetting
store_accessor :vendor_settings, :api_key
validates :api_key, presence: true
end
答案 2 :(得分:0)
在我看来,您的架构已经足够无形,以至于您最好使用无架构数据库。也许是基于“NoSQL”文档的解决方案之一?这样,您可以随意添加和删除记录中的字段。