Rails通过单个模型实现多个has_many关系

时间:2011-08-25 10:20:23

标签: ruby-on-rails model has-many polymorphic-associations

我想知道如何处理以下情况:

Page has_many Assets

Stylesheet has_many Assets

Javascript has_many Assets

现在我希望能够执行以下查询:

Page.first.assets#显示此页面的所有资产(样式表和javascripts)

Page.first.assets.javascripts#显示此页面的所有javascript资源(样式表相同)

Javascript.first.pages#显示包含此javascript的所有页面(样式表相同)

我目前有这样的设置:

Assets:
  stylesheet_id
  javascript_id
  page_id

  belongs_to :stylesheet
  belongs_to :javascript
  belongs_to :page

  scope :stylesheets, where{ stylesheet_id != nil } ###
  scope :javascripts, where{ javascript_id != nil } # uses "squeel" gem

Pages:
  has_many :assets
  has_many :stylesheets, through: :assets
  has_many :javascripts, through: :assets

Stylesheets/Javascripts:
  content (text field)

  has_many :assets
  has_many :pages, through: :assets

问题不在于它不起作用

然而,感觉这不是正确的方法,因为我在*_id模型中有三个Assets字段。 javascript_idstylesheet_idpage_id。对于每一行,javascript_idstylesheet_id在这种情况下都会为空,这对我来说就像是一种代码味道。

有关如何处理这种情况的任何建议吗?

1 个答案:

答案 0 :(得分:1)

@rubish感谢您的帮助,以及其他stackoverflow帖子,我现在有以下工作,但我仍然觉得我要么过于复杂或缺少一些关键信息,但至少它是有效的(大多数情况下)

模型/ theme.rb

class Theme < ActiveRecord::Base
   attr_accessible #none

   belongs_to :website
   has_many :pages
   has_many :assets, class_name: "ThemeAsset", dependent: :destroy

   has_many :styles, class_name: "AssetStyle", through: :assets, source: :assetable, source_type: "AssetStyle"
   has_many :scripts, class_name: "AssetScript", through: :assets, source: :assetable, source_type: "AssetScript"
 end

模型/ theme_asset.rb

class ThemeAsset < ActiveRecord::Base
  attr_accessible :assetable

  belongs_to :assetable, polymorphic: true
  belongs_to :theme
end

模型/ asset_style.rb

class AssetStyle < ActiveRecord::Base
  attr_accessible #none

  has_many :assets, class_name: "ThemeAsset",  as: :assetable
end

模型/ asset_script.rb

class AssetScript < ActiveRecord::Base
  attr_accessible #none

  has_many :assets, class_name: "ThemeAsset",  as: :assetable
end

以下允许我使用不同的资产,但我不知道这是否是正确的方法,因为:

  • theme.assets显示所有theme_asset行,assetable_idassetable_type

  • 我找不到通过theme.assets.scripts仅显示样式或脚本的默认方式,但我想我可以使用scope,与我原来的问题相同

  • 如果我theme.styles.create保存了样式,但没有记录添加到asset表中,这意味着我永远无法通过theme.assets找到它。

  • 添加两条记录的唯一方法是使用theme.assets.create(assetable: theme.styles.new)(简化)

这是正确的方法,如果没有,任何人都可以建立在我的解决方案之上吗?提前谢谢。