visionmedia-dm-forms 0.0.2 → 0.0.3
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/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
|