Rails和Postgres:在数组上联接表

时间:2018-09-28 20:15:04

标签: ruby-on-rails postgresql associations

从概念上讲,我要说的是:产品a有5种颜色,将是一组颜色ID。这些颜色ID是链接到颜色表的键,该颜色表保存与颜色相关的数据,例如十六进制表示形式,彩色图像等。最后,我想将颜色表与产品表连接在一起,以便提取颜色相关的数据。

在当前设置中,我有两个表:productscolors。在我的products表中,有一列(color_ids)包含一个整数数组。该数组在colors表中保存colors的ID。为了在Rails中将两者结合在一起,我创建了一个Product类中的自定义SQL字符串,例如:

class Product < ApplicationRecord
  has_many :colors

  def self.custom_query   
    "SELECT * FROM products JOIN colors on colors.id = ANY(products.color_ids)
    WHERE products.name = 'Some Product'"
  end

end

我尝试使用关联(includes(:colors)),但这似乎不起作用,因为主要ID是ID数组。

是否有一种更优雅的/ Rails方式来实现我想做的事情?

2 个答案:

答案 0 :(得分:1)

使用简单的has_and_belongs_to_many关联。不要将您的参考ID存储在数组中,只是因为PostgreSQL允许您这样做,所以这不是应该在关系数据库中实现关系的方式。

# new migration
create_table :colors_products do |t|
  t.references :color, foreign_key: true
  t.references :product, foreign_key: true
end
add_index :colors_products, [:color_id, :product_id], unique: true


class Product < ApplicationRecord
  has_and_belongs_to_many :colors
end

class Color < ApplicationRecord
  has_and_belongs_to_many :products
end

所有ActiveRecord方法将起作用。

为什么不应该与数组建立联系(除非您真的知道自己在做什么):

  1. 您不能使用外键。您将能够在数组中拥有不再在数据库中的color_id。
  2. 如果删除颜色,数据库将无法自动清除所有产品的ID。
  3. ActiveRecord(和大多数ORM)将无法正常工作,您将需要大量的解决方法。

答案 1 :(得分:0)

您可以轻松完成

class Product < ApplicationRecord
  def colors   
    Color.where(id: color_ids)
  end
end

class Color < ApplicationRecord
  def products   
    Product.where('? = Any (category_ids)', id)
  end
end