2010-01-29 2 views
5

Предположим, что у меня такая полиморфная структура.Rails - Кратко находить родительский ресурс полиморфно вложенного ресурса

map.resources :bar, :has_many => :foo 
map.resources :baz, :has_many => :foo 
map.resources :qux, :has_many => :foo 

class Foo 
    belongs_to :parent, :polymorphic => true 
end 

class FooController < AC 
before_filter :find_parent 

... 

private 
def find_parent 
    # ugly way: 
    @parent = if params[:bar_id] 
    Bar.find(params[:bar_id]) 
    elsif params[:baz_id] 
    Baz.find(params[:baz_id]) 
    elsif params[:qux_id] 
    Qux.find(params[:qux_id]) 
    end 
end 
end 

Это довольно уродливо. Всякий раз, когда мы добавляем новую вещь, к которой она может принадлежать, нам нужно добавить ее без DRYly к этому before_filter.

Это также ухудшается. Предположим, что Foos - это действительно полиморфные вещи, которые могут появляться где угодно, как комментарии или теги. И предположим, что у вас есть следующие маршруты:

map.resources :bar, :has_many => :foo do |bar| 
bar.resources :baz, :has_many => :foo 
end 
map.resources :qux, :has_many => :foo do |qux| 
qux.resources :baz, :has_many => :foo 
end 

... теперь мы должны беспокоиться о том, чтобы проверить bar_id или baz_id первым.

Для более сложных ресурсов, возможно, этого будет недостаточно, чтобы убедиться, что вы получаете идентификатор родителя.

Что было бы идеальным, если мы могли бы сделать что-то вроде этого:

def get_parent 
# fetch the parameter that immediately preceeded :id 
@parent = if x = params.before(:id) 
    # polymorphic find 
    x.key.to_s[0..-4].classify.constantize.find x.value 
end 
end 

В конце концов, наши маршруты уже закодировать родителю в силу порядка параметров в URL. Зачем отказываться от этой информации?

Итак: как это можно сделать?

+0

ли вы в конечном итоге найти DRY способ сделать это? – hornairs

ответ

4

Вы должны быть в состоянии попросить foo.parent

Вам нужно иметь что-то вроде этого:

class Bar < ActiveRecord::Base 
    has_many :foos, :as => :parent 
    ... 
end 
+0

Да, таким образом вы наверняка узнаете, что получите настоящего родителя вашего foo. Так как пользователь может передать что-либо в url, и вы получите любой Bar/Baz/Qux для определенных Foo). – Eimantas

+0

Это не обязательно работает в некоторых видах полиморфизма has_many, и это не будет работать вообще для новых записей. Для первых предположим, что один и тот же Foo разделяется между баром и базом, и мне нужно указать (для конкретного запроса), какой из них был эффективным. – Sai

+0

Также не работает для индекса FooController # (который должен знать, какие родительские foos для запроса). – Sai

Смежные вопросы