2013-06-09 13 views
11

Czy tablice postgresów można wykorzystać do utworzenia związku jeden-do-wielu/has_many w szynach (4)? Mam świadomość, że tablica typów kluczy obcych nie jest możliwa.Szyny/słupki, "klucze obce" przechowywane w tablicy, aby utworzyć jedno-wiele skojarzeń

Przykład: zadanie ma wielu cesjonariuszy. Tradycyjnie rozwiązałbym to za pomocą tabeli powiązań: tasks-> assignees-> users. Korzystanie z tablic nie jest konieczne, ponieważ można zapisać wiele "kluczy obcych".

Następująca kwerenda mogłyby być następnie wykorzystane, aby wszystkie zadania przypisane do mnie:

select * from tasks where ? IN tasks.assignees 
+5

Będziesz zainteresowany wiedząc, że klucze obce tablicowe oparte są w trakcie opracowywania. Mogą dostać się do PostgreSQL 9.4, ale nie sądzę, że zrobili to dla 9.3. –

Odpowiedz

6

Nie będzie w stanie dokonać Szyny świadomi tej tablicy i użyć go do stowarzyszeń.

Ale jeśli chcesz szybciej wyszukiwać/filtrować zadania przypisane do użytkowników, możesz zachować tablicę identyfikatorów użytkowników w obiekcie zadania. W przeciwnym razie musisz wykonać JOIN, aby znaleźć wszystkie zadania przypisane Alice w standardowej tabeli powiązań.

Rozwiązaniem jest więc zachowanie tabeli powiązań, ale także skopiowanie identyfikatora użytkownika cesjonariusza w obiekcie zadania i użycie tej listy identyfikacyjnej do szybszego wyszukiwania/filtrowania.

Konieczne będzie przechwycenie w cykl życia after_create i after_destroy dla obiektów cesjonariusza i wstawienie nowych identyfikatorów Identyfikatora do tablicy rekordów Zadań. A następnie, gdy osoba wyznaczona zostanie usunięta z zadania, zaktualizuj tablicę, aby usunąć identyfikator.

See Postgres docs dla wszystkich operatorów tablicy:

coś takiego:

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 
+0

Ale jak sprawić, by szyny były świadome asocjacji przez tablicę, aby załadować modele, gdy są one włączone? – Xeago

+1

Nie można uświadomić szynom powiązania za pośrednictwem tablicy. Będzie to wykorzystywane tylko jako podstawowy mechanizm "buforowania" i potencjalnie będzie optymalizacją, ponieważ zadania mogą być wykonywane bezpośrednio, zamiast wykonywać "JOIN". –

Powiązane problemy