Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 193 lines (139 sloc) 6.695 kb
7fa300f @jeremyevans Initial WIP
authored
1 = Forme
2
3 Forme is a HTML forms library for ruby with the following goals:
4
7289221 @jeremyevans Add RDoc documentation
authored
5 1. Have no external dependencies
6 2. Have a simple API
7 3. Support forms both with and without related objects
8 4. Allow compiling down to different types of output
7fa300f @jeremyevans Initial WIP
authored
9
9a3f378 @jeremyevans Update the README
authored
10 = Demo Site
11
12 A demo site is available at http://forme.heroku.com.
13
14 = Source Code
15
16 Source code is available on GitHub at https://github.com/jeremyevans/forme.
17
8375d6b @jeremyevans Massive refactoring, completely new API
authored
18 = Basic Usage
7fa300f @jeremyevans Initial WIP
authored
19
9a3f378 @jeremyevans Update the README
authored
20 Without an object, Forme is a simple form builder:
8375d6b @jeremyevans Massive refactoring, completely new API
authored
21
22 f = Forme::Form.new
23 f.open(:action=>'/foo', :method=>:post) # '<form action="/foo" method="post">
24 f.input(:textarea, :value=>'foo', :name=>'bar') # '<textarea name="bar">foo</textarea>'
25 f.input(:text, :value=>'foo', :name=>'bar') # '<input name="bar" type="text" value="foo"/>'
26 f.close # '</form>'
27
9312369 @jeremyevans Update documentation in lib/forme.rb
authored
28 With an object, <tt>Form#input</tt> calls +forme_input+ on the obj with the form, field, and options, which
29 should return a <tt>Forme::Input</tt> or <tt>Forme::Tag</tt> instance. Also, in <tt>Form#initialize</tt>,
30 +forme_config+ is called on object with the form if the object responds to it, allowing customization of
31 the entire form based on the object.
8375d6b @jeremyevans Massive refactoring, completely new API
authored
32
33 f = Forme::Form.new(obj)
34 f.input(:field) # '<input id="obj_field" name="obj[field]" type="text" value="foo"/>'
35
889b27b @jeremyevans Handle case where object does not respond to forme_input
authored
36 If the object doesn't respond to +forme_input+, it falls back to creating text fields
37 with the name and id set to the field name and the value set by calling the given method
38 on the object.
39
40 f = Forme::Form.new([:foo])
41 f.input(:first) # '<input id="first" name="first" type="text" value="foo"/>'
42
e0177fd @jeremyevans Add section on DSL to the README
authored
43 = DSL
44
9a3f378 @jeremyevans Update the README
authored
45 Forme comes with a DSL:
e0177fd @jeremyevans Add section on DSL to the README
authored
46
47 Forme.form(:action=>'/foo') do |f|
48 f.input(:text, :name=>'bar')
49 f.tag(:fieldset) do
50 f.input(:textarea, :name=>'baz')
51 end
52 end
53 # <form action="/foo">
54 # <input name="bar" type="text"/>
55 # <fieldset>
56 # <textarea name="baz"></textarea>
57 # </fieldset>
58 # </form>
59
9a3f378 @jeremyevans Update the README
authored
60 You can wrap up multiple inputs with the <tt>:inputs</tt> method:
61
62 Forme.form(:action=>'/foo') do |f|
63 f.inputs([[:text, :name=>'bar'], [:textarea, :name=>'baz']])
64 end
65 # <form action="/foo">
66 # <fieldset>
67 # <input name="bar" type="text"/>
68 # <textarea name="baz"></textarea>
69 # </fieldset>
70 # </form>
71
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
72 = Basic Design
73
74 Interally, Forme builds an abstract syntax tree of objects that
75 represent the form. The abstract syntax tree goes through a
76 series of transformations that convert it from high level
77 abstract forms to low level abstract forms and finally to
78 strings. Here are the main classes used by the library:
8375d6b @jeremyevans Massive refactoring, completely new API
authored
79
80 <tt>Forme::Form</tt> :: main object
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
81 <tt>Forme::Input</tt> :: high level abstract tag (a single +Input+ could represent a select box with a bunch of options)
82 <tt>Forme::Tag</tt> :: low level abstract tag representing an html tag (there would be a separate +Tag+ for each option in a select box)
83 <tt>Forme::TagArray</tt> :: array of Tags, Inputs, and Strings
84
85 The group of objects that perform the transformations to
86 the abstract syntax trees are known as transformers.
87 Transformers use a functional style, and all use a +call+-based
88 API, so you can use a +Proc+ for any custom transformer.
89
90 == Transformer Types
91
92 +serializer+ :: tags input/tag, returns string
93 +formatter+ :: takes input, returns tag
94 +error_handler+ :: takes error message and tag, returns version with errors noted
95 +labeler+ :: takes label and tag, returns labeled version
96 +wrapper+ :: takes tag, returns wrapped version
97 +inputs_wrapper+ :: takes form, options, and block, wrapping block in a tag
98
99 The +serializer+ is the base of the library. It turns +Tag+ into strings. If it comes across
100 an +Input+, it calls the +formatter+ on the +Input+ to turn it into a +Tag+, and then serializes
101 that +Tag+. The +formatter+ first converts the +Input+ to a +Tag+, and calls the
102 +error_handler+ and +labeler+ if necessary with the +Tag+ to add the error handling and
103 labeling. Finally, it calls the +wrapper+ to wrap the resulting tag before returning it.
104
105 The +inputs_wrapper+ is called by <tt>Forme::Form#inputs</tt> and serves to wrap a bunch
106 of related inputs.
107
108 == Built-in Transformers
109
110 Forme ships with a bunch of built-in transformers that you can use:
111
112 === +serializer+
113
114 :default :: returns HTML strings
d85d065 @jeremyevans Add html_usa serializer for using American time and date formats
authored
115 :html_usa :: returns HTML strings, formats dates and times in American format without timezones
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
116 :text :: returns plain text strings
117
118 === +formatter+
119
120 :default :: turns Inputs into Tags
121 :disabled :: disables all resulting input tags
122 :readonly :: uses +span+ tags for most values, good for printable versions of forms
123
124 === +error_handler+
125
126 :default :: modifies tag to add an error class and adds a span with the error message
127
128 === +labeler+
129
130 :default :: uses implicit labels, where the tag is a child of the label tag
131 :explicit :: uses explicit labels with the for attribute, where tag is a sibling of the label tag
132
133 === +wrapper+
134
135 :default :: returns tag without wrapping
136 :li :: wraps tag in li tag
47d430c @jeremyevans Add :p, :div, and :span wrappers
authored
137 :p :: wraps tag in p tag
138 :div :: wraps tag in div tag
139 :span :: wraps tag in span tag
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
140 :trtd :: wraps tag in a tr tag with all parts wrapped in individual td tags, useful for lining up
141 inputs with the :explicit labeler without CSS
142
143 === +inputs_wrapper+
144
145 :default :: uses a fieldset to wrap inputs
146 :ol :: uses an ol tag to wrap inputs, useful with :li wrapper
27b82ee @jeremyevans Only set the :labeler and :error_handler options in the formatter if …
authored
147 :div :: uses a div tag to wrap inputs
148 :fieldset_ol :: use both a fieldset and an ol tag to wrap inputs
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
149 :table :: uses a table tag to wrap inputs, useful with :trtd wrapper
a5d0c33 @jeremyevans Update the README, mentioning the RDoc documentation, and Sequel and …
authored
150
151 = Sequel Support
152
153 Forme ships with a Sequel plugin (use <tt>Sequel::Model.plugin :forme</tt> to enable), that makes
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
154 Sequel::Model instances support the +forme_config+ and +forme_input+ methods and return customized inputs.
9a3f378 @jeremyevans Update the README
authored
155
156 It deals with inputs based on database columns, virtual columns, and associations. It also handles
157 nested associations using the +subform+ method:
158
159 Forme.form(Album[1], :action=>'/foo') do |f|
160 f.inputs([:name, :copies_sold, :tags]) do
161 f.subform(:artist, :inputs=>[:name])
162 f.subform(:tracks, :inputs=>[:number, :name])
163 end
164 end
a5d0c33 @jeremyevans Update the README, mentioning the RDoc documentation, and Sequel and …
authored
165
166 = Sinatra ERB Support
167
168 Forme ships with a Sinatra extension that you can get by <tt>require "forme/sinatra"</tt> and using
898eb18 @jeremyevans Add some information on the internal design, transformer purpose, and…
authored
169 <tt>helpers Forme::Sinatra::ERB</tt> in your Sinatra::Base subclass. It allows you to use the
e0177fd @jeremyevans Add section on DSL to the README
authored
170 following API in your Sinatra ERB forms:
a5d0c33 @jeremyevans Update the README, mentioning the RDoc documentation, and Sequel and …
authored
171
172 <% form(@obj, :action=>'/foo') do |f| %>
173 <%= f.input(:field) %>
174 <% f.tag(:fieldset) do %>
175 <%= f.input(:field_two) %>
570c0c6 @jeremyevans Fix some spacing issues in code examples in the README
authored
176 <% end %>
177 <% end %>
178
8375d6b @jeremyevans Massive refactoring, completely new API
authored
179 = Other Similar Projects
180
181 All of these have external dependencies:
182
7289221 @jeremyevans Add RDoc documentation
authored
183 1. Rails built-in helpers
184 2. Formtastic
9a3f378 @jeremyevans Update the README
authored
185 3. simple_form
186 4. padrino-helpers
187
188 Forme's API draws a lot of inspiration from both Formtastic and simple_form.
7fa300f @jeremyevans Initial WIP
authored
189
190 = Author
191
192 Jeremy Evans <code@jeremyevans.net>
Something went wrong with that request. Please try again.