如何在没有belongs_to的情况下从has_one关联中检索属性?

时间:2015-06-10 17:40:48

标签: ruby-on-rails ruby-on-rails-3.2 redmine-plugins

我有几个嵌套类看起来像这样:

class Presentation < ActiveRecord::Base
  has_many :campaign_records, :as => :campaignable

  def campaign_records_text(joiner)
    return '' if self.campaign_records.blank?
    self.campaign_records.map {|c| c.to_s}.join(joiner)
  end
end

class CampaignRecord < ActiveRecord::Base
  belongs_to :campaignable, :polymorphic => true
  has_one :campaign
  has_one :tier_one
  has_one :tier_two

  def to_s
    "#{campaign.name} - #{tier_one.name} - #{tier_two.name}"
  end
end

class Campaign < ActiveRecord::Base
   has_many :tier_ones

   attr_accessible :name
end

class TierOne < ActiveRecord::Base
   has_many :tier_twos
   belongs_to :campaign

   attr_accessible :name
end

class TierTwo < ActiveRecord::Base
   belongs_to :tier_one

   attr_accessible :name
end

总而言之,Campaign有许多关联的TierOne s,而每个TierOne都有自己的TierTwo套。 Presentation有一组CampaignRecord个,它们将CampaignTierOneTierTwo链接在一起。请注意,Campaign 不属于 CampaignRecord,因为许多CampaignRecord可以引用它。

所以这就是问题所在:我想更改CampaignRecord.to_s方法以返回“campaign.name - tier_one.name - tier_two.name”(如上所示),但这样做会导致我尝试拨打some_campaign_record.to_s时出错:

  

ActionView :: Template :: Error(Mysql2 ::错误:未知列   'where子句'中的'campaigns.campaign_record_id':选择'广告系列'。*   来自'广告系列'在哪里'广告系列'。'campaign_record_id'=#LIMIT 1)

我在哪里出错?我知道rails auto会为我生成很多getter和setter,但默认的to_s方法就是常用的,所以如何以正确的rails方式覆盖它? has_one是否需要belongs_to或是否有belongs_to_many隐藏在我应该使用的地方?

非常感谢任何帮助!提前谢谢!

(另外,我看到我的问题与this unanswered question

非常相似

修改

我在这里看到一些关于模型结构的混淆,所以让我试着用一种希望更清晰的方式来解释它。

首先,要明确Campaign 与<{1}}非常不同

将Campaign-TierOne-TierTwo关系想象为三层列表:

  1. 广告系列1
    • TierOne 1.1
      • TierTwo 1.1.1
      • TierTwo 1.1.2
      • ...
    • TierOne 1.2
      • TierTwo 1.2.1
      • TierTwo 1.2.2
      • ...
    • ...
  2. 广告系列2
    • TierOne 2.1
      • TierTwo 2.1.1
      • TierTwo 2.1.2
      • ...
    • TierOne 2.2
      • TierTwo 2.2.1
      • TierTwo 2.2.2
      • ...
    • ...
  3. 活动3 ...
  4. CampaignRecord模型表示Campaign,TierOne,TierTwo元组。首次创建时,您选择一个Campaign。然后从该Campaign的TierOnes集中选择一个TierOne。然后是来自TierOne的TierTwos的TierTwo。换句话说,CampaignRecord模型是遍历Campaign-TierOne-TierTwo树的路径。

    CampaignRecord的集合是用户先前与该表示实例关联的有效Campaign-TierOne-TierTwo路径的集合。 (演示文稿将与这些路径中的零个或多个相关联。)

    功能的重要一点是,Presentation应该具有一组可变大小的Campaign-TierOne-TierTwo链接。在修改任何给定的演示文稿时,我需要能够修改/添加/删除Campaign-TierOne-TierTwo与演示文稿的链接。我选择将这些Campaign-TierOne-TierTwo链接表示为presentation.campaign_records。演示文稿可以包含大量这些CampaignRecords,但没有Campaign,TierOne或TierTwo将CampaignRecords一个CampaignRecord。

    所以,我的问题变成了:为什么我的belong_to模型抛出“找不到指定的列”错误,因为它从来不应该首先查找该列?

    Campaign

2 个答案:

答案 0 :(得分:0)

根据上述评论,我看到的一个错误如下:

class CampaignRecord < ActiveRecord::Base
  ...
  has_one :tier_two
  ...
end

看看Rails Guide on Associations.。 Campaign会在任何具有has_ 某种关联的ActiveRecord模型中看到campaign_record_id。

我最好的选择是你要将该列添加到TierTwo数据库中。

或者,如果每个 TierTwo的CampaignRecord都可以通过其TierOne推断出来,那么您也可以假设:

class CampaignRecord < ActiveRecord::Base
  ...
  has_many :tier_twos, through: :tier_one
  ...
end

然而,这似乎不是正确的选择。你说CampaignRecord只有一个TierTwo,而TierOne可以有许多 TierTwos。

如果这有帮助,请告诉我。我可能错过了一些有助于澄清我的建议的业务逻辑信息。

答案 1 :(得分:0)

事后看来,解决方案现在对我来说非常明显。我的CampaignRecord模型具有用于存储其他模型记录的ID的字段。但是CampaignRecord中的has_one意味着其他模型应该存储CampaignRecord的ID。解决方案是将has_one更改为belongs_to,以便查找向另一个方向发送:

class CampaignRecord < ActiveRecord::Base
  belongs_to :campaignable, :polymorphic => true
  belongs_to :campaign
  belongs_to :tier_one
  belongs_to :tier_two

  def to_s
    "#{campaign.name} - #{tier_one.name} - #{tier_two.name}"
  end
end