11

可以使用 postgres 数组在 rails (4) 中创建一对多/has_many 关联吗?我知道外键类型数组是不可能的。

示例:一个任务有多个受理人。传统上我会使用关联表来解决这个问题:tasks->assignees->users。使用数组,这将不是必需的,因为可以存储多个“外键”。

然后可以使用以下查询来获取分配给我的所有任务:

select * from tasks where ? IN tasks.assignees
4

1 回答 1

6

您将无法让 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
于 2013-06-09T17:35:32.787 回答