【问题标题】:How to DRY up 2 controllers/models/views that are basically the exact same如何干燥 2 个基本完全相同的控制器/模型/视图
【发布时间】:2016-07-05 02:00:57
【问题描述】:

Order has_many AItemsBItems。如您所知,这些项目基本相同,但有一个重要的商业原因将它们分开分类。想知道干燥这个的最佳策略是什么。我意识到这有点自以为是……但希望能得到一些明确的观点和论据。

查看代码

目前我正在使用部分。像这样:

class AItemsController
  def new
  end
end

class BItemsController
  def new
  end
end

# view files layout
> views
  > AItems
    > new.html.erb
  > BItems
    > new.html.erb

# routing
get '/AItems/new'
get '/BItems/new'

# code for /views/AItems/new.html.erb
<%= render "layouts/items_new", object: "AItems" %>

# code for /views/BItems/new.html.erb
<%= render "layouts/items_new", object: "BItems" %>

我想知道完全摆脱部分是否更容易,只做这样的参数:

class AItemsController
  def new
  end
end

class BItemsController
  def new
  end
end

# view files layout
> views
  > Items
    > new.html.erb

# routing
get '/items/new/:type'

# code for /views/Items/new.html.erb
# code from partial evaluating the param[:type] instead of a passed object

控制器代码

目前所有内容都是重复的...(我还没有尝试过 DRYing),因为它看起来像这样(非常说明性,关键是要表明没有命名约定,实际上所有内容都基本相同):

class AItemsController
  def new
    @items = AItems.joins(:order).where("orders.status_id IS NULL")
  end

  def do_something
    a_items_params.each do |item_params|
      key_var = item_params[:some_attribute]
      ...
    end
  end
end

class BItemsController
  def new
    @items = BItems.joins(:order).where("orders.status_id IS NULL")
  end

  def do_something
    b_items_params.each do |item_params|
      key_var = item_params[:some_attribute]
      ...
    end
  end
end

我还没有把它弄干,因为我对如何做有点矛盾。下面的例子是说明性的,如果代码不准确,请原谅,但希望你能明白要点。

解决方案 A: 在一种方式中,我可以将动作定义保留在每个控制器中,然后将动作中的代码从共享关注点中提取出来:

class AItemsController
  include SharedCode

  def new
    shared_new
  end

  def do_something
    shared_do_something
  end
end

解决方案 B: 将操作定义抽象为共同关注点:

class AItemsController
  included SharedAction

  shared_action("AItems")
end

解决方案 C: 将所有内容路由到单个控制器并再次使用参数来区分(从视图传递)

class ItemsController
  def new
    item_type = params[:item_type]
  end

  def do_something
    item_type = params[:item_type]
  end
end

型号代码

这个比较简单,在这里我不需要大量的反馈,我只是将共享关注点用于关键方法/回调。


显然,一个人的答案会影响另一个人。例如,如果所有内容都通过单个控制器进行路由,那么我将拥有一个带有参数的视图,而不是部分方法。但由于控制器有多个 DRYing 选项,因此仍有争论的余地。

如果您已经读到这里,我会很高兴地对这个问题的定义过于松散感到愤怒,以换取至少对您会做什么的一些想法。如果你接管了我的代码,你更容易理解什么?

我正在努力学习,而做到这一点的最佳方法是征求多种观点并权衡利弊。

【问题讨论】:

  • 你可能使用继承,但为什么不使用一个项目表,只为 A 项目和 B 项目设置一个标签?
  • 我同意上面的(单表继承)。但还有另一种选择:子类化 ItemsController。例如,使用解决方案 C,然后使用 AItemsController &lt; ItemsController 和例如定义要使用的项目类的私有方法
  • MageeWorld 将它们分开纯粹是商业原因,而不是代码原因。它使我们的会计更快/更容易。 TarynEast 我喜欢这个主意,好建议!

标签: ruby-on-rails ruby controller dry


【解决方案1】:

查看InheritedResources Gemhttps://github.com/josevalim/inherited_resources

继承资源通过制作控制器来加速开发 继承所有宁静的动作,所以你只需要专注于什么 重要的。它使您的控制器在 同一时间。

Responders Gem,替代继承资源:https://github.com/plataformatec/responders

一组响应器模块可让您的 Rails 4.2+ 应用程序枯竭。

【讨论】:

    猜你喜欢
    • 2011-01-17
    • 2013-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2016-02-21
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多