在Rails中有这种自定义Formtastic输入的更好方法吗?

Mat*_*ins 9 forms ruby-on-rails formtastic ruby-on-rails-3

我现在已经使用Formtastic一段时间了,这对于加快表单的实现非常有用.但是,我有一个特殊情况,我需要在我的表单中显示更多的自定义.具体来说,该字段是用于上传图像的文件上载表单,并且在编辑表单上,我想显示已上载的图像的当前版本的缩略图.

期望的表格输出

我有这个工作,但它要求我使用自定义HTML标记,这意味着任何时候Formtastic更改输出格式,我需要更新我匹配的HTML.这就是我现在所拥有的:

<%= form.inputs do %>
    <% if form.object.new_record? -%>
        <%= form.input :image, :required => true, :hint => 'Maximum size of 3MB. JPG, GIF, PNG.' %>
    <% else -%>
        <li class="file input required" id="profile_image_input">
            <label class="label" for="profile_image">Image</label>
            <%= image_tag form.object.image.url(:thumb), :class => 'attachment' %>
            <%= form.file_field :image %>
            <p class="inline-hints">Maximum size of 3MB. JPG, GIF, PNG.</p>
        </li>
    <% end -%>
<% end %>
Run Code Online (Sandbox Code Playgroud)

理想情况下,做一些更像下面的事情会更好,input_html假设是输入,提示等生成的HTML:

<%= form.inputs do %>
    <%= form.input :image, :required => true, :hint => 'Maximum size of 3MB. JPG, GIF, PNG.' do |input_html| %>
        <%= image_tag form.object.image.url(:thumb), :class => 'attachment' unless form.object.new_record? %>
        <%= input_html %>
    <% end %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

这样的事情是否已经存在?还是有另一种类似的选择会让我的生活更轻松吗?

Mat*_*ins 20

好吧,我当然是自己解决了这个问题.我在这里发帖时总会发生.:P

对于任何想要做类似事情的人,我创建了一个从Formtastic的文件输入派生的自定义输入类型.

class AttachmentInput < Formtastic::Inputs::FileInput
  def image_html_options
    {:class => 'attachment'}.merge(options[:image_html] || {})
  end

  def to_html
    input_wrapping do
      label_html <<
      image_html <<
      builder.file_field(method, input_html_options)
    end
  end

protected

  def image_html
    return "".html_safe if builder.object.new_record?

    url = case options[:image]
    when Symbol
      builder.object.send(options[:image])
    when Proc
      options[:image].call(builder.object)
    else
      options[:image].to_s
    end

    builder.template.image_tag(url, image_html_options).html_safe
  end
end
Run Code Online (Sandbox Code Playgroud)

现在我可以通过以下方式创建此类型的输入:

<%= form.input :image, :as => :attachment,
                       :required => true,
                       :hint => 'Maximum size of 3MB. JPG, GIF, PNG.',
                       :image => proc { |o| o.image.url(:thumb) } %>
Run Code Online (Sandbox Code Playgroud)

可选地,:image标签可以接受以下之一:

  • 一个Proc,它传递了表单的对象参数,
  • 一个Symbol,它是对象上的方法名称,
  • 其他任何东西,转换为字符串并假定代表URL.

另外,我可以使用:image_html选项来指定HTML类,id等.

  • 是的,看起来不错.我有很多自定义输入执行这样的操作,或者在禁用的输入中将值显示为String. (4认同)
  • 我是编辑/添加源代码的新手.你把AttachmentInput类放在哪里了?你把一个类放在rails lib文件夹中了吗?你把它放在输入文件夹中了吗?如果在输入文件夹中,您如何管理不同的版本?如果Justin更新代码库会怎么样? (3认同)

Joh*_*rie 7

位于https://github.com/justinfrench/formtastic#modified--custom-inputs的Formtastic文档的底部:

Create a file in app/inputs with a filename ending in _input.rb
Run Code Online (Sandbox Code Playgroud)

对于一个完整的解决方案来说还不够,但是通过灵感来源获得灵感之后能够提出以下对我来说效果很好的方法.

在app/inputs/label_input.rb中:

class LabelInput
  include Formtastic::Inputs::Base

    def to_html
        input_wrapping do
            label_html <<
            "#{@object.send(method)}"
        end
    end
  end
Run Code Online (Sandbox Code Playgroud)

碰巧在页面上的表单中使用ActiveAdmin:

form do |f|
  f.inputs do
    f.input :project
    f.input :date_consumed
    f.input :total_consumed
    f.input :computed_waste, :as => :label
    f.actions
  end
end
Run Code Online (Sandbox Code Playgroud)