多态关联 - 轨道

时间:2016-09-02 05:07:59

标签: ruby-on-rails activerecord polymorphic-associations

我在了解rails中的多态关联时遇到了一些麻烦。 怎么样?

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

class Employee < ApplicationRecord
  has_many :pictures, as: :imageable
end

class Product < ApplicationRecord
  has_many :pictures, as: :imageable
end

不同
class Picture < ApplicationRecord
  belongs_to :employee
  belongs_to :product
end

class Employee < ApplicationRecord
  has_many :pictures
end

class Product < ApplicationRecord
  has_many :pictures
end

4 个答案:

答案 0 :(得分:3)

除了支持它所需的模式和语法之外没有太大区别。如果你有一些相对大量的belongs_to:imageable关系,它将作为一个用例开始有意义。使用标准命名方法,它们将n个表示多个belongs_to关联所需的字段减少为两个,“MODEL_able”和一个引用目标模型id的id。这有利于为每个belongs_to模型设置MODEL_id。他们很难成为一个巨大的胜利,但是熟悉它是一件好事。

答案 1 :(得分:3)

在第二种情况下,您需要在图片表中添加两个外键,即employee_id和product_id。

在图片迁移的第一种情况t.references :imageable, polymorphic: true中,将在图片表中添加两个字段,即

t.integer :imageable_id
t.string  :imageable_type

imagable_type字段将是与您将此模型关联到的类的名称,而imagable_id将保存该记录的ID。

e.g,

图片表的典型行看起来像

id | name | imagable_id | imagable_type |

1  | pic1 | 1           | Employee      |
2  | pic2 | 3           | Product       |

所以这里,第一行图片属于员工模型,持有ID为1的员工图片。第二行属于产品型号,持有ID为3的产品图片

第一种方法的优点是您可以在以后将图片模型与任何其他模型相关联,而无需添加外键。

只需添加一行

即可
has_many :pictures, as: :imageable

将设置关联。

答案 2 :(得分:1)

Without Polymorphic
20160902065429_create_employee_images
class CreateEmployeeImages < ActiveRecord::Migration[5.0]
    def change
        create_table :employee_images do |t|
            t.integer :employee_id
            t.string :image

            t.timestamps
        end
    end
end
20160902065445_create_product_images
class CreateProductImages < ActiveRecord::Migration[5.0]
    def change
        create_table :product_images do |t|
            t.integer :product_id
            t.string :image
            t.timestamps
        end
    end
end

app/model/employee.rb
class Employee < ApplicationRecord
    has_many :employee_images
end

app/model/product.rb
class Product < ApplicationRecord
    has_many :pictures, as: :imageable
end

app/model/employee_image.rb
class EmployeeImage < ApplicationRecord
    belongs_to :employee
end

app/model/product_image.rb
class ProductImage < ApplicationRecord
    belogs_to :product
end

With Polymorphic

db/migrate/20160902063459_create_products.rb
class CreateProducts < ActiveRecord::Migration[5.0]
    def change
        create_table :products do |t|
            t.string :name
            t.timestamps
        end
    end
end

db/migrate/20160902063513_create_employees.rb
class CreateEmployees < ActiveRecord::Migration[5.0]
    def change
        create_table :employees do |t|
            t.string :name
            t.timestamps
        end
    end
end

db/migrate/20160902063602_create_pictures.rb
class CreatePictures < ActiveRecord::Migration[5.0]
    def change
        create_table :pictures do |t|
            t.string :picture
            t.integer :imageable_id
            t.string :imageable_type
            t.string :image

            t.timestamps
        end
    end
end

app/model/employee.rb
class Employee < ApplicationRecord
    has_many :pictures, as: :imageable
end

app/model/picture.rb
class Picture < ApplicationRecord
    belongs_to :imageable, polymorphic: true
end

app/model/product.rb
class Product < ApplicationRecord
    has_many :pictures, as: :imageable
end

1-没有多态性。我们使用了两个不同的表来做同样的事情。 2-对于多态,我们只创建了一个模型来存储第三个多态模型中两个或两个以上模型的图像。
这里我们在第三个表中需要两个coulms,一个用于stroe模型类名,第二个用于记录id。 我们可以使用任意两列,但列名应该与imageable + id imageable + type相同 在这里我们可以使用任何可成像的名称,就像我们可以使用poly_id poly_type但我们必须确保我们在模型中使用的是什么。

如果我们使用poly_id和poly_type,那么我们必须在picture.rb和has_many:pictures中使用belogs_to:poly,polymorphic:true,如::employee.rb和product.rb中的poly     在两者中。

答案 3 :(得分:0)

想象你有这些模型:帖子,想法,文章,你想拥有所有三个的评论模型! 你可以有三个表来评论: 发表评论, IdeaCommnet, ArticleComment 您可以拥有一般评论模型,并根据其相关模型存储每条评论。 正如@Karan Purohit所说:)