半全局 Rails 部分
Semi-global Rails partial
有没有更好的方法来实现我的目标?
- 我在
/views/shared/
文件夹中有一个部分,其中包含用于发送电子邮件的表单中的所有字段。
- 一个带有默认选项的辅助方法来呈现所述部分(
render partial: 'shared/email_fields' locals: locals
其中 locals
是默认变量的散列)。
- 用于发送电子邮件的每个表单的辅助方法调用上述辅助方法并传入
FormBuilder
对象或包含 name
html 属性开头的字符串.
我遇到的问题:大多数电子邮件表单略有不同,这导致我不得不向 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 并对其进行自定义以提供我想要的形式。
实际上,它的意义远不止于此,但希望这能让您了解另一种剥猫皮的方法。
有没有更好的方法来实现我的目标?
- 我在
/views/shared/
文件夹中有一个部分,其中包含用于发送电子邮件的表单中的所有字段。 - 一个带有默认选项的辅助方法来呈现所述部分(
render partial: 'shared/email_fields' locals: locals
其中locals
是默认变量的散列)。 - 用于发送电子邮件的每个表单的辅助方法调用上述辅助方法并传入
FormBuilder
对象或包含name
html 属性开头的字符串.
我遇到的问题:大多数电子邮件表单略有不同,这导致我不得不向 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 并对其进行自定义以提供我想要的形式。
实际上,它的意义远不止于此,但希望这能让您了解另一种剥猫皮的方法。