半全局 Rails 部分

Semi-global Rails partial

有没有更好的方法来实现我的目标?

我遇到的问题:大多数电子邮件表单略有不同,这导致我不得不向 locals 哈希添加额外的选项,我觉得全局部分变得臃肿。是否有某种方式以这种方式使用全局部分,使得部分不会变得超级臃肿?

我曾考虑过将每个表格完全分开,但这不利于维护和干燥。我想过传递要在全局局部中呈现的局部名称,但其中一些形式需要相同的选项并且从不同的控制器呈现,我不想放一堆不是的局部/views/shared/ 文件夹中的全局文件。现在,我只是坚持使用臃肿的全局部分。

如有任何帮助,我们将不胜感激!

一种方法是为每个表单单独分配一个部分。把表格共有的所有项目都放在一个部分中。然后,您可以在个人表单部分中引用 "common items" 部分。根据您的表单结构,您可能有多个 "common items" 部分,但这没关系。目标是保持代码井井有条和干燥。

这是我的做法。这听起来很奇怪,但请耐心等待。

所以,我的申请基本上有两种形式。对于通过 javascript 提交的表单,它看起来像这样:

#views/shared/_remote_form.html.haml

= form_tag @presenter.form_path, 
    remote: true, 
    id: @presenter.form_id, 
    class: @presenter.form_classes, 
    data: @presenter.form_data, 
    method: @presenter.form_method do 
    .well
      = @presenter.form_inner
      .form-controls-container
        .form-controls-wrapper
          = @presenter.form_controls

如您所见,我使用演示器。演示者在相关控制器中实例化为控制器变量,因此演示者可用于部分。类似于:

class FooController < ApplicationController

  def new
    @presenter = NewFooFormPresenter.new(self)
    render partial: 'shared/remote_form'
  end

  ...

end

您可以看到我传入了控制器,以便演示者能够呈现表单的各个部分。

所有 FormPresenters 继承自 FormPresenterBase,它为表单中调用的每个方法添加了存根方法。像这样:

class FormPresenterBase

  def initialize(controller)
    @controller = controller
  end

  def form_path
    root_path
  end

  def form_id
    'bogus-form-id'
  end

  def form_classes
    'something-bogus'
  end

  def form_inner; end

  def form_controls; end

  ...

end

让我 bootstrap 表单不会一直抛出一堆错误。自然地,存根形式不会真正起作用,但这没关系,因为每个 FormPresenter 都会用实际值覆盖存根方法。所以,像这样:

class NewFooFormPresenter < FormPresenterBase

  def form_path
    new_for_form_path
  end

  def form_id
   'new-foo-form'
  end 

  def form_classes
    'something-not-bogus'
  end

  # The form fields could be unique to this form. Or, I might have a set of common 
  # fields that I use across multiple forms. I just decide which partial has the 
  # correct set of fields and render it here.
  def form_inner
    render partial: 'new_inner_fields'
  end

  # The controls are also rendered from partials. Here, I want to have an okay 
  # button and a cancel button. So, I just call the correct partial that 
  # renders those. I call html_safe on the resultant string so that it renders 
  # correctly.
  def form_controls
    [:okay, :cancel].each_with_object("") do |control_sym, to_return|
      render partial: "shared/form_widgets/#{control_sym.to_s}_button"
    end.html_safe

  end

  ...

end

当然,我的 FormPresenters 可能会很棘手。如果有共享通用方法的系列,我可以使用进一步的继承或模块包含来保持一切干燥。

因此,一旦我将所有基本表单小部件(字段组合、控件等)配置为部分组件,我就可以在我的演示器中随意混合和匹配。并且(至少对于表格而言),我基本上永远不必在我的余生中再写另一部分。每当我需要一个新的变体时,我只需启动一个新的 FormPresenter 并对其进行自定义以提供我想要的形式。

实际上,它的意义远不止于此,但希望这能让您了解另一种剥猫皮的方法。