2013-02-19 16 views
14

Mam zagnieżdżony zasób należący do wielu różnych modeli. Na przykład:Szyny: Pobieranie obiektu nadrzędnego z zagnieżdżonego zasobu

resources :users do 
    resources :histories, only: [:show] 
end 

resources :publications do 
    resources :histories, only: [:show] 
end 

resources :events do 
    resources :histories, only: [:show] 
end 

W HistoriesController, chcę znaleźć obiektu nadrzędnego, choć mam kłopot myślenia suchym sposób sobie z tym poradzić. W tej chwili najlepsze, co mogę wymyślić to:

if params[:user_id].present? 
    @parent = User.find(params[:user_id]) 
elsif params[:publication_id].present? 
    @parent = Publication.find(params[:publication_id]) 
elsif . . . . 

Mam dosłownie dziesiątki modeli mam do oddziału przez w ten sposób, który wydaje niechlujstwa. Czy istnieje lepsze (być może zapieczone) podejście, którego nie rozważam?

Odpowiedz

11
nie

naprawdę rozwiązanie, ale można uciec z

parent_klasses = %w[user publication comment] 
if klass = parent_klasses.detect { |pk| params[:"#{pk}_id"].present? } 
    @parent = klass.camelize.constantize.find params[:"#{klass}_id"] 
end 

jeśli używasz konwencję między nazwy parametrów i modeli

+0

Zaoszczędzi mi to mnóstwo czasu i dużo linii. Dzięki! – nullnullnull

1

Jako alternatywę dla przyjętego odpowiedź, można użyć dynamiczna trasa tak:

get ':item_controller/:item_id/histories/:id', to: 'histories#show' 

ta powinna następnie powinny umożliwić dostęp do klasy nadrzędnej coś takiego w swoim histories_controller.rb

parent_controller = params[:item_controller] 
parent_class = parent_controller.singularize.camelize.constantize 
@parent = parent_class.find(params[:item_id]) 

Możliwe jest również dodanie ograniczenia do elementu item_controller na trasach, jeśli trzeba.

10

Sposób, w jaki to robię, to dodanie nazwy klasy modelu nadrzędnego jako domyślnego parametru na trasie.

Na przykład pytanie to powinno być coś takiego:

resources :users, model_name: 'User' do 
    resources :histories, only: [:show] 
end 

resources :publications, model_name: 'Publication' do 
    resources :histories, only: [:show] 
end 

resources :events, model_name: 'Event' do 
    resources :histories, only: [:show] 
end 

Spowoduje to dodanie nazwy modelu w hash params.

Następnie w kontroler/działania można uzyskać modelu nadrzędnego jak:

params[:model_name].constantize # Gives you the model Class (eg. User) 

i klucza obcego jak:

params[:model_name].foreign_key # Gives you column name (eg. user_id) 

więc można zrobić coś takiego:

parent_class = params[:model_name].constantize 
parent_foreing_key = params[:model_name].foreign_key 

parent_object = parent_class.find(params[parent_foreing_key]) 
+2

To jest świetna, najczystsza odpowiedź IMO – niborg

+0

To jest dobre rozwiązanie, jednak podczas korzystania z niego napotkałem problemy w mojej specyfikacji kontrolera. Nie znalazłem istniejącego Railsowego sposobu ustawiania wartości dla parametru "nazwa_modelu" dla całej specyfikacji kontrolera, więc musiałbym podać wartość w każdej z moich metod spec. – Matt

Powiązane problemy