自定义 Rails *_for 助手?
a custom Rails *_for helper?
我发现自己在显示视图中使用 Rails' form_for 来利用 AR 对象上的翻译和其他方法来创建非交互式表单来显示对象。尽管使用自定义生成器,但必须有更好的方法来执行此操作。是否有针对此类功能的任何东西(gem 或 diy-tutorial-wise)?我的搜索技术很差。
例如,如果我能写这样的东西就好了:
<%= dl_for(@cog) do |dl| %>
<%= dl.dt_dd(:name) %>
<%= dl.dt_dd(:colors) { |colors| colors.to_sentence } %>
<%= dl.dt_dd(:size, { class: @cog.size }) %>
<% end %>
并得到:
<dl>
<dt>My Name Translation</dt>
<dd>Cog 1</dd>
<dt>My Colors Translation</dt>
<dd>Red, Green and Blue</dd>
<dt class="Small">My Size Translation</dt>
<dd class="Small">Small</dd>
</dl>
您可以使用演示者模式的变体来创建您自己的元素构建器:
class DefinitionListBuilder
attr_reader :object
# context is the view context that we can call the rails helper
# method on
def initialize(object, context, **options)
@object = object
@context = context
@options = options
@i18n_key = object.model_name.i18n_key
end
def h
@context
end
def dl(&block)
@context.content_tag :dl, @options do
yield self
end
end
def dt_dd(attribute, **options)
h.capture do
h.concat(h.content_tag :dt, translate_attribute(attribute), options)
h.concat(h.content_tag :dd, object.send(attribute), options)
end
end
private
def translate_attribute(attribute)
key = "activerecord.attributes.#{@i18n_key}.#{attribute}"
h.t(key)
end
end
这个普通的旧 ruby 对象相当于 FormBuilder
。这实际上只是一个对象,它包装了一个模型实例并提供了该实例范围内的帮助程序。然后创建一个帮助器,它创建元素构建器的实例:
module DefinitionListHelper
def dl_for(record, **options, &block)
builder = DefinitionListBuilder.new(record, self, options)
builder.dl(&block)
end
end
这相当于 ActionView::Helpers::FormHelper
提供 form_for
。
为了简洁起见,这被简化了,#dd_dt
不占用块。
示例:
# config/locales/se.yml
se:
activerecord:
attributes:
cog:
name: 'Namn'
size: 'Storlek'
color: 'Färg'
<%= dl_for(Cog.new(name: 'Cogsworth', size: 'biggish', color: 'red')) do |builder| %>
<%= builder.dt_dd :name %>
<%= builder.dt_dd :size %>
<%= builder.dt_dd :color %>
<% end %>
HTML 输出:
<dl>
<dt>Namn</dt><dd>Cogsworth</dd>
<dt>Storlek</dt><dd>biggish</dd>
<dt>Färg</dt><dd>red</dd>
</dl>
我发现自己在显示视图中使用 Rails' form_for 来利用 AR 对象上的翻译和其他方法来创建非交互式表单来显示对象。尽管使用自定义生成器,但必须有更好的方法来执行此操作。是否有针对此类功能的任何东西(gem 或 diy-tutorial-wise)?我的搜索技术很差。
例如,如果我能写这样的东西就好了:
<%= dl_for(@cog) do |dl| %>
<%= dl.dt_dd(:name) %>
<%= dl.dt_dd(:colors) { |colors| colors.to_sentence } %>
<%= dl.dt_dd(:size, { class: @cog.size }) %>
<% end %>
并得到:
<dl>
<dt>My Name Translation</dt>
<dd>Cog 1</dd>
<dt>My Colors Translation</dt>
<dd>Red, Green and Blue</dd>
<dt class="Small">My Size Translation</dt>
<dd class="Small">Small</dd>
</dl>
您可以使用演示者模式的变体来创建您自己的元素构建器:
class DefinitionListBuilder
attr_reader :object
# context is the view context that we can call the rails helper
# method on
def initialize(object, context, **options)
@object = object
@context = context
@options = options
@i18n_key = object.model_name.i18n_key
end
def h
@context
end
def dl(&block)
@context.content_tag :dl, @options do
yield self
end
end
def dt_dd(attribute, **options)
h.capture do
h.concat(h.content_tag :dt, translate_attribute(attribute), options)
h.concat(h.content_tag :dd, object.send(attribute), options)
end
end
private
def translate_attribute(attribute)
key = "activerecord.attributes.#{@i18n_key}.#{attribute}"
h.t(key)
end
end
这个普通的旧 ruby 对象相当于 FormBuilder
。这实际上只是一个对象,它包装了一个模型实例并提供了该实例范围内的帮助程序。然后创建一个帮助器,它创建元素构建器的实例:
module DefinitionListHelper
def dl_for(record, **options, &block)
builder = DefinitionListBuilder.new(record, self, options)
builder.dl(&block)
end
end
这相当于 ActionView::Helpers::FormHelper
提供 form_for
。
为了简洁起见,这被简化了,#dd_dt
不占用块。
示例:
# config/locales/se.yml
se:
activerecord:
attributes:
cog:
name: 'Namn'
size: 'Storlek'
color: 'Färg'
<%= dl_for(Cog.new(name: 'Cogsworth', size: 'biggish', color: 'red')) do |builder| %>
<%= builder.dt_dd :name %>
<%= builder.dt_dd :size %>
<%= builder.dt_dd :color %>
<% end %>
HTML 输出:
<dl>
<dt>Namn</dt><dd>Cogsworth</dd>
<dt>Storlek</dt><dd>biggish</dd>
<dt>Färg</dt><dd>red</dd>
</dl>