【问题标题】:Rails has_many unique scopeRails has_many 唯一范围
【发布时间】:2021-05-13 03:35:08
【问题描述】:

我有两个模型

class Campaign < ApplicationRecord
  has_many :ads
end
class Ad < ApplicationRecord
  belongs_to :campaign
  belongs_to :platform
  validates :platform, uniqueness: { scope: :campaign }
end

基本上,在一个广告系列中,我不能有两个广告属于同一个平台。

我想要实现的是达到一种干净的方式来实现一个范围来检索每个平台的广告。 示例:

Campaign.find(1).facebook

Campaign.find(1).ads.facebook

将返回此活动的唯一 Facebook 广告。

应该在广告系列模型或广告模型上实施此范围,您将如何实施?

感谢所有想法。谢谢!

【问题讨论】:

  • 平台列表是硬编码的吗?还是您希望方法是动态的?
  • @SiimLiiser 它们是动态的并存储在数据库中。但是,如果您对硬编码后的操作有什么建议,请继续!

标签: ruby-on-rails postgresql activerecord


【解决方案1】:

您可以在广告模型中创建for_platform 范围

class Ad < ApplicationRecord
  belongs_to :campaign
  belongs_to :platform
  validates :platform, uniqueness: { scope: :campaign }
  scope :for_platform, -> (platform) { where(platform: Platform.find_by(name: platform) }
end

my_campain.ads.for_platform(:facebook).take

如果你想要一个facebook 方法,你可以使用上面的方法和method_missing 上的Campaign 来做到这一点

class Ad < ApplicationRecord
  belongs_to :campaign
  belongs_to :platform
  validates :platform, uniqueness: { scope: :campaign }
  scope :for_platform, -> (platform) { where(platform: Platform.find_by(name: platform) }
end

class Campaign < ApplicationRecord

  private

  def method_missing(m, *args, @block)
    if Platform.find_by(name: m)
      return ads.for_platform(m).take
    end
    super
  end  
end

my_campain.facebook # assumes there's a platform with name 'facebook'

【讨论】:

  • 感谢@SteveTurczyn 的提议!我对它进行了一些扩展,我最终在我添加的 Campaign 模型中添加了 has_one :facebook_ad, lambda {merge(Ad.for_platform("facebook"))}, class_name: "Ad"。这样我就可以安全地拨打my_campaign.facebook
猜你喜欢
  • 1970-01-01
  • 2012-02-13
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多