Что такое СУХОЕ решение для маршрутов и контроллера с полиморфным ресурсом, подключенным к обоим из пары вложенных ресурсов? - PullRequest
1 голос
/ 02 января 2012

Отказ от ответственности: первый месяц разработки с рельсами, но я прочитал все, что смог найти.

Редактировать: Почему-то я пропустил этот очень похожий вопрос с аналогичным окончательным ответом.

У меня есть полиморфные флаги:

Class Flag...
  belongs_to :flaggable, :polymorphic => true
  ...
end

У меня есть вложенные ресурсы с соответствующим оператором has_many: flags,: as =>: flaggable.

resources :posts do
  resources :comments
end

Мне бы хотелосьи посты, и комментарии, и в будущем другие вещи на сайте будут помечены. Что такое СУХОЙ / стандартный способ (я использую Rails 3.1) для этого в отношении маршрутов и контроллера?


Что я сделал для маршрутов:

В основном на основе этого рельса, приведенного , я сделал флаги как вложенный ресурс как постов, так и комментариев.Я уже думаю, что я на неправильном пути, потому что кажется, что он повторяет полиморфные отношения в моделях, а также нарушает принцип, согласно которому «Ресурсы никогда не должны быть вложены глубже, чем на один уровень».

resources :posts do
  resources :flags
  resources :comments do
    resources :flags
  end
end

В качестве альтернативы я подумал о том, чтобы реализовать маркируемые маршруты отдельно, как показано ниже.Но опять же, это не кажется СУХИМЫМ и дополнительно создает нежелательные независимые маршруты для комментариев.

resources :posts do
  resources :flags
end
resources :comments do
  resources :flags
end

Наконец, мне стало интересно, смогу ли я сделать общий ресурс для флагманских объектов.Я не мог найти способ реализовать это, и у него есть та же проблема, что и в предыдущем способе сделать общие маршруты доступными для универсального типа flaggable.

resources :flaggable do
  resources :flags
end

Что я сделал для контроллера дляперечисленные выше вложенные ресурсы:

Я реализовал find_flaggable, но понял, что для вложенных ресурсов параметром, который преобразуется в класс flaggable, может быть либо Post, либо Comment, поскольку оба они заканчиваются параметрами (post_id и comment_id).Я мог бы решить нижеприведенный список приоритетов идентификатора для текущей настройки, но это не общее решение и делает его еще менее СУХИМЫМ, чем оно уже есть.

def find_flaggable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      return $1.classify.constantize.find(value)
    end
  end
  nil
end

Так вот где яостановился (на самом деле реализовал ограниченное решение только для сообщений и комментариев) и понял, что не знаю удовлетворительного способа сделать это.Кто-нибудь может помочь?

Ответы [ 3 ]

2 голосов
/ 06 января 2012

Просто, чтобы решить проблему СУШКИ кода в ваших маршрутах, можно использовать

.
[:posts, :comments, :yet_another_resource].each do |resource_type|
  resources resource_type do
    resources :flags
  end
end

вместо

resources :posts do
  resources :flags
end
resources :comments do
  resources :flags
end

Это начинает становиться действительно чистым и полезным, когда у вас много действий под вложенными ресурсами. Вроде как простая версия рефакторинга «Извлечь метод» для ваших маршрутов.

EDIT

Если вы пропустили мой комментарий, я думаю polymorphic_url - это то, что вы ищете !!

1 голос
/ 04 января 2012

Поскольку вы пытаетесь пометить статью, а не манипулировать коллекцией ресурсов флага, я бы просто создал метод flag в контроллерах для ресурсов, которые вы можете пометить.просто создайте флаг из самого ресурса.

class PostsController < ApllicationController
  ...

  def flag
    @post = Post.find(params[:id])
    flag = @post.flags.build(params[:flag])

    if flag.save
      flash[:notice] = "Post flagged"
    else
      flash[:notice] = "Unable to flag post"
    end
    render @post
  end
end

rout.rb:

 resources :posts do
   post 'flag', :on => member
   resources :comments do
     post 'flag', :on => member
   end
 end

Что-то подобное должно работать, это не СУЩЕСТВЕННЫЙ способ сделать это.Но, вероятно, я бы это реализовал.

0 голосов
/ 07 января 2012

Спасибо за ответы.Вот то, что я в конечном итоге использовал, хотя я не совсем доволен этим.Это похоже на полуморфный полиморфизм, так как родитель полиморфного ресурса фактически должен быть непосредственно «напечатан» где-то вдоль линии.В решении Джейка в контроллере.В Азоло осуществляется разметка флагов на различные контроллеры.Я надеялся найти способ позволить Rails выполнять типизацию и упростить код приложения.

Чтобы ответить на мой первый вопрос о маршрутах, кажется, что никого не беспокоит наличие неиспользуемых маршрутов, вызванных, например, путём вводакомментарии на базовом уровне с флагами в качестве дочернего ресурса (как в ответе Джейка).Поэтому я принял ответ Джейка как способ настройки маршрутов.Хелперы полиморфного пути тоже хороши.

[:posts, :comments, :yet_another_resource].each do |resource_type|
  resources resource_type do
    resources :flags
  end
end

Это может привести к использованию контроллера флага, который принимает различные хелперы полиморфного пути с чем-то вроде find_flaggable из railscast в моем вопросе.

def find_flaggable
  params.each do |name, value|
    if name =~ /(.+)_id$/
      return $1.classify.constantize.find(value)
    end
  end
  nil
end

Еще раз спасибо за помощь.

...