2009-07-02 16 views
8

Zastanawiam się, czy istnieje skuteczny sposób łączenia wyników wielu obiektów ActiveRecord w Railsach. Na przykład mogę wykonać trzy indywidualne wywołania do trzech osobnych tabel i chcę, aby wyniki zostały połączone i posortowane według wspólnej kolumny.Jak łączyć obiekty ActiveRecord?

Oto bardzo prosty przykład kodu, który, miejmy nadzieję uczynić moje pytanie łatwiej zrozumieć:

@results1 = Table1.find(:all) 
@results2 = Table2.find(:all) 
@results3 = Table3.find(:all) 

@combined_results_sorted_by_date_column = (how?) 

Jak sugeruje innym, oto jedno rozwiązanie tego problemu.

@combined_results = @result1 + @result2 + @result3 
@combined_results.sort! {|x,y| x.date <=> y.date} 

Co zrobić, jeśli chcę sortować według daty, ale tabela 3 odnosi się do kolumny "created_on" jako daty?

Odpowiedz

2

Nie pracujesz z "Tabelami", ale raczej z obiektami.

Jeśli myślisz o tym w ten sposób, że to nie ma sensu mieć:

@results1 = Users.find(:all) 
@results2 = Posts.find(:all) 
@results3 = Comments.find(:all) 

Co miałby „kombinowane” forma to znaczy?

Najprawdopodobniej chcesz połączyć wyniki tego samego rodzaju za pomocą różnych "zapytań". Czy to prawda?

+0

Mam zastosowanie, połączone komentarze, statusy i zatwierdzenia na osi czasu w aplikacji do zarządzania problemami. – dangerousdave

+0

W tym przypadku wszyscy muszą odpowiedzieć na konkretny interfejs lub mieć sposób na zmapowanie w jeden. Najważniejsze jest to, że myślenie o tym w kategoriach "tabel bazy danych" doprowadzi cię do złych projektów. Nie próbowałem sugerować, że nie korzystasz z danych z różnych miejsc, tylko zastanawiasz się, jak się do tego podejść. –

0
@combined_results = @result1 + @result2 + @result3 
@combined_results.sort! {|x,y| x.date <=> y.date} 

Chociaż na pewno nie jest to najbardziej wydajny kod na świecie, może być po prostu tym, czego potrzebujesz.

Jeśli niektóre modele nie mają metody wyświetlania dat, proponuję ją utworzyć. To jest tak proste, jak.

def date 
    created_on 
end 
0
@results1 = Table1.find(:all) 
@results2 = Table2.find(:all) 
@results3 = Table3.find(:all) 

combined = (@results1 + @results2 + @results3).sort { |x, y| x.date <=> y.date } 
+0

Co zrobić, jeśli chcę sortować według daty, ale tabela 3 odnosi się do kolumny "created_on" jako daty? Wielkie dzięki! – Jess

+0

Można to rozwiązać, dodając metodę "date()" do tabeli 3, która zwraca wartość "created_on". – Ethan

14
@results1 = Table1.find(:all) 
@results2 = Table2.find(:all) 
@results3 = Table3.find(:all) 

@combined_results_sorted_by_date_column = 
    (@results1 + @results2 + @results3).sort_by(&:date) 

Co jeśli chcę sortować według daty, ale Table3 odnosi się do "created_on" kolumny jako nieaktualne?

class Table3 
    alias_method :date, :created_on 
end 

lub po prostu

class Table3 
    alias date created_on 
end 
0

Nie jestem pewien, co się ilości danych są podobne, ale kiedy przychodzi do sortowania bazy danych zrobi lepszą robotę niż kiedykolwiek będzie przy użyciu " "kod warstwy aplikacji".

Potrzebujesz danych zwróconych jako tablica obiektów modelu, ponieważ trzy tabele prawdopodobnie wygenerują zmiksowaną tablicę trzech odrębnych klas modeli?

Dlaczego nie używać wierszy i kolumn zwracanych przez SQL-SQL i czy DB wykonuje całą ciężką pracę, sortując dane?

1

Prawdopodobnie nie spodoba ci się ta odpowiedź, ale powiedziałabym, że warto poprawić schemat bazy danych. Byłem w podobnej sytuacji, a sortowanie wyników po ich zespoleniu zdecydowanie nie jest tym, do czego chcesz się udać.

+1

Wierzę ci, ale czy mógłbyś bardziej szczegółowo opisać, jak poradziłeś sobie z sytuacją? – iterion

0

Zakładam, że chcesz mieć mieszaną tablicę trzech różnych typów obiektów ActiveRecord, posortowaną według daty.

@array = (Bucket.all + Mop.all + Detergent.all).sort{|x,y| x.sort_by <==> y.sort_by} 

Ponieważ pole sort_by jest różne dla każdego typu obiektu, należy go zdefiniować.

class Bucket < ActiverRecord::Base 
    def sort_by 
    cleaned_on 
    end 
end 

class Detergent < ActiverRecord::Base 
    def sort_by 
    purchased_on 
    end 
end 

Można pobrać wszystkie dane posortowane w jednym zapytaniu przy użyciu UNION, ale nie można uzyskać obiektów AR z tego.