2

大家好,

我正在使用 Ruby on Rails 开发一个应用程序,我们需要跟踪应用程序将访问的每个用户(例如 Facebook、MySpace、Google、SalesForce、Twitter、WordPress 等)的一堆外部服务代表用户。对于某些服务,我们需要存储(加密的)用户名和密码,对于一些我们需要保存 OAuth 数据,对于一些 OAuth2 数据,等等。随着应用程序的发展,我们将需要支持更多类型的帐户,每个帐户都有自己的一组身份验证数据。

每个用户都可以在应用程序中创建帖子,我们会将这些帖子发送到外部服务,以便为用户发布。然后,我们跟踪对已发布帖子的响应(Twitter 上的转推、Facebook 上的点赞/分享等)。

所以:

class User < ActiveRecord::Base
  has_many :services
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :publishes
end

class Publish < ActiveRecord::Base
  has_one :service
  belongs_to :post
end

class Service < ActiveRecord::Base
  belongs_to :user
  belongs_to :publish
end

我在为我的类型使用单表继承Service(例如WordpressService,、、和简单地序列化一个简单的哈希以保存身份验证数据)和使用传统的规范化方案之间进行辩论,其中每种类型的服务都是它自己的模型和表FacebookServiceTwitterService我希望能够轻松地遍历与用户关联的所有服务,并且发布需要能够与任何类型的服务相关联(例如,发布可能被发送到 WordPress、Facebook 或 Twitter) .

我可以使用传统的标准化方法来实现这种模型关系吗?或者这正是 STI 想要解决的问题?

谢谢。

4

4 回答 4

2

您可能想查看omniauth 插件,该插件非常容易设置并处理为许多开箱即用的服务存储身份验证凭据。有几个 railscasts 展示了如何设置它。如果不出意外,您可以看到他们建议如何存储东西。

于 2010-10-23T17:24:03.097 回答
2

作为 STI 的替代方案,您可以使用多态关联:

class AccountAuth < AR::Base
  belongs_to :account
  belongs_to :authentication, :polymorphic => true
end
# account_id          :integer
# authentication_id   :integer
# authentication_type :string

module Auth
  #common logic
end

class FacebookAuth < AR::Base
  include Auth
  has_one :account_auth,:as=>:authentication
  has_one :account, :through => :account_auth
end

class Account < AR::Base
  has_many :account_auths
  has_many :authentications, :through => :account_auths
end

可能会帮助你。

于 2011-04-03T11:44:36.583 回答
0

您将存储几百万用户,每秒查询表多少次?一般来说,您的物理设计会受到这种类型的存储的影响,但硬件将克服大量应用程序的设计缺陷。如果您不是在进行大规模日期或大量交易,那么您可以处理任何事情。

于 2010-09-22T18:20:12.803 回答
0

虽然我仍然不确定这是否是解决这个问题的“正确”方法,但我决定使用单表继承,以便我可以轻松获得另一个模型的所有has_many服务的列表(因为每个子类Service也是一个Service,我可以打电话model_instance.services给他们全部)。

为了解决代码重复的问题,我创建了一个模块,用于任何应该has_many :services以及每种类型的服务的模型:

module HasServices
  extend ActiveSupport::Concern
  included do
    has_many :services
    has_many :facebook_services
    has_many :twitter_services
    has_many :wordpress_services
  end
end

Service也知道它的子类,以便可以轻松创建菜单等:

class Service < ActiveRecord::Base

  @child_classes = []

  ...

  protected

    def self.inherited(child)
      @child_classes << child
      super
    end

    def self.child_classes
      @child_classes
    end
end
于 2010-09-26T21:10:37.013 回答