Former

<img src=“https://secure.travis-ci.org/opbandit/former.png?branch=master” alt=“Build Status” /> <img src=“https://gemnasium.com/opbandit/former.png” alt=“Dependency Status” />

Former turns an html string into a set of editable fields. For instance, if you want to give users the ability to edit certain parts of pregenerated HTML (like the href’s of a’s), this gem makes it easy to create the form and handle user input.

Installation

Add this line to your application’s Gemfile:

gem 'former'

And then execute:

$ bundle

Or install it yourself as:

$ gem install former

Usage

First, create a new parser that extends Builder class.

class Parser < Former::Builder
  attr "a.important", :href
  attr "img", :src
  text "p", "a.important"
end

In this example, we want to be able to edit the location of all links that have a class of “important”, the location of all images, and the text in any paragraphs or important links. Note that the text method takes any number of parameters which each will be evaluated for text children (or, if you give no parameters, all text nodes will be included).

To produce the input fields from some example input HTML, first create an instance of your parser.

parsed = Parser.new "<p>some text<a class='important' href='http://alink.com'>some link text<img src='/an/image/path' /></a>last text</p>"

Then, we can get information about the editable fields:

parsed.each { |elem| puts "#{elem.node.name} is #{elem.value}" }

And, even create an html form from this:

parsed.each { |elem| puts "<input name='former_0' type='text' value='#{elem.value}' />" }

You can also convert the original html to json:

puts parsed.to_json

You can then set fields individually or as a group (with, say, the params from a POST/GET):

parsed[0] = "A New Description"
parsed[1] = "http://anewlink.com"
# or...
parsed.set_values :former_0 => "A New Description", :former_1 => "http://anewlink.com"

When the new values have been set, you can spit out the new HTML version:

puts parsed.to_html

Will produce the original html with the new field values:

<p>A New Description<a class='important' href='http://anewlink.com'>some link...

If you want finer grained control over what’s considered an editable element, you can pass a block in as well to the attr method. For instance, if you want only text fields that are not empty, you could use:

class Parser < Former::Builder
  text("p", "a.important") { |elem| not elem.text.strip.empty? }
end

p = Parser.new("<p>\n</p><p>some text</p>").length # this is only 1
p[0] = 'other text'
p.to_html # => '<p>\n</p><p>other text</p>'