多态通过控制器has_many:Antipattern?

时间:2010-02-17 21:17:01

标签: ruby-on-rails controller dry polymorphic-associations

我很想说是的。

一个人为的例子,使用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并将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决定父资源是俱乐部还是健身房,并采取相应行动。一个非DRY解决方案:

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需要处理Flash消息并重定向两个或更多错误状态。

野外有解决方案。 James Golick的真棒ResourceController有一种处理parent_type,parent_object等的方法。通过向ApplicationController添加一些方法,Revolution On Rails为DRYing up multiple polymorphic controllers提供了一个很好的解决方案。当然,对于像Blog#posts和Article#posts等简单案例,ActionController有#polymorhpic_url。

所有这些让我感到疑惑,是否真的值得对MembersController施加所有压力?在Rails中处理多态性很好,但我的感觉是使用条件(if / unless / case)清楚地表明你不知道你正在处理什么类型。元编程有所帮助,但仅在类型具有相似行为时才有用。两者似乎都指出需要进行设计审查。

我很想听听你对此的看法。在这种情况下干燥更好,或者确切地知道您拥有哪种父类型?我在这里是神经病吗?

1 个答案:

答案 0 :(得分:0)