可以使用 postgres 数组在 rails (4) 中创建一对多/has_many 关联吗?我知道外键类型数组是不可能的。
示例:一个任务有多个受理人。传统上我会使用关联表来解决这个问题:tasks->assignees->users。使用数组,这将不是必需的,因为可以存储多个“外键”。
然后可以使用以下查询来获取分配给我的所有任务:
select * from tasks where ? IN tasks.assignees
可以使用 postgres 数组在 rails (4) 中创建一对多/has_many 关联吗?我知道外键类型数组是不可能的。
示例:一个任务有多个受理人。传统上我会使用关联表来解决这个问题:tasks->assignees->users。使用数组,这将不是必需的,因为可以存储多个“外键”。
然后可以使用以下查询来获取分配给我的所有任务:
select * from tasks where ? IN tasks.assignees
您将无法让 Rails 知道该数组并将其用于关联。
但是,如果您想更快地搜索/过滤分配给用户的任务,您可以在任务对象中保留一组用户 ID。否则,您必须执行 JOIN 才能在标准关联表中查找分配给 Alice 的所有任务。
因此解决方案是保留关联表,同时将受理人用户 ID 复制到任务对象中,并使用该 ID 列表进行更快的搜索/过滤。
您需要连接到受让人对象的after_create
生命after_destroy
周期,并将新的受让人 ID 插入到任务记录数组中。然后,当从任务中删除受让人时,更新数组以删除 ID。
有关所有 Array 运算符,请参阅 Postgres 文档:
像这样的东西:
class Task < ActiveRecord::Base
has_many :assignees, :dependent => :destroy
end
class Asignee < ActiveRecord::Base
belongs_to :task
after_create :insert_task_assignee
after_destroy :remove_task_assignee
# assumes that there is a column called assignee_id
# that contains the User ID of the assigned person
private
def insert_task_assignee
# TODO: check for duplicates here - before we naively push it on?
task.assignee_list = task.assignee_list.push(assignee_id)
task.assignee_list.save
end
def remove_task_assignee
id_list = task.assignee_list
id_list.reject! { |candidate_id| candidate_id == assignee_id }
task.assignee_list = id_list
task.assignee_list.save
end
end
# find all tasks that have been assigned Alice & Bob
# this will require the `postgres_ext` gem for Ruby / Postgres array searching
tasks = Task.where.contains(:assignee_list => [alice.id, bob.id]).all