【问题标题】:Rails: Multiple relationships between two modelsRails:两个模型之间的多重关系
【发布时间】:2014-07-14 08:51:59
【问题描述】:

我正在 Rails 4.0.4 中创建数据库迁移,我想捕获以下关系:

一位客户有许多信用卡。一位客户只有一张默认信用卡。

我认为它应该是这样的。

class Customer < ActiveRecord::Base
  has_many :cards
  has_one :card # i.e. has one default card
end

class Card < ActiveRecord::Base
  belongs_to :customer
end

这是正确的吗?如果是这样,Rails 怎么知道Card 类中的belongs_to 指的是哪个关系?如果它不正确(我猜是这样),请帮我修复它。

【问题讨论】:

  • 在你的情况下,我将使用has_many :cards 并在cards 表中制作is_default 之类的is_default。默认卡将具有is_defaulttrue
  • 或者你可以这样做has_one :default_card, :class_name =&gt; "Card"
  • 我也建议与@Pavan 相同的答案,为简单起见,您可以为默认卡定义一个范围,这样您只需要 1 个关系。

标签: ruby-on-rails ruby-on-rails-4 rails-migrations


【解决方案1】:

我会把瞄准镜放在卡片的一侧,对我来说似乎更容易

class Customer < ActiveRecord::Base
  has_many :card
end

class Card < ActiveRecord::Base
  belongs_to :customer
  scope :default, -> { where is_default: true }
end

default_card = customer.cards.default

【讨论】:

  • 在我看来,这个过程比同一个模型有多个关联更好。更强大且易于维护
  • @PamioSolanky 我同意。干净!
  • 唯一的缺点是在Cards 表中添加一个is_default 字段,这需要额外的实现逻辑来维护一张默认卡/客户
  • 所以我正在尝试实现check_single_default_card 方法来检查以确保只有一张卡设置为默认值(它在Card 模型中有一个before_save 触发器)。如何从Card 模型访问它所属的Customer
【解决方案2】:

目前,您的代码通过 has_one :cardhas_many :cards 足以混淆 Rails。您应该使用专门为这些类型的关联提供的 class_name 选项。

这样的东西应该适合你

class Customer < ActiveRecord::Base
  has_many :cards
  has_one :default_card, :class_name => "Card"
end

【讨论】:

  • 谢谢。我还需要在Card 模型上添加任何内容吗?
  • @Yazin 不,这就够了。
【解决方案3】:

foreign_key

要添加到Pavan's 答案,您需要使用某种条件来确定哪个是default 卡。

因为 Rails 的 relational database 结构依赖 foreign_keys 来提取相关数据,所以您需要为您的 default_card 分配正确的 foreign_key,或者使用条件来查找它:

#app/models/customer.rb
Class Customer < ActiveRecord::Base
   has_one :default_card, -> { where default: true" },class: "Card", foreign_key: "customer_id"
end

这将依赖于在您的 cards 表中包含布尔列 default

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多