如何在Rails中编写类似form_for的方法

时间:2012-08-21 22:20:59

标签: ruby-on-rails view-helpers

对于我的应用程序,将有趣的html生成结构化为一组看起来像form_for的调用将会很有帮助。这是一个例子,来自_reports.html.erb:

<%= reports_list do |rep| %>
  <%= rep.group_header("Reports by Question") do %>
    <%= rep.title("Response Distribution") %>
    <%= rep.description do %>
      lorem lorem lorem
      lorem lorem lorem
    <%= end %>
    <%= rep.title("Response Distribution") %>
    <%= rep.description do %>
      lorem lorem lorem
      lorem lorem lorem
    <%= end %>
  <%= end %>
<%= end %>

这些调用中的每一个都会生成一些带有css和标签的html等等,这会完全模糊这个报表列表的结构。

我尝试过阅读form_for,但是我无法将其解读为我需要的模式。任何人都有这方面的想法,和/或一个提炼问题的链接?谢谢!

1 个答案:

答案 0 :(得分:1)

您可以编写一个小型自定义DSL(您可以改进并使代码更好):

可以大大改进的小型DSL:

class ReportHtmlMaker
  def initialize(output)
    @output = output
  end

  def content(text)
    @output << text.to_s
    nil
  end

  def translate_semantic_tag(tagname,attributes={})
    newline = "" # "\r\n" uncomment to add newlines
    case tagname.to_sym
    when :group_header
      tagname = "h1"
      attributes[:id] =  "report_group_header"
    when :title
      tagname = "h2"
      attributes[:class] =  "report_title"
    when :description
      tagname = "p"
    end

    @output << "<#{tagname}"
    attributes.each { |attr,value| @output << " #{attr}='#{value}'" }
    if block_given?
      @output << ">" << newline
      content = yield
      if content
        @output << content.to_s << newline
      end
      @output << "</#{tagname}>" << newline
    else
      @output << "/>" << newline
    end
    nil
  end
  alias method_missing translate_semantic_tag

  def self.generate(output, &block)
    ReportHtmlMaker.new(output).instance_eval(&block)
  end
end

用法:

output = String.new
ReportHtmlMaker.generate(output) do  #or, use STDOUT to output to console
  group_header do
    title do
      "Response Distribution"
    end
    description do
      "lorem ipsum dolor mit"
    end
  end
end

输出:

puts output # =>

<div id='report_group_header'>
  <h2 class='report_title'>Response Distribution</h2>
  <p class='report_description'>lorem ipsum dolor mit</p>
</h1>

那是你在找什么?