Ruby on Rails命名为model的class属性

时间:2014-08-31 20:34:49

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

我有两个类Productuser,它们与多态类型有has_many关系。

class User < ActiveRecord::Base
  has_many :pictures, as: :imageable
end

class Product < ActiveRecord::Base
  has_many :pictures, as: :imageable
end

class Picture < ActiveRecord::Base
   belongs_to :imageable, polymorphic: true
end

我还要为profile_picture的用户模型添加新属性,以便@user.profile_picture将返回图片对象。怎么能实现呢?特别是要向用户添加外键的迁移。

编辑:我已经更新了用户模型

has_one :profile_picture, class_name: "Picture", foreign_key: "profile_picture_id"

并添加了以下迁移

add_column :users, :profile_picture_id, :integer

然而,如果有人能够解释我到底做错了什么,我似乎无法设置个人资料图片,我将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:1)

class User < ActiveRecord::Base
  has_many :pictures
  has_one :profile_picture, :class_name => "Picture"
end

class Product < ActiveRecord::Base
  has_many :pictures
end

class Picture < ActiveRecord::Base
   belongs_to :imageable, polymorphic: true
end

答案 1 :(得分:0)

正确使用关联时,没有直接方法来实现此目的。

数据结构错误。您正尝试以两种不同的方式关联同一个模型。问题是:这两种方式相互干扰

您正在尝试使用相同类型存储不同类型的对象。直接的方式(在另一个答案中建议)将使您无法确定哪些只是User的图片以及他们中的profile_picture是什么。因此,任何可能的解决方案都需要添加区分profile_picture的方法。

就在昨天我写了an example on how to use "single table inheritance"。它实际上非常适合这里,您需要两个类似的数据结构以不同的方式运行。为了使它工作,你需要两件事:

  1. pictures表添加STI支持:
    rails g migration AddTypeToPictures type:string:index
    ...并确保添加type类型为string的列,并在其上添加索引。

  2. rails g model ProfilePicture --no-migration --parent=Picture
    此类将被创建为空,但将继承Picture的所有内容,因此在许多情况下它应保持为空。

  3. 然后只需一个简单的关联就可以在任何类上使用:

    has_one :profile_picture, as: :imageable
    

    我们假设我们将其添加到User。然后,查找User的个人资料图片的搜索条件为:

    • type"ProfilePicture"
    • imageable_type"User"
    • imageable_id等于相关用户的id

    搜索变得很麻烦,对吧?嗯,这应该有效,但我不建议所有这些,它有影响和替代方案:

    • 无论您决定添加到ProfilePicture的数据库列,都必须将其添加到Picture,即使它未被使用:它们也存储在同一个表中。
      解决方案:使ProfilePicture成为一个成熟的模型:为其创建一个表,使其继承ActiveRecord::Base
    • 获取用户的个人资料图片需要额外的数据库查询,其中包含三个(哇!)不同的标准。
      解决方案(推荐):将个人资料图片放置在相应模型中的方式与Picture相同:这将不需要额外的查询来获取个人资料图片。