sinatra-formhelpers 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/LICENSE +21 -0
- data/README.md +91 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/lib/sinatra/form_helpers.rb +217 -0
- data/sinatra-formhelpers.gemspec +47 -0
- data/spec/form_helpers_spec.rb +295 -0
- data/spec/spec_helper.rb +55 -0
- metadata +73 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
sinatra-formhelpers - Suite of form helpers for sinatra
|
2
|
+
Copyright 2009 Tom Wilson
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
Sinatra::FormHelpers - Lightweight form helpers for Sinatra
|
2
|
+
===========================================================
|
3
|
+
|
4
|
+
This plugin adds lightweight (3-5 lines each) form helpers to Sinatra that aid with
|
5
|
+
common form and HTML tags.
|
6
|
+
|
7
|
+
link "google", "http://www.google.com" # <a href="http://www.google.com">google</a>
|
8
|
+
label :person, :first_name # <label for="person_first_name">First Name</label>
|
9
|
+
input :person, :first_name # <input name="person[first_name]" id="person_first_name" type="text" />
|
10
|
+
|
11
|
+
There are also helpers for: form, textarea, submit, image, radio, checkbox, and select
|
12
|
+
|
13
|
+
Why Bother?
|
14
|
+
-----------
|
15
|
+
After all, you can just write Haml or write your own helpers or hand-code raw HTML or whatever. Well, here's some considerations:
|
16
|
+
|
17
|
+
1. Helpers maintain correct state across form submissions (eg, on errors, form stays filled in)
|
18
|
+
2. Generate automatic labels, valid CSS ID's, and <code>nested[names]</code> to make ORMs happy
|
19
|
+
3. No Rails ultra-magic(tm) here. Just fast, simple code.
|
20
|
+
|
21
|
+
Usage
|
22
|
+
-----
|
23
|
+
With Bundler/Isolate:
|
24
|
+
|
25
|
+
gem 'sinatra-formhelpers', '~>0.6.0'
|
26
|
+
|
27
|
+
Then, include it in a Sinatra application:
|
28
|
+
|
29
|
+
require 'sinatra/form_helpers'
|
30
|
+
|
31
|
+
If you're subclassing <code>Sinatra::Base</code>, you also need to call <code>helpers</code> manually:
|
32
|
+
|
33
|
+
class MyApp < Sinatra::Base
|
34
|
+
helpers Sinatra::FormHelpers
|
35
|
+
# ...
|
36
|
+
end
|
37
|
+
|
38
|
+
Views
|
39
|
+
-----
|
40
|
+
In your views, use these helpers to dynamically create form HTML elements. Here's an example in ERB:
|
41
|
+
|
42
|
+
<p>
|
43
|
+
Fill out the below form to sign up.
|
44
|
+
For more information, visit our <%= link 'FAQ', '/faq' %>
|
45
|
+
</p>
|
46
|
+
|
47
|
+
<%= form('/users', :post) %>
|
48
|
+
|
49
|
+
<%= input(:user, :first_name) %>
|
50
|
+
<%= input(:user, :last_name) %>
|
51
|
+
|
52
|
+
<%= input(:user, :email, :size => 40) %>
|
53
|
+
|
54
|
+
<%= password(:user, :password) %>
|
55
|
+
<%= password(:user, :confirm_password) %>
|
56
|
+
|
57
|
+
<%= radio(:user, :gender, ['M', 'F']) %>
|
58
|
+
|
59
|
+
<%= submit %>
|
60
|
+
|
61
|
+
Unlike the super-magic Rails <code>form\_for</code> method, the <code>form()</code> helper just takes a URL and method. (Note that <code>form()</code> will accept <code>:create</code>, <code>:update</code>, and <code>:delete</code> and include the special <code>\_method</code> hidden param for you.)
|
62
|
+
|
63
|
+
To reduce repetition, use <code>fieldset()</code> to prefix fields with a namespace:
|
64
|
+
|
65
|
+
<%= form('/users', :create) %>
|
66
|
+
|
67
|
+
<% fieldset(:user) do |f| %>
|
68
|
+
<%= f.input(:first_name) %>
|
69
|
+
<%= f.input(:last_name) %>
|
70
|
+
|
71
|
+
<%= f.input(:email, :size => 40) %>
|
72
|
+
|
73
|
+
<%= f.password(:password) %>
|
74
|
+
<%= f.password(:confirm_password) %>
|
75
|
+
|
76
|
+
<%= f.radio(:gender, ['M', 'F']) %>
|
77
|
+
<% end %>
|
78
|
+
|
79
|
+
<%= submit 'Create account' %>
|
80
|
+
<%= submit 'Cancel', :onclick => 'window.location=http://mydomain.com;return false' %>
|
81
|
+
|
82
|
+
This will create fields named <code>user[first\_name]</code>, <code>user[last\_name]<code>, and so forth.
|
83
|
+
|
84
|
+
Known Bugs
|
85
|
+
----------
|
86
|
+
* Currently <code>fieldset</code> does not return a <fieldset> tag properly (working on it)
|
87
|
+
|
88
|
+
|
89
|
+
Author
|
90
|
+
------
|
91
|
+
Copyright (c) 2011 [Nate Wiger](http://nateware.com). Based on initial efforts (c) 2009 twilson63.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rake'
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gem|
|
11
|
+
gem.name = "sinatra-formhelpers"
|
12
|
+
gem.summary = %Q{Form helpers for Sinatra}
|
13
|
+
gem.description = %Q{Simple, lightweight form helpers for Sinatra. Based on initial efforts by twilson63.}
|
14
|
+
gem.email = "nate@wiger.org"
|
15
|
+
gem.homepage = "http://github.com/nateware/sinatra-formhelpers"
|
16
|
+
gem.authors = ["Nate Wiger"]
|
17
|
+
gem.add_development_dependency "bacon", ">= 0"
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::RubygemsDotOrgTasks.new
|
21
|
+
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# SPECS ===============================================================
|
28
|
+
|
29
|
+
task :test => :spec
|
30
|
+
desc "run all the specs"
|
31
|
+
task :spec do
|
32
|
+
sh "bacon spec/*_spec.rb"
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'spec'
|
39
|
+
test.pattern = 'spec/**/*_spec.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
task :rcov do
|
44
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
task :default => :test
|
50
|
+
|
51
|
+
require 'rake/rdoctask'
|
52
|
+
Rake::RDocTask.new do |rdoc|
|
53
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
54
|
+
|
55
|
+
rdoc.rdoc_dir = 'rdoc'
|
56
|
+
rdoc.title = "Sinatra::FormHelpers #{version}"
|
57
|
+
rdoc.rdoc_files.include('README*')
|
58
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.0
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module Sinatra
|
2
|
+
module FormHelpers
|
3
|
+
# FormHelpers are a suite of helper methods
|
4
|
+
# built to make building forms in Sinatra
|
5
|
+
# a breeze.
|
6
|
+
#
|
7
|
+
# link "jackhq", "http://www.jackhq.com"
|
8
|
+
#
|
9
|
+
# label :person, :first_name
|
10
|
+
# input :person, :first_name
|
11
|
+
# textarea :person, :notes
|
12
|
+
#
|
13
|
+
# etc.
|
14
|
+
def form(action, method=:get, options={}, &block)
|
15
|
+
method_input = ''
|
16
|
+
if method.is_a? Symbol
|
17
|
+
case method.to_s.downcase
|
18
|
+
when 'delete', 'update'
|
19
|
+
method_input = %Q(<input type="hidden" name="_method" value="#{method}" />)
|
20
|
+
method = :post
|
21
|
+
when 'create'
|
22
|
+
method = :post
|
23
|
+
end
|
24
|
+
end
|
25
|
+
action = "/#{action}" if action.is_a? Symbol
|
26
|
+
|
27
|
+
out = tag(:form, nil, {:action => action, :method => method.to_s.upcase}.merge(options)) + method_input
|
28
|
+
out << fieldset(action, &block) + '</form>' if block_given?
|
29
|
+
out
|
30
|
+
end
|
31
|
+
|
32
|
+
def fieldset(obj, legend=nil, &block)
|
33
|
+
raise ArgumentError, "Missing block to fieldset()" unless block_given?
|
34
|
+
out = yield Fieldset.new(self, obj)
|
35
|
+
'<fieldset>' + (legend.nil? ? '' : "<legend>#{fast_escape_html(legend)}</legend>") + out + '</fieldset>'
|
36
|
+
end
|
37
|
+
|
38
|
+
# Link to a URL
|
39
|
+
def link(content, href=content, options={})
|
40
|
+
tag :a, content, options.merge(:href => href)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Link to an image
|
44
|
+
def image(src, options={})
|
45
|
+
single_tag :img, options.merge(:src => src)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Form field label
|
49
|
+
def label(obj, field, display = "", options={})
|
50
|
+
tag :label, (display.nil? || display == '') ? titleize(field.to_s) : display, options.merge(:for => "#{obj}_#{field}")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Form text input. Specify the value as :value => 'foo'
|
54
|
+
def input(obj, field=nil, options={})
|
55
|
+
value = param_or_default(obj, field, options[:value])
|
56
|
+
single_tag :input, options.merge(
|
57
|
+
:type => "text", :id => css_id(obj, field),
|
58
|
+
:name => field.nil? ? obj : "#{obj}[#{field}]",
|
59
|
+
:value => value
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Form password input. Specify the value as :value => 'foo'
|
64
|
+
def password(obj, field=nil, options={})
|
65
|
+
value = param_or_default(obj, field, options[:value])
|
66
|
+
single_tag :input, options.merge(
|
67
|
+
:type => "password", :id => css_id(obj, field),
|
68
|
+
:name => field.nil? ? obj : "#{obj}[#{field}]",
|
69
|
+
:value => value
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Form textarea box.
|
74
|
+
def textarea(obj, field=nil, content='', options={})
|
75
|
+
content = param_or_default(obj, field, content)
|
76
|
+
tag :textarea, content, options.merge(
|
77
|
+
:id => css_id(obj, field),
|
78
|
+
:name => field.nil? ? obj : "#{obj}[#{field}]"
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Form submit tag.
|
83
|
+
def submit(value='Submit', options={})
|
84
|
+
single_tag :input, {:name => "submit", :type => "submit",
|
85
|
+
:value => value, :id => css_id('button', value)}.merge(options)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Form reset tag. Does anyone use these anymore?
|
89
|
+
def reset(value='Reset', options={})
|
90
|
+
single_tag :input, {:name => "reset", :type => "reset",
|
91
|
+
:value => value, :id => css_id('button', value)}.merge(options)
|
92
|
+
end
|
93
|
+
|
94
|
+
# General purpose button, usually these need JavaScript hooks.
|
95
|
+
def button(value, options={})
|
96
|
+
single_tag :input, {:name => "button", :type => "button",
|
97
|
+
:value => value, :id => css_id('button', value)}.merge(options)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Form checkbox. Specify an array of values to get a checkbox group.
|
101
|
+
def checkbox(obj, field, values, options={})
|
102
|
+
join = options.delete(:join) || ' '
|
103
|
+
labs = options.delete(:label)
|
104
|
+
vals = param_or_default(obj, field, [])
|
105
|
+
ary = values.is_a?(Array) && values.length > 1 ? '[]' : ''
|
106
|
+
Array(values).collect do |val|
|
107
|
+
id, text = id_and_text_from_value(val)
|
108
|
+
single_tag(:input, options.merge(:type => "checkbox", :id => css_id(obj, field, id),
|
109
|
+
:name => "#{obj}[#{field}]#{ary}", :value => id,
|
110
|
+
:checked => vals.include?(val) ? 'checked' : nil)) +
|
111
|
+
(labs.nil? || labs == true ? label(obj, "#{field}_#{id.to_s.downcase}", text) : '')
|
112
|
+
end.join(join)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Form radio input. Specify an array of values to get a radio group.
|
116
|
+
def radio(obj, field, values, options={})
|
117
|
+
#content = @params[obj] && @params[obj][field.to_s] == value ? "true" : ""
|
118
|
+
# , :checked => content
|
119
|
+
join = options.delete(:join) || ' '
|
120
|
+
labs = options.delete(:label)
|
121
|
+
vals = param_or_default(obj, field, [])
|
122
|
+
Array(values).collect do |val|
|
123
|
+
id, text = id_and_text_from_value(val)
|
124
|
+
single_tag(:input, options.merge(:type => "radio", :id => css_id(obj, field, id),
|
125
|
+
:name => "#{obj}[#{field}]", :value => id,
|
126
|
+
:checked => vals.include?(val) ? 'checked' : nil)) +
|
127
|
+
(labs.nil? || labs == true ? label(obj, "#{field}_#{id.to_s.downcase}", text) : '')
|
128
|
+
end.join(join)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Form select dropdown. Currently only single-select (not multi-select) is supported.
|
132
|
+
def select(obj, field, values, options={})
|
133
|
+
content = ""
|
134
|
+
Array(values).each do |val|
|
135
|
+
id, text = id_and_text_from_value(val)
|
136
|
+
if val.is_a? Array
|
137
|
+
content << tag(:option, text, :value => id)
|
138
|
+
else
|
139
|
+
content << tag(:option, text, :value => id)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
tag :select, content, options.merge(:id => css_id(obj, field), :name => "#{obj}[#{field}]")
|
143
|
+
end
|
144
|
+
|
145
|
+
# Form hidden input. Specify value as :value => 'foo'
|
146
|
+
def hidden(obj, field="", options={})
|
147
|
+
content = param_or_default(obj, field, options[:value])
|
148
|
+
single_tag :input, options.merge(:type => "hidden", :id => css_id(obj, field), :name => "#{obj}[#{field}]")
|
149
|
+
end
|
150
|
+
|
151
|
+
# Standard open and close tags
|
152
|
+
# EX : tag :h1, "shizam", :title => "shizam"
|
153
|
+
# => <h1 title="shizam">shizam</h1>
|
154
|
+
def tag(name, content, options={})
|
155
|
+
"<#{name.to_s}" +
|
156
|
+
(options.length > 0 ? " #{hash_to_html_attrs(options)}" : '') +
|
157
|
+
(content.nil? ? '>' : ">#{content}</#{name}>")
|
158
|
+
end
|
159
|
+
|
160
|
+
# Standard single closing tags
|
161
|
+
# single_tag :img, :src => "images/google.jpg"
|
162
|
+
# => <img src="images/google.jpg" />
|
163
|
+
def single_tag(name, options={})
|
164
|
+
"<#{name.to_s} #{hash_to_html_attrs(options)} />"
|
165
|
+
end
|
166
|
+
|
167
|
+
def fast_escape_html(text)
|
168
|
+
text.to_s.gsub(/\&/,'&').gsub(/\"/,'"').gsub(/>/,'>').gsub(/</,'<')
|
169
|
+
end
|
170
|
+
|
171
|
+
def titleize(text)
|
172
|
+
text.to_s.gsub(/_+/, ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
|
173
|
+
end
|
174
|
+
|
175
|
+
def param_or_default(obj, field, default)
|
176
|
+
if field
|
177
|
+
params[obj] ? params[obj][field.to_s] || default : default
|
178
|
+
else
|
179
|
+
params[obj] || default
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def hash_to_html_attrs(options={})
|
184
|
+
html_attrs = ""
|
185
|
+
options.keys.sort.each do |key|
|
186
|
+
next if options[key].nil? # do not include empty attributes
|
187
|
+
html_attrs << %Q(#{key}="#{fast_escape_html(options[key])}" )
|
188
|
+
end
|
189
|
+
html_attrs.chop
|
190
|
+
end
|
191
|
+
|
192
|
+
def id_and_text_from_value(val)
|
193
|
+
if val.is_a? Array
|
194
|
+
[val.first, val.last]
|
195
|
+
else
|
196
|
+
[val, val]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def css_id(*things)
|
201
|
+
things.compact.map{|t| t.to_s}.join('_').downcase.gsub(/\W/,'_')
|
202
|
+
end
|
203
|
+
|
204
|
+
class Fieldset
|
205
|
+
def initialize(parent, name)
|
206
|
+
@parent = parent
|
207
|
+
@name = name.to_s.gsub(/\W+/,'')
|
208
|
+
end
|
209
|
+
|
210
|
+
def method_missing(meth, *args)
|
211
|
+
@parent.send(meth, @name, *args)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
helpers FormHelpers
|
217
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sinatra-formhelpers}
|
8
|
+
s.version = "0.4.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Nate Wiger}]
|
12
|
+
s.date = %q{2011-08-26}
|
13
|
+
s.description = %q{Simple, lightweight form helpers for Sinatra. Based on initial efforts by twilson63.}
|
14
|
+
s.email = %q{nate@wiger.org}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/sinatra/form_helpers.rb",
|
26
|
+
"sinatra-formhelpers.gemspec",
|
27
|
+
"spec/form_helpers_spec.rb",
|
28
|
+
"spec/spec_helper.rb"
|
29
|
+
]
|
30
|
+
s.homepage = %q{http://github.com/nateware/sinatra-formhelpers}
|
31
|
+
s.require_paths = [%q{lib}]
|
32
|
+
s.rubygems_version = %q{1.8.6}
|
33
|
+
s.summary = %q{Form helpers for Sinatra}
|
34
|
+
|
35
|
+
if s.respond_to? :specification_version then
|
36
|
+
s.specification_version = 3
|
37
|
+
|
38
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
39
|
+
s.add_development_dependency(%q<bacon>, [">= 0"])
|
40
|
+
else
|
41
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
42
|
+
end
|
43
|
+
else
|
44
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require File.expand_path 'spec_helper', File.dirname(__FILE__)
|
2
|
+
|
3
|
+
# class Application < Sinatra::Base
|
4
|
+
# register Sinatra::FormHelpers
|
5
|
+
#
|
6
|
+
# set :raise_errors, false
|
7
|
+
# set :show_exceptions, false
|
8
|
+
#
|
9
|
+
# get '/link' do
|
10
|
+
#
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# class Bacon::Context
|
15
|
+
# include Rack::Test::Methods
|
16
|
+
# def app
|
17
|
+
# Application # our application
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
describe "Sinatra::FormHelpers methods" do
|
22
|
+
it "renders an anchor tag" do
|
23
|
+
fh.form(:person, :create).should == '<form action="/person" method="POST">'
|
24
|
+
end
|
25
|
+
it 'renders a form tag' do
|
26
|
+
fh.form(:person, :update, :action => "/people/14").should ==
|
27
|
+
'<form action="/people/14" method="POST"><input type="hidden" name="_method" value="update" />'
|
28
|
+
end
|
29
|
+
it 'renders a form tag (2)' do
|
30
|
+
fh.form("/people/7", :delete).should ==
|
31
|
+
'<form action="/people/7" method="POST"><input type="hidden" name="_method" value="delete" />'
|
32
|
+
end
|
33
|
+
it 'renders a form tag (3)' do
|
34
|
+
fh.form("/people", :create).should ==
|
35
|
+
'<form action="/people" method="POST">'
|
36
|
+
end
|
37
|
+
it 'renders a nested form tag' do
|
38
|
+
fh.form(:person, :create) do |f|
|
39
|
+
# f.input(:first_name)
|
40
|
+
f.input(:last_name)
|
41
|
+
end.should == '<form action="/person" method="POST"><fieldset>' +
|
42
|
+
# '<input id="person_first_name" name="person[first_name]" type="text" />' +
|
43
|
+
'<input id="person_last_name" name="person[last_name]" type="text" />' +
|
44
|
+
'</fieldset></form>'
|
45
|
+
end
|
46
|
+
it 'nests form elements arbitrarily' do
|
47
|
+
fh.fieldset(:person) do |n|
|
48
|
+
# n.radio(:partners, 1..6)
|
49
|
+
n.textarea(:comments, "yo yo yo!")
|
50
|
+
end.should == '<fieldset>' +
|
51
|
+
# '<input id="person_partners_1" name="person[partners]" type="radio" value="1" /> ' +
|
52
|
+
# '<input id="person_partners_2" name="person[partners]" type="radio" value="2" /> ' +
|
53
|
+
# '<input id="person_partners_3" name="person[partners]" type="radio" value="3" /> ' +
|
54
|
+
# '<input id="person_partners_4" name="person[partners]" type="radio" value="4" /> ' +
|
55
|
+
# '<input id="person_partners_5" name="person[partners]" type="radio" value="5" /> ' +
|
56
|
+
# '<input id="person_partners_6" name="person[partners]" type="radio" value="6" />' +
|
57
|
+
'<textarea id="person_comments" name="person[comments]">yo yo yo!</textarea></fieldset>'
|
58
|
+
end
|
59
|
+
it 'renders a link tag' do
|
60
|
+
fh.link('http://google.com').should == '<a href="http://google.com">http://google.com</a>'
|
61
|
+
end
|
62
|
+
it 'renders a form label tag' do
|
63
|
+
fh.label(:person, :first_name).should == '<label for="person_first_name">First Name</label>'
|
64
|
+
end
|
65
|
+
it 'renders a form checkbox tag' do
|
66
|
+
fh.checkbox(:person, :gender, %w[M F], :join => '<br />').should ==
|
67
|
+
'<input id="person_gender_m" name="person[gender][]" type="checkbox" value="M" /><label for="person_gender_m">M</label><br />' +
|
68
|
+
'<input id="person_gender_f" name="person[gender][]" type="checkbox" value="F" /><label for="person_gender_f">F</label>'
|
69
|
+
end
|
70
|
+
it 'renders a minimal text tag' do
|
71
|
+
fh.input(:q).should == %q(<input id="q" name="q" type="text" />)
|
72
|
+
end
|
73
|
+
it 'renders a minimal textarea tag' do
|
74
|
+
fh.textarea(:r).should == %q(<textarea id="r" name="r"></textarea>)
|
75
|
+
end
|
76
|
+
it 'renders a submit tag' do
|
77
|
+
fh.submit.should == %q(<input id="button_submit" name="submit" type="submit" value="Submit" />)
|
78
|
+
fh.submit("Send!").should == %q(<input id="button_send_" name="submit" type="submit" value="Send!" />)
|
79
|
+
end
|
80
|
+
it 'renders a reset tag' do
|
81
|
+
fh.reset.should == %q(<input id="button_reset" name="reset" type="reset" value="Reset" />)
|
82
|
+
fh.reset("Blark").should == %q(<input id="button_blark" name="reset" type="reset" value="Blark" />)
|
83
|
+
end
|
84
|
+
it 'supports multiple values for checkboxes' do
|
85
|
+
fh.params = {:user => {'devices' => ['iPhone', 'iPad'] }}
|
86
|
+
fh.checkbox(:user, :devices, ['iPhone', 'iPad', 'iPod', 'iPoop']).should ==
|
87
|
+
"<input checked=\"checked\" id=\"user_devices_iphone\" name=\"user[devices][]\" type=\"checkbox\" value=\"iPhone\" /><label for=\"user_devices_iphone\">iPhone</label> <input checked=\"checked\" id=\"user_devices_ipad\" name=\"user[devices][]\" type=\"checkbox\" value=\"iPad\" /><label for=\"user_devices_ipad\">iPad</label> <input id=\"user_devices_ipod\" name=\"user[devices][]\" type=\"checkbox\" value=\"iPod\" /><label for=\"user_devices_ipod\">iPod</label> <input id=\"user_devices_ipoop\" name=\"user[devices][]\" type=\"checkbox\" value=\"iPoop\" /><label for=\"user_devices_ipoop\">iPoop</label>"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "Sinatra::FormHelpers in app" do
|
92
|
+
it 'renders an anchor tag' do
|
93
|
+
app.get '/link' do
|
94
|
+
erb "<%= link 'google', 'http://www.google.com', :title => 'Google' %>"
|
95
|
+
end
|
96
|
+
|
97
|
+
get '/link'
|
98
|
+
last_response.body.should == %q(<a href="http://www.google.com" title="Google">google</a>)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'renders a label tag' do
|
102
|
+
app.get '/label' do
|
103
|
+
erb "<%= label :person, :first_name %>"
|
104
|
+
end
|
105
|
+
|
106
|
+
get '/label'
|
107
|
+
last_response.body.should == %q(<label for="person_first_name">First Name</label>)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'renders a label tag with display input' do
|
111
|
+
app.get '/hello' do
|
112
|
+
erb "<%= label :person, :first_name, 'Hello World'%>"
|
113
|
+
end
|
114
|
+
|
115
|
+
get '/hello'
|
116
|
+
last_response.body.should == %q(<label for="person_first_name">Hello World</label>)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'renders an input tag type text without @params' do
|
120
|
+
app.get '/text' do
|
121
|
+
erb "<%= input :person, :first_name %>"
|
122
|
+
end
|
123
|
+
|
124
|
+
get '/text'
|
125
|
+
last_response.body.should =~ /name="person\[first_name\]"/
|
126
|
+
last_response.body.should == %q(<input id="person_first_name" name="person[first_name]" type="text" />)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'renders an input tag type text with single arg' do
|
130
|
+
app.get '/q' do
|
131
|
+
erb "<%= input :q %>"
|
132
|
+
end
|
133
|
+
|
134
|
+
get '/q'
|
135
|
+
last_response.body.should == %q(<input id="q" name="q" type="text" />)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'renders an input tag type text with @params' do
|
139
|
+
app.get '/tom' do
|
140
|
+
@params = { :person => {"first_name" => "Tom"}}
|
141
|
+
erb "<%= input :person, :first_name %>"
|
142
|
+
end
|
143
|
+
|
144
|
+
get '/tom'
|
145
|
+
last_response.body.should == %q(<input id="person_first_name" name="person[first_name]" type="text" value="Tom" />)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'renders an textarea tag type text without @params' do
|
149
|
+
app.get '/notes' do
|
150
|
+
erb "<%= textarea :person, :notes %>"
|
151
|
+
end
|
152
|
+
|
153
|
+
get '/notes?person[notes]=Yeppers'
|
154
|
+
last_response.body.should == %q(<textarea id="person_notes" name="person[notes]">Yeppers</textarea>)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'renders a textarea tag with @params' do
|
158
|
+
app.get '/notes2' do
|
159
|
+
@params = { :person => {"notes" => "This is a note"}}
|
160
|
+
erb "<%= textarea :person, :notes %>"
|
161
|
+
end
|
162
|
+
|
163
|
+
get '/notes2'
|
164
|
+
last_response.body.should == %q(<textarea id="person_notes" name="person[notes]">This is a note</textarea>)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'renders a textarea tag with @params' do
|
168
|
+
app.get '/img' do
|
169
|
+
erb "<%= image '/images/hello.png', :alt => 'Lolcatz' %>"
|
170
|
+
end
|
171
|
+
|
172
|
+
get '/img'
|
173
|
+
last_response.body.should == '<img alt="Lolcatz" src="/images/hello.png" />'
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'renders an input tag with a submit type' do
|
177
|
+
app.get '/sub' do
|
178
|
+
erb "<%= submit 'Create' %>"
|
179
|
+
end
|
180
|
+
|
181
|
+
get '/sub'
|
182
|
+
last_response.body.should == '<input id="button_create" name="submit" type="submit" value="Create" />'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'renders an input tag with a submit type with zero args' do
|
186
|
+
app.get '/create' do
|
187
|
+
erb "<%= submit %>"
|
188
|
+
end
|
189
|
+
|
190
|
+
get '/create'
|
191
|
+
last_response.body.should == '<input id="button_submit" name="submit" type="submit" value="Submit" />'
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'renders an input tag with a checkbox type' do
|
195
|
+
app.get '/check' do
|
196
|
+
erb "<%= checkbox :person, :active, 'Yes' %>"
|
197
|
+
end
|
198
|
+
|
199
|
+
get '/check'
|
200
|
+
last_response.body.should ==
|
201
|
+
'<input id="person_active_yes" name="person[active]" type="checkbox" value="Yes" /><label for="person_active_yes">Yes</label>'
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'renders an input tag with a multiple checkbox type' do
|
205
|
+
app.get '/check2' do
|
206
|
+
erb "<%= checkbox :person, :eyes, [1,2,3] %>"
|
207
|
+
end
|
208
|
+
|
209
|
+
get '/check2'
|
210
|
+
last_response.body.should ==
|
211
|
+
'<input id="person_eyes_1" name="person[eyes][]" type="checkbox" value="1" /><label for="person_eyes_1">1</label> ' +
|
212
|
+
'<input id="person_eyes_2" name="person[eyes][]" type="checkbox" value="2" /><label for="person_eyes_2">2</label> ' +
|
213
|
+
'<input id="person_eyes_3" name="person[eyes][]" type="checkbox" value="3" /><label for="person_eyes_3">3</label>'
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'renders an input tag with a radio type' do
|
217
|
+
app.get '/radio' do
|
218
|
+
erb "<%= radio :person, :gender, [['M','Male'],['F','Female'],'Other'] %>"
|
219
|
+
end
|
220
|
+
|
221
|
+
get '/radio'
|
222
|
+
last_response.body.should ==
|
223
|
+
"<input id=\"person_gender_m\" name=\"person[gender]\" type=\"radio\" value=\"M\" /><label for=\"person_gender_m\">Male</label> " +
|
224
|
+
"<input id=\"person_gender_f\" name=\"person[gender]\" type=\"radio\" value=\"F\" /><label for=\"person_gender_f\">Female</label> " +
|
225
|
+
"<input id=\"person_gender_other\" name=\"person[gender]\" type=\"radio\" value=\"Other\" /><label for=\"person_gender_other\">Other</label>"
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'renders a select tag' do
|
229
|
+
app.get '/select' do
|
230
|
+
erb "<%= select :person, :relationship, ['Friend','CoWorker','Lead'] %>"
|
231
|
+
end
|
232
|
+
|
233
|
+
get '/select'
|
234
|
+
last_response.body.should == '<select id="person_relationship" name="person[relationship]">' +
|
235
|
+
'<option value="Friend">Friend</option><option value="CoWorker">CoWorker</option>' +
|
236
|
+
'<option value="Lead">Lead</option></select>'
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'renders a hidden tag with value' do
|
240
|
+
app.get '/hidden' do
|
241
|
+
erb '<%= hidden :person, :id, :value => 1 %>'
|
242
|
+
end
|
243
|
+
|
244
|
+
get '/hidden'
|
245
|
+
last_response.body.should == '<input id="person_id" name="person[id]" type="hidden" value="1" />'
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'renders a form tag' do
|
249
|
+
app.get '/form' do
|
250
|
+
erb "<%= form :person, :create %>"
|
251
|
+
end
|
252
|
+
|
253
|
+
get '/form'
|
254
|
+
last_response.body.should == %q(<form action="/person" method="POST">)
|
255
|
+
end
|
256
|
+
|
257
|
+
# it 'renders a form_for style tag' do
|
258
|
+
# app.get '/form_for' do
|
259
|
+
# erb <<-EndTemplate
|
260
|
+
# <% form(:person, :create) do |f| %>
|
261
|
+
# <%= f.input(:login) %>
|
262
|
+
# <%= f.password(:password) %>
|
263
|
+
# <%= submit %>
|
264
|
+
# <% end %>
|
265
|
+
# EndTemplate
|
266
|
+
# end
|
267
|
+
#
|
268
|
+
# get '/form_for'
|
269
|
+
# last_response.body.should == %q(<form action="/person" method="POST">)
|
270
|
+
# end
|
271
|
+
|
272
|
+
it 'renders a fieldset group' do
|
273
|
+
app.get '/fieldset' do
|
274
|
+
erb <<-EndTemplate
|
275
|
+
<% fieldset(:user) do |f| %>
|
276
|
+
<%= f.input(:first_name) %>
|
277
|
+
<%= f.input(:last_name) %>
|
278
|
+
|
279
|
+
<%= f.input(:email, :size => 40) %>
|
280
|
+
|
281
|
+
<%= f.password(:password) %>
|
282
|
+
<%= f.password(:confirm_password) %>
|
283
|
+
|
284
|
+
<%= f.radio(:gender, ['M', 'F']) %>
|
285
|
+
<% end %>
|
286
|
+
<%= submit %>
|
287
|
+
EndTemplate
|
288
|
+
end
|
289
|
+
|
290
|
+
get '/fieldset'
|
291
|
+
last_response.body.should ==
|
292
|
+
" <input id=\"user_first_name\" name=\"user[first_name]\" type=\"text\" />\n <input id=\"user_last_name\" name=\"user[last_name]\" type=\"text\" />\n\n <input id=\"user_email\" name=\"user[email]\" size=\"40\" type=\"text\" />\n\n <input id=\"user_password\" name=\"user[password]\" type=\"password\" />\n <input id=\"user_confirm_password\" name=\"user[confirm_password]\" type=\"password\" />\n\n <input id=\"user_gender_m\" name=\"user[gender]\" type=\"radio\" value=\"M\" /><label for=\"user_gender_m\">M</label> <input id=\"user_gender_f\" name=\"user[gender]\" type=\"radio\" value=\"F\" /><label for=\"user_gender_f\">F</label>\n<input id=\"button_submit\" name=\"submit\" type=\"submit\" value=\"Submit\" />"
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bacon'
|
3
|
+
require 'rack/test'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.expand_path File.dirname(__FILE__))
|
6
|
+
$LOAD_PATH.unshift(File.expand_path File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
require 'sinatra/base'
|
8
|
+
require 'sinatra/form_helpers'
|
9
|
+
|
10
|
+
class TestFormHelpers
|
11
|
+
include Sinatra::FormHelpers
|
12
|
+
attr_accessor :params
|
13
|
+
def initialize
|
14
|
+
@params = {}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def fh
|
18
|
+
@fh ||= TestFormHelpers.new
|
19
|
+
end
|
20
|
+
|
21
|
+
class Application < Sinatra::Base
|
22
|
+
helpers Sinatra::FormHelpers
|
23
|
+
set :raise_errors, false
|
24
|
+
set :show_exceptions, false
|
25
|
+
end
|
26
|
+
|
27
|
+
Bacon.summary_on_exit
|
28
|
+
class Bacon::Context
|
29
|
+
include Rack::Test::Methods
|
30
|
+
def app
|
31
|
+
Application
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lifted from sinatra/test_helpers (sinatra-contrib)
|
36
|
+
# def app
|
37
|
+
# @app ||= Class.new Sinatra::Base
|
38
|
+
# Rack::Lint.new @app
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def app=(base)
|
42
|
+
# @app = base
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# def mock_app(base = Sinatra::Base, &block)
|
46
|
+
# inner = nil
|
47
|
+
# @app = Sinatra.new(base) do
|
48
|
+
# inner = self
|
49
|
+
# set :raise_errors, false
|
50
|
+
# set :show_exceptions, false
|
51
|
+
# class_eval(&block)
|
52
|
+
# end
|
53
|
+
# @settings = inner
|
54
|
+
# app
|
55
|
+
# end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-formhelpers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.4.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nate Wiger
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-26 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bacon
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description: Simple, lightweight form helpers for Sinatra. Based on initial efforts by twilson63.
|
27
|
+
email: nate@wiger.org
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- LICENSE
|
34
|
+
- README.md
|
35
|
+
files:
|
36
|
+
- .document
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- lib/sinatra/form_helpers.rb
|
42
|
+
- sinatra-formhelpers.gemspec
|
43
|
+
- spec/form_helpers_spec.rb
|
44
|
+
- spec/spec_helper.rb
|
45
|
+
homepage: http://github.com/nateware/sinatra-formhelpers
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.6
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Form helpers for Sinatra
|
72
|
+
test_files: []
|
73
|
+
|