多态关联 - rails

Polymorphic Associations - rails

我在理解 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

除了支持它所需的架构和语法外,没有太大区别。如果你有一些相对大量的 belongs_to :imageable 关系,它作为一个用例就开始有意义了。使用标准命名方法,他们会将表示多个 belongs_to 关联所需的 n 个字段减少为两个,"MODEL_able" 和一个引用目标模型 ID 的 ID。这有利于每个 belongs_to 模型有一个 MODEL_id。对他们来说,这是一场巨大的胜利是相当罕见的,但熟悉是一件好事。

在第二种情况下,您需要在图片 table.

中添加两个外键,即 employee_id 和 product_id

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

t.integer :imageable_id
t.string  :imageable_type

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

例如

典型的图片行 table 看起来像

id | name | imagable_id | imagable_type |

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

所以在这里,第一行的图片属于员工模型,其中包含 ID 为 1 的员工图片。第二行属于产品模型,其中包含 ID 为 3 的产品图片

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

只需添加行

has_many :pictures, as: :imageable

将设置关联。

假设您有这些模型:Post、想法、文章,并且您希望为所有三! 您可以使用三个表来进行评论,例如: Post评论, 创意网, 文章评论 您可以拥有一个通用评论模型并根据相关模型存储每个评论。 正如@Karan Purohit 提到的:)

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- 没有多态。我们使用了两个不同的 table 来做同样的事情。 2- 使用多态我们只创建了一个模型来存储第三个多态模型中两个或两个以上模型的图像。
这里我们需要第三个 table 中的两个库,一个用于 stroe model class name ,第二个用于 record id 。 我们可以取任意两列,但列名应该相同,如 imageable+id imageable+type 在这里我们可以使用 imageable 的任何名称,就像我们可以使用 poly_id poly_type 但我们必须确保我们在模型中使用的是什么。

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