Как заставить контроллер gem обрабатывать несколько произвольных моделей? - PullRequest
0 голосов
/ 06 июня 2011

У меня есть четыре модели, которые я могу комментировать с помощью четырех отдельных контроллеров комментариев.Эти четыре контроллера комментариев, по сути, делают одно и то же и отличаются незначительно.

В попытке удалить дублирование четырех комментирующих контроллеров, которые по сути все одинаковы, я создал Rails Engine в качестве самоцвета для произвольного выбора.обрабатывать комментирование любой произвольной модели, которую я указываю в route.rb.

Так что в моем файле rout.rb теперь я могу использовать:

comments_on :articles, :by => :users

с comments_on, реализованным следующим образом в моем геме:

def comments_on(*resources)
  options = resources.extract_options!

  [snip of some validation code]

  topic_model = resources.first.to_s
  user_model = options[:by].to_s

  # Insert a nested route
  Rails.application.routes.draw do
    resources topic_model do
      resources "comments"
    end
  end
end

Маршруты отображаются в «Rake Routes», и запросы правильно перенаправляются на «драгоценный камень» моего контроллера «CommentsController», но на этом функциональность моего драгоценного камня заканчивается.

Как лучше всего обнаружитьконтекст в моем геме CommentsController, так что я могу обрабатывать запросы, специфичные для того, как были вызваны comments_on?

Более конкретно, как бы я реализовал действие индекса, подобное следующему, с учетом его контекста?

def index
  @article = Article.find(params[:article_id])
  @comments = ArticleComment.find(:all, :conditions => { :article_id => @article.id })
end

Спасибо за помощь!

1 Ответ

1 голос
/ 07 июня 2011

Вы можете указать тему в качестве дополнительного параметра в ваших маршрутах:

Rails.application.routes.draw do
  resources topic_model do
    resources "comments", :topic_model => topic_model.to_s
  end
end

Тогда ваш контроллер можно записать так:

def index
  @topic = topic
  @comments = topic.comments
end

protected
def topic
  m = params[:topic_model]
  Kernel.const_get(m).find(params["#{m.underscore}_id"])
end

Вы можете переместить многологика из контроллера и в модель, а также.topic.comments может быть именованной областью, которую должны реализовывать все эти модели.

В прошлом я делал подобные шаблоны, и обычно есть крайний случай, который разрушает эту идею, и вы в конечном итоге делаете больше 'мета программирование, чем мудро.

Я бы порекомендовал сделать базовый контроллер, а затем создать упрощенные контроллеры, которые унаследовали бы от этого, или попытаться разделить эти общие поведения на модули.

...