visionmedia-dm-forms 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +4 -0
- data/Manifest +19 -16
- data/README.rdoc +4 -33
- data/Rakefile +6 -4
- data/Todo.rdoc +13 -15
- data/dm-forms.gemspec +7 -4
- data/examples/benchmarks.rb +26 -110
- data/examples/login.rb +20 -0
- data/lib/dm-forms.rb +5 -6
- data/lib/dm-forms/base.rb +115 -0
- data/lib/dm-forms/core_ext.rb +27 -22
- data/lib/dm-forms/helpers.rb +83 -0
- data/lib/dm-forms/mixins.rb +8 -0
- data/lib/dm-forms/mixins/descriptions.rb +18 -0
- data/lib/dm-forms/mixins/errors.rb +0 -0
- data/lib/dm-forms/mixins/labels.rb +16 -0
- data/lib/dm-forms/mixins/wrappers.rb +26 -0
- data/lib/dm-forms/tag.rb +67 -134
- data/lib/dm-forms/version.rb +1 -4
- data/spec/functional/helpers_spec.rb +186 -0
- data/spec/functional/mixins/descriptions_spec.rb +19 -0
- data/spec/functional/mixins/labels_spec.rb +19 -0
- data/spec/functional/mixins/wrappers_spec.rb +21 -0
- data/spec/functional/tag_spec.rb +33 -41
- data/spec/integration/datamapper_spec.rb +73 -45
- data/spec/spec_helper.rb +5 -7
- data/tasks/spec.rake +5 -0
- metadata +42 -22
- data/examples/datamapper.rb +0 -37
- data/examples/elements.rb +0 -31
- data/examples/haml.rb +0 -21
- data/examples/login.haml +0 -4
- data/lib/dm-forms/elements.rb +0 -210
- data/lib/dm-forms/model_elements.rb +0 -33
- data/spec/functional/core_ext_spec.rb +0 -56
- data/spec/functional/elements_spec.rb +0 -209
- data/spec/integration/haml_spec.rb +0 -29
data/lib/dm-forms/version.rb
CHANGED
@@ -0,0 +1,186 @@
|
|
1
|
+
|
2
|
+
def params
|
3
|
+
Hash.new { |h, k| k }
|
4
|
+
end
|
5
|
+
public :params
|
6
|
+
|
7
|
+
describe DataMapper::Form::Helpers do
|
8
|
+
|
9
|
+
include DataMapper::Form::Helpers
|
10
|
+
|
11
|
+
describe "#new_form_context" do
|
12
|
+
it "should create a new context each time its called" do
|
13
|
+
a = new_form_context
|
14
|
+
b = new_form_context
|
15
|
+
a.should be_a(DataMapper::Form::Base)
|
16
|
+
b.should be_a(DataMapper::Form::Base)
|
17
|
+
a.should_not == b
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#form_context" do
|
22
|
+
it "should utilize the previous context or create a new one when not present" do
|
23
|
+
a = form_context
|
24
|
+
b = form_context
|
25
|
+
a.should be_a(DataMapper::Form::Base)
|
26
|
+
b.should be_a(DataMapper::Form::Base)
|
27
|
+
a.should == b
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
%w( textfield submit file button hidden password radio checkbox ).each do |type|
|
32
|
+
describe "##{type}" do
|
33
|
+
it "should create an unbound #{type}" do
|
34
|
+
send(type, :name => 'foo').should have_tag("input[@type=#{type}]")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
%w( textfield radio checkbox ).each do |type|
|
40
|
+
describe "##{type}" do
|
41
|
+
it "should use origin #params method to grab the default value when present" do
|
42
|
+
send(type, :name => 'foo').should have_tag("input[@type=#{type}]") do |tag|
|
43
|
+
tag.attributes['value'].should == 'foo'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#textarea" do
|
50
|
+
it "should default its contents using origin #params" do
|
51
|
+
textarea(:name => 'comments').should have_tag('textarea[@name=comments]', 'comments')
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should allow contents to be passed as a first argument" do
|
55
|
+
def params; {} end
|
56
|
+
textarea('Whatever', :name => 'comments').should have_tag('textarea[@name=comments]', 'Whatever')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#form" do
|
61
|
+
it "should create a form, defaulting method to post" do
|
62
|
+
markup = form :action => '/login' do
|
63
|
+
textfield :name => 'name'
|
64
|
+
textfield :name => 'pass'
|
65
|
+
submit 'Login', :name => 'op'
|
66
|
+
end
|
67
|
+
markup.should have_tag('form[@action=/login]') do |form|
|
68
|
+
form.attributes['method'].should == 'post'
|
69
|
+
form.should have_tag('input[@name=name]')
|
70
|
+
form.should have_tag('input[@name=pass]')
|
71
|
+
form.should have_tag('input[@name=op]')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should create a form with get method" do
|
76
|
+
markup = form :action => '/login', :method => :get do
|
77
|
+
end
|
78
|
+
markup.should have_tag('form[@method=get]')
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should use multipart encoding when multipart is set" do
|
82
|
+
markup = form :action => '/login', :multipart => true do
|
83
|
+
end
|
84
|
+
markup.should have_tag('form[@enctype=multipart/form-data]')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should use multipart encoding a file field is present" do
|
88
|
+
markup = form :action => '/login' do
|
89
|
+
file :name => 'image'
|
90
|
+
end
|
91
|
+
markup.should have_tag('form[@enctype=multipart/form-data]')
|
92
|
+
markup.should_not have_tag('input[@type=hidden]')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should create a hidden input with _method when anything but get or post" do
|
96
|
+
markup = form :method => :put do
|
97
|
+
file :name => 'image'
|
98
|
+
end
|
99
|
+
markup.should have_tag('form[@method=post]')
|
100
|
+
markup.should have_tag('input[@type=hidden]') do |input|
|
101
|
+
input.attributes['name'].should == '_method'
|
102
|
+
input.attributes['value'].should == 'put'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should create a form using yeild syntax" do
|
107
|
+
markup = form :action => '/login' do |f|
|
108
|
+
f.textfield :name => 'name'
|
109
|
+
f.textfield :name => 'pass'
|
110
|
+
f.submit 'Login'
|
111
|
+
end
|
112
|
+
markup.should have_tag('form[@action=/login]') do |form|
|
113
|
+
form.should have_tag('input[@name=name]')
|
114
|
+
form.should have_tag('input[@name=pass]')
|
115
|
+
form.should have_tag('input[@name=submit]')
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#fieldset" do
|
121
|
+
it "should create a fieldset with optional legend" do
|
122
|
+
markup = fieldset :legend => 'User Details' do
|
123
|
+
textfield :name => 'name'
|
124
|
+
textfield :name => 'email'
|
125
|
+
end
|
126
|
+
markup.should have_tag('fieldset') do |fieldset|
|
127
|
+
fieldset.should have_tag('legend', 'User Details')
|
128
|
+
fieldset.should have_tag('input[@name=name]')
|
129
|
+
fieldset.should have_tag('input[@name=email]')
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#submit" do
|
135
|
+
it "should default value to Submit, and name to submit" do
|
136
|
+
submit.should have_tag('input[@name=submit]')
|
137
|
+
submit.should have_tag('input[@value=Submit]')
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should allow the first arg to be a value string" do
|
141
|
+
submit('Login').should have_tag('input[@value=Login]')
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "#select" do
|
146
|
+
before :each do
|
147
|
+
@days = {
|
148
|
+
1 => 'Mon',
|
149
|
+
2 => 'Tue',
|
150
|
+
3 => 'Wed',
|
151
|
+
4 => 'Thu',
|
152
|
+
5 => 'Fri',
|
153
|
+
6 => 'Sat',
|
154
|
+
7 => 'Sun',
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should populate options" do
|
159
|
+
select(:name => 'days', :options => @days).should have_tag('select[@name=days]') do |select|
|
160
|
+
@days.each do |value, contents|
|
161
|
+
select.should have_tag("option[@value=#{value}]", contents)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should allow setting of the selected option" do
|
167
|
+
select(:name => 'days', :options => @days, :selected => 2).should have_tag('select[@name=days]') do |select|
|
168
|
+
select.should have_tag('option[@selected=selected]', 'Tue')
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should allow a prompt option, defaulting it to selected" do
|
173
|
+
select(:name => 'days', :options => @days, :prompt => 'Select day').should have_tag('select[@name=days]') do |select|
|
174
|
+
select.should have_tag('option[@selected=selected]', 'Select day')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should allow a prompt option, but allowing selection of other options" do
|
179
|
+
select(:name => 'days', :options => @days, :prompt => 'Select day', :selected => 7).should have_tag('select[@name=days]') do |select|
|
180
|
+
select.should have_tag('option[@selected=selected]', 'Sun')
|
181
|
+
select.should have_tag('option:not(selected)', 'Select day')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
describe DataMapper::Form::Descriptions do
|
3
|
+
|
4
|
+
include DataMapper::Form::Helpers
|
5
|
+
DataMapper::Form::Base.send :include, DataMapper::Form::Descriptions
|
6
|
+
|
7
|
+
it "should create elements like normal when descriptions are not utilized" do
|
8
|
+
markup = textfield :name => 'email'
|
9
|
+
markup.should have_tag('input[@type=textfield]')
|
10
|
+
markup.should_not have_tag('span[@class=description]')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should create elements with descriptions" do
|
14
|
+
markup = textfield :name => 'email', :description => 'Please enter a valid email.'
|
15
|
+
markup.should have_tag('input[@type=textfield]')
|
16
|
+
markup.should have_tag('span[@class=description]')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
describe DataMapper::Form::Labels do
|
3
|
+
|
4
|
+
include DataMapper::Form::Helpers
|
5
|
+
DataMapper::Form::Base.send :include, DataMapper::Form::Labels
|
6
|
+
|
7
|
+
it "should create elements like normal when labels are not utilized" do
|
8
|
+
markup = textfield :name => 'email'
|
9
|
+
markup.should have_tag('input[@type=textfield]')
|
10
|
+
markup.should_not have_tag('label')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should create elements with labels" do
|
14
|
+
markup = textfield :name => 'email', :label => 'Email'
|
15
|
+
markup.should have_tag('input[@type=textfield]')
|
16
|
+
markup.should have_tag('label[@for=email]', 'Email')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
describe DataMapper::Form::Wrappers do
|
3
|
+
|
4
|
+
include DataMapper::Form::Helpers
|
5
|
+
DataMapper::Form::Base.send :include, DataMapper::Form::Wrappers
|
6
|
+
|
7
|
+
it "should create wrappers around elements for styling" do
|
8
|
+
markup = textarea :name => 'comments'
|
9
|
+
markup.should have_tag('div[@class=form-textarea form-comments]') do |div|
|
10
|
+
div.should have_tag('textarea')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should create wrappers around elements for styling, prioritizing :type for the class" do
|
15
|
+
markup = textfield :name => 'email'
|
16
|
+
markup.should have_tag('div[@class=form-textfield form-email]') do |div|
|
17
|
+
div.should have_tag('input[@type=textfield]')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/spec/functional/tag_spec.rb
CHANGED
@@ -1,49 +1,41 @@
|
|
1
1
|
|
2
2
|
describe DataMapper::Form::Tag do
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
it "should generate classes" do
|
7
|
-
tag = Tag.new :input, :attributes => { :name => 'email', :type => :textfield }
|
8
|
-
tag.send(:classes).should == 'form-textfield form-email'
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should generate classes when no name is present" do
|
12
|
-
tag = Tag.new :input, :attributes => { :type => :textfield }
|
13
|
-
tag.send(:classes).should == 'form-textfield'
|
14
|
-
end
|
4
|
+
include DataMapper::Form::Tag
|
15
5
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
6
|
+
describe "#tag" do
|
7
|
+
it "should create a simple tag" do
|
8
|
+
tag(:div).should have_tag('div')
|
9
|
+
end
|
20
10
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
tag.attributes.has_key?(:description).should be_false
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should allow capturing of elements via block" do
|
38
|
-
tag = Tag.new :fieldset, :attributes => { :id => 'something' } do |f|
|
39
|
-
f.button :one
|
40
|
-
f.button :two
|
11
|
+
it "should create a tag with attributes" do
|
12
|
+
tag(:div, :id => 'foo').should have_tag('div#foo')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should create a tag with param contents" do
|
16
|
+
tag(:div, 'bar', :id => 'foo').should have_tag('div#foo', 'bar')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should create a tag with block contents" do
|
20
|
+
tag :div, :id => 'foo' do
|
21
|
+
'bar'
|
22
|
+
end.
|
23
|
+
should have_tag('div#foo', 'bar')
|
41
24
|
end
|
42
|
-
tag.render.should == <<-HTML.deindent
|
43
|
-
<fieldset id="something"><input type="button" class="form-button form-one" name="one" />
|
44
|
-
<input type="button" class="form-button form-two" name="two" />
|
45
|
-
</fieldset>
|
46
|
-
HTML
|
47
|
-
end
|
48
25
|
|
26
|
+
it "should mirror boolean attributes" do
|
27
|
+
tag(:option, :selected => true).should have_tag("option[@selected=selected]")
|
28
|
+
tag(:option, :selected => 'true').should have_tag("option[@selected=selected]")
|
29
|
+
tag(:option, :selected => '1').should have_tag("option[@selected=selected]")
|
30
|
+
tag(:option, :selected => 'selected').should have_tag("option[@selected=selected]")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should negate boolean attributes" do
|
34
|
+
tag(:option, :selected => false).should have_tag("option:not([@selected=selected])")
|
35
|
+
tag(:option, :selected => '').should have_tag("option:not([@selected=selected])")
|
36
|
+
tag(:option, :selected => '0').should have_tag("option:not([@selected=selected])")
|
37
|
+
tag(:option, :selected => 'false').should have_tag("option:not([@selected=selected])")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
49
41
|
end
|
@@ -2,69 +2,97 @@
|
|
2
2
|
require 'dm-core'
|
3
3
|
require 'dm-validations'
|
4
4
|
|
5
|
-
include DataMapper::Form::ModelElements
|
6
|
-
|
7
5
|
DataMapper.setup :default, 'sqlite3::memory:'
|
8
6
|
|
9
7
|
class User
|
10
8
|
include DataMapper::Resource
|
11
|
-
property :id,
|
12
|
-
property :name,
|
13
|
-
property :email,
|
9
|
+
property :id, Serial
|
10
|
+
property :name, String, :format => /^[\w]+$/
|
11
|
+
property :email, String, :format => :email_address
|
12
|
+
property :signature, Text, :nullable => true, :lazy => false
|
13
|
+
end
|
14
|
+
|
15
|
+
class User::Role
|
16
|
+
include DataMapper::Resource
|
17
|
+
property :id, Serial
|
18
|
+
property :name, String
|
14
19
|
end
|
15
20
|
|
16
21
|
DataMapper.auto_migrate!
|
17
22
|
|
18
|
-
describe DataMapper::Form::
|
23
|
+
describe DataMapper::Form::Helpers do
|
24
|
+
|
25
|
+
include DataMapper::Form::Helpers
|
19
26
|
|
20
27
|
before :each do
|
21
|
-
@
|
28
|
+
@valid_user = User.new :name => 'foo bar', :email => 'is-valid@email.com', :signature => 'i like cookies'
|
29
|
+
@invalid_user = User.new :name => 'foobar', :email => 'is-valid@email.com', :signature => 'i like cookies'
|
30
|
+
@admin_role = User::Role.new :name => 'admin'
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#new_form_context" do
|
34
|
+
it "should generate a name used for prefixing form element names" do
|
35
|
+
new_form_context(@admin_role, self).name.should == 'role'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#form_for" do
|
40
|
+
it "should create a form in context to a model" do
|
41
|
+
markup = form_for @valid_user do
|
42
|
+
textfield :name, :id => 'username'
|
43
|
+
password :pass, :id => 'password'
|
44
|
+
end
|
45
|
+
markup.should have_tag('form') do |form|
|
46
|
+
form.should have_tag('input[@name=user[name]]') { |name| name.attributes['value'].should == 'foo bar' }
|
47
|
+
form.should have_tag('input[@name=user[pass]]')
|
48
|
+
end
|
49
|
+
end
|
22
50
|
end
|
23
51
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
52
|
+
describe "#fields_for" do
|
53
|
+
it "should create a temporary context within a form" do
|
54
|
+
markup = form_for @valid_user do
|
55
|
+
textfield :name, :id => 'username'
|
56
|
+
fields_for @admin_role do
|
57
|
+
textfield :name, :id => 'role-name'
|
58
|
+
end
|
59
|
+
password :pass, :id => 'password'
|
60
|
+
end
|
61
|
+
markup.should have_tag('form') do |form|
|
62
|
+
form.should have_tag('input[@name=user[name]]') { |name| name.attributes['value'].should == 'foo bar' }
|
63
|
+
form.should have_tag('input[@name=user[pass]]')
|
64
|
+
form.should have_tag('input[@name=role[name]]')
|
65
|
+
end
|
66
|
+
end
|
37
67
|
end
|
38
68
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
69
|
+
describe "#fieldset_for" do
|
70
|
+
it "should create a fieldset in context to a model" do
|
71
|
+
markup = form_for @valid_user do
|
72
|
+
textfield :name, :id => 'username'
|
73
|
+
fieldset_for @admin_role, :legend => 'Role' do
|
74
|
+
textfield :name, :id => 'role-name'
|
75
|
+
end
|
76
|
+
password :pass, :id => 'password'
|
77
|
+
end
|
78
|
+
markup.should have_tag('form') do |form|
|
79
|
+
form.should have_tag('input[@name=user[name]]') { |name| name.attributes['value'].should == 'foo bar' }
|
80
|
+
form.should have_tag('input[@name=user[pass]]')
|
81
|
+
form.should have_tag('fieldset') do |fieldset|
|
82
|
+
fieldset.should have_tag('legend', 'Role')
|
83
|
+
fieldset.should have_tag('input[@name=role[name]]')
|
84
|
+
end
|
85
|
+
end
|
44
86
|
end
|
45
|
-
results.should == <<-HTML.deindent
|
46
|
-
<form method="post" id="form-user"><input type="textfield" class="error form-textfield form-name" name="name" />
|
47
|
-
<input type="textfield" class="form-textfield form-email" name="email" />
|
48
|
-
<input type="submit" class="form-submit form-op" value="Save" name="op" />
|
49
|
-
</form>
|
50
|
-
HTML
|
51
87
|
end
|
52
88
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
f.submit :op, :value => 'Save'
|
89
|
+
describe "#textarea" do
|
90
|
+
it "should default its contents using the models method" do
|
91
|
+
markup = fields_for @valid_user do
|
92
|
+
textarea :signature
|
93
|
+
end
|
94
|
+
markup.should have_tag('textarea[@name=user[signature]]', 'i like cookies')
|
60
95
|
end
|
61
|
-
results.should == <<-HTML.deindent
|
62
|
-
<form method="post" action="/register" id="form-user"><input type="hidden" value="put" name="_method" />
|
63
|
-
<input type="textfield" class="form-textfield form-name" name="name" />
|
64
|
-
<input type="textfield" class="form-textfield form-email" name="email" />
|
65
|
-
<input type="submit" class="form-submit form-op" value="Save" name="op" />
|
66
|
-
</form>
|
67
|
-
HTML
|
68
96
|
end
|
69
97
|
|
70
98
|
end
|