2012-08-14 11 views
5

Mam model gry, który ma wiele: tekstów. Problem polega na tym, że muszę różnie zamawiać teksty w zależności od tego, do której gry należą (tak, brzydko, ale to dane z wcześniejszych wersji). Stworzyłem metodę Text.in_game_order_query(game), która zwraca odpowiednią kolejność.Odwołując się do wystąpienia w has_many (Rails)

Moim ulubionym rozwiązaniem byłoby umieszczenie domyślnego zakresu w modelu tekstowym, ale wymagałoby to znajomości gry, której są częścią. Nie chcę też tworzyć oddzielnych klas dla tekstów dla każdej gry - jest wiele gier, z których więcej pojawia się, a wszystkie nowsze używają tej samej kolejności. Więc miałem inny pomysł: Transakcja tekstów w has_many, gdy wiem, które gra są częścią:

has_many :texts, :order => Text.in_game_order_query(self) 

Jednak samo jest klasą tutaj, tak, że nie działa.

Czy naprawdę nie ma innego rozwiązania oprócz wywoływania @game.texts.in_game_order(@game) za każdym razem?

Odpowiedz

-1

Myślę, że jeśli chcesz runtime informacje przetwarzane warto to zrobić z:

has_many :texts, :order => proc{ {Text.in_game_order_query(self)} } 
+0

Podwójne nawiasy klamrowe dają błąd składniowy, a tylko jeden zestaw {} wokół niego mówi "Nie można odwiedzić proc". – Sprachprofi

+0

Przepraszam literówka. Tylko jeden zestaw aparatów ortodontycznych. Ale nie jestem pewien, jeśli to działa z: porządku w ogóle. Używam go z: warunkami. Może jeśli proc nie działa, spróbuj lambda lub Proc.new –

0

Oto sposób, gdzie można to zrobić,

has_many :texts, :order => lambda { Text.in_game_order_query(self) } 

Jest to kolejny sposób, który zazwyczaj nie polecam (ale zadziała),

has_many :texts do 
    def game_order(game) 
    find(:all, :order => Text.in_game_order_query(game)) 
    end 
end 

i możesz do nich zadzwonić,

game.texts.game_order(game) 
+0

"Can not visit proc" :-( – Sprachprofi

+0

spróbuj z, 'has_many: texts, lambda {{: order => Text.in_game_order_query (self)}}' – PradeepKumar

+0

"źle liczba argumentów (1 za 0) "- zaczynam myśleć, że to nie jest możliwe :-(Próbowałem również przenieść tę funkcję do modelu gry, dzięki czemu mogę zrobić self.in_game_order_query bez konieczności przekazywania argumentu, ale brak szczęścia. – Sprachprofi

0

Nie jestem pewien co zamówienie/zapytanie wygląda w metodzie klasy in_game_order_query ale uważam, że można to zrobić

has_many :texts, :finder_sql => proc{Text.in_game_order_query(self)} 

Tylko z powiadomieniem, że nigdy nie użył tego wcześniej, ale chciałbym doceń to, jeśli dasz mi znać, czy to działa dla ciebie, czy nie.

Wyjazd http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many więcej dokumentacji: finder_sql

1

Czy Association extension być taka możliwość?

Wydaje się, że można zrobić tę pracę:

module Legacy 
    def legacy_game_order 
    order(proxy_association.owner.custom_texts_order) 
    end 
end 

class Game << ActiveRecord::Base 
    includes Legacy 
    has_many :texts, :extend => Legacy 

    def custom_texts_order 
    # your custom query logic goes here 
    end 
end 

ten sposób, biorąc pod uwagę wystąpienie gra, powinieneś być w stanie uzyskać dostęp do niestandardowych zapytanie instancji bez konieczności przechodzenia w siebie:

g = Game.find(123) 
g.texts.legacy_game_order 
3

W następstwie skorzystania z pomysłu PradeepKumar, znalazłem następujące rozwiązanie do pracy:

Założenie klasy Block, która ma atrybut block_type i co ntainer klasa (słownie Page), można mieć coś takiego:

class Page 
    ... 

    has_many :blocks do 
    def ordered_by_type 
     # self is the array of blocks 
     self.sort_by(&:block_type) 
    end 
    end 

    ... 
end 

Wtedy, kiedy zadzwonić

page.blocks.ordered_by_type 

można dostać to, co chcesz - zdefiniowany przez Proc. Oczywiście procesor może być znacznie bardziej złożony i nie działa w wywołaniu SQL, ale po skompilowaniu zestawu wyników.

UPDATE:
ja ponownie przeczytać ten post i moją odpowiedź po sporo czasu, a ja zastanawiam się, czy można zrobić coś tak prostego jak innej metody, która w zasadzie sugerowanej się na stanowisku.

Co jeśli dodano metoda Game nazywa ordered_texts

def ordered_texts 
    texts.in_game_order(self) 
    end 

Czy to rozwiązało problem? Lub czy ta metoda musi być przenośna z innymi metodami relacji Game?

3

Ostatnio miałem bardzo podobny problem i byłem przekonany, że nie było to możliwe w Railsach, ale nauczyłem się czegoś bardzo interesującego.

Możesz zadeklarować parametr dla zakresu, a następnie go nie przekazać i domyślnie będzie on przekazywał obiekt nadrzędny!

Tak, można tak zrobić:

class Game < ActiveRecord 
    has_many :texts, -> (game) { Text.in_game_order_query(game) } 

Wierzcie lub nie, nie trzeba przechodzić w grze. Rails zrobi to magicznie dla ciebie. Możesz po prostu:

game.texts 

Jest jednak jedno zastrzeżenie. To nie będzie działać obecnie w Railsach, jeśli masz włączone wstępne ładowanie. Jeśli to zrobisz, możesz otrzymać to ostrzeżenie:

OSTRZEŻENIE DEPRECATION: Zakres asocjacji "teksty" jest zależny od instancji (blok zakresu przyjmuje argument). Wstępne ładowanie odbywa się przed utworzeniem poszczególnych instancji. Oznacza to, że żadna instancja nie jest przekazywana do zakresu asocjacji. Najprawdopodobniej spowoduje to nieprawidłowe lub nieprawidłowe zachowanie. Łączenie, wstępne ładowanie i szybkie ładowanie tych powiązań jest przestarzałe i zostanie usunięte w przyszłości.

Powiązane problemy