Полиморфный has_many через контроллеры: Antipattern?

Я испытываю желание сказать да.

Придуманный пример с использованием has_many:through и polymorphs:

class Person < ActiveRecord::Base
  has_many :clubs, :through => :memberships
  has_many :gyms, :through => :memberships
end

class Membership < ActiveRecord::Base
  belongs_to :member, :polymorphic => true
end

class Club < ActiveRecord::Base
  has_many :people, :through => :memberships
  has_many :memberships, :as => :member
end

etc.

Оставляя в стороне вопрос о том, является ли тренажерный зал клубом, или какие-либо другие недостатки дизайна.

Чтобы добавить пользователя в клуб, заманчиво быть RESTful и POST person_id и club_id в MembersController, например:

form_for club_members_path(@club, :person_id => person.id) ...

В этом сценарии, когда мы решили сделать:

form_for gym_members_path(@gym, :person_id => person.id) ...

Нам нужно будет заставить MembersController решить, является ли родительский ресурс клубом или спортзалом, и действовать соответствующим образом. Одно неСУХОЕ решение:

class MembersController < ApplicationController
  before_filter :find_parent
  ...
  private
  def find_parent
    @parent = Gym.find(params[:gym_id]) if params[:gym_id]
    @parent = Club.find(params[:club_id]) if params[:club_id]
  end
end

Шокирующе ужасно, если вы делаете это более одного раза.

Кроме того, это основано на концепции, что вступление в клуб и в спортзал примерно одинаковы. Или, по крайней мере, Gym#add_member и Club#add_member будут вести себя более или менее параллельно. Но мы должны предположить, что у спортивных залов и клубов могут быть разные причины отклонения заявки на членство. MembersController должен обрабатывать флэш-сообщения и перенаправления для двух или более состояний ошибки.

Есть решения в дикой природе. У потрясающего ResourceController от Джеймса Голика есть способ работы с parent_type, parent_object и т. Д. Revolution On Rails предлагает отличное решение для СУШКИ нескольких полиморфных контроллеров путем добавления некоторых методов в ApplicationController. И, конечно же, ActionController имеет #polymorhpic_url для более простых случаев, таких как сообщения в блоге # статьи и сообщения в статье # и т. Д.

Все это заставляет меня задуматься: а стоит ли вообще оказывать такое давление на MembersController? Полиморфизм довольно хорошо обрабатывается в Rails, но я чувствую, что использование условных выражений (если / если / не случай) является четким признаком того, что вы не знаете, с каким типом вы имеете дело. Метапрограммирование помогает, но только когда типы имеют похожее поведение. Оба, кажется, указывают на необходимость пересмотра дизайна.

Я хотел бы услышать ваши мысли по этому поводу. Лучше быть СУХИМ в этом сценарии или точно знать, какой у вас родительский тип? Я здесь невротик?

1 ответ

Я думаю, что эта ссылка дает ответ на ваш вопрос http://revolutiononrails.blogspot.com/2007/05/drying-up-polymorphic-controllers.html

Другие вопросы по тегам