【问题标题】:a custom Rails *_for helper? [closed]自定义 Rails *_for 助手? [关闭]
【发布时间】:2020-05-03 12:54:57
【问题描述】:

我发现自己在显示视图中使用 Rails 的 form_for 来利用 AR 对象上的翻译和其他方法来创建非交互式表单来显示对象。尽管使用自定义构建器,但必须有更好的方法来做到这一点。这种功能有什么(宝石或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>

【问题讨论】:

  • 您想要的是自定义 DSL(特定于域的语言)。只要搜索“ruby custom dsl”,你会发现很多资源,我不能特别推荐。

标签: ruby-on-rails actionview


【解决方案1】:

您可以使用演示者模式的变体来创建自己的元素构建器:

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

这相当于提供form_forActionView::Helpers::FormHelper

为了简洁起见,这被简化了,#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>

【讨论】:

  • 谢谢 max,这已经足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 2015-08-11
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2018-08-10
  • 2016-01-29
相关资源
最近更新 更多