formtastic 0.9.4 → 0.9.5
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/README.textile +19 -2
- data/Rakefile +3 -4
- data/generators/form/form_generator.rb +9 -3
- data/lib/formtastic.rb +1042 -913
- data/lib/formtastic/i18n.rb +6 -1
- data/spec/custom_macros.rb +103 -3
- data/spec/form_helper_spec.rb +11 -1
- data/spec/i18n_spec.rb +48 -0
- data/spec/input_spec.rb +8 -8
- data/spec/inputs/boolean_input_spec.rb +34 -1
- data/spec/inputs/check_boxes_input_spec.rb +57 -1
- data/spec/inputs/date_input_spec.rb +3 -1
- data/spec/inputs/datetime_input_spec.rb +8 -8
- data/spec/inputs/radio_input_spec.rb +38 -2
- data/spec/inputs/select_input_spec.rb +124 -12
- data/spec/inputs/time_input_spec.rb +3 -1
- data/spec/inputs/time_zone_input_spec.rb +44 -1
- data/spec/inputs_spec.rb +10 -1
- data/spec/semantic_fields_for_spec.rb +3 -1
- data/spec/spec_helper.rb +13 -2
- metadata +4 -14
@@ -103,13 +103,29 @@ describe 'select input' do
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
+
describe "for a belongs_to association with :group_by => :author" do
|
107
|
+
it "should call author.posts" do
|
108
|
+
[@freds_post].each { |post| post.stub!(:to_label).and_return("Post - #{post.id}") }
|
109
|
+
@fred.should_receive(:posts)
|
110
|
+
|
111
|
+
semantic_form_for(@new_post) do |builder|
|
112
|
+
concat(builder.input(:main_post, :as => :select, :group_by => :author ) )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
106
117
|
describe 'for a belongs_to association with :group_by => :continent' do
|
107
118
|
before do
|
108
119
|
@authors = [@bob, @fred, @fred, @fred]
|
109
120
|
::Author.stub!(:find).and_return(@authors)
|
110
121
|
@continent_names = %w(Europe Africa)
|
111
|
-
@continents = (0..1).map { |i|
|
122
|
+
@continents = (0..1).map { |i| c = ::Continent.new; c.stub!(:id).and_return(100 - i);c }
|
112
123
|
@authors[0..1].each_with_index { |author, i| author.stub!(:continent).and_return(@continents[i]) }
|
124
|
+
::Continent.stub!(:reflect_on_all_associations).and_return {|macro| mock('reflection', :klass => Author) if macro == :has_many}
|
125
|
+
::Continent.stub!(:reflect_on_association).and_return {|column_name| mock('reflection', :klass => Author) if column_name == :authors}
|
126
|
+
::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Continent, :macro => :belongs_to) if column_name == :continent }
|
127
|
+
|
128
|
+
|
113
129
|
@continents.each_with_index do |continent, i|
|
114
130
|
continent.stub!(:to_label).and_return(@continent_names[i])
|
115
131
|
continent.stub!(:authors).and_return([@authors[i]])
|
@@ -279,21 +295,76 @@ describe 'select input' do
|
|
279
295
|
|
280
296
|
describe 'when :selected is set' do
|
281
297
|
before do
|
282
|
-
@
|
283
|
-
|
284
|
-
|
298
|
+
@output_buffer = ''
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "no selected items" do
|
302
|
+
before do
|
303
|
+
@new_post.stub!(:author_id).and_return(nil)
|
304
|
+
semantic_form_for(@new_post) do |builder|
|
305
|
+
concat(builder.input(:author, :as => :select, :selected => nil))
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'should not have any selected item(s)' do
|
310
|
+
output_buffer.should_not have_tag("form li select option[@selected='selected']")
|
285
311
|
end
|
286
312
|
end
|
287
|
-
|
288
|
-
|
289
|
-
|
313
|
+
|
314
|
+
describe "single selected item" do
|
315
|
+
before do
|
316
|
+
@new_post.stub!(:author_id).and_return(nil)
|
317
|
+
semantic_form_for(@new_post) do |builder|
|
318
|
+
concat(builder.input(:author, :as => :select, :selected => @bob.id))
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'should have a selected item; the specified one' do
|
323
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", :count => 1)
|
324
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", /bob/i)
|
325
|
+
output_buffer.should have_tag("form li select option[@selected='selected'][@value='#{@bob.id}']")
|
326
|
+
end
|
290
327
|
end
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
328
|
+
|
329
|
+
describe "multiple selected items" do
|
330
|
+
|
331
|
+
describe "when :multiple => false" do
|
332
|
+
before do
|
333
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
334
|
+
|
335
|
+
semantic_form_for(@new_post) do |builder|
|
336
|
+
concat(builder.input(:authors, :as => :select, :selected => [@bob.id, @fred.id], :multiple => false))
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should only select the first value" do
|
341
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", :count => 1)
|
342
|
+
# FIXME: Not supported by Nokogiri.
|
343
|
+
# output_buffer.should have_tag("form li select:not([@multiple]) option[@selected='selected']", /bob/i)
|
344
|
+
# output_buffer.should have_tag("form li select:not([@multiple]) option[@selected='selected'][@value='#{@bob.id}']")
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "when :multiple => true" do
|
349
|
+
before do
|
350
|
+
@new_post.stub!(:author_ids).and_return(nil)
|
351
|
+
|
352
|
+
semantic_form_for(@new_post) do |builder|
|
353
|
+
concat(builder.input(:authors, :as => :select, :selected => [@bob.id, @fred.id]))
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should have multiple items selected; the specified ones" do
|
358
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", :count => 2)
|
359
|
+
output_buffer.should have_tag("form li select[@multiple] option[@selected='selected']", /bob/i)
|
360
|
+
output_buffer.should have_tag("form li select[@multiple] option[@selected='selected'][@value='#{@bob.id}']")
|
361
|
+
output_buffer.should have_tag("form li select[@multiple] option[@selected='selected']", /fred/i)
|
362
|
+
output_buffer.should have_tag("form li select[@multiple] option[@selected='selected'][@value='#{@fred.id}']")
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
295
366
|
end
|
296
|
-
|
367
|
+
|
297
368
|
end
|
298
369
|
|
299
370
|
describe 'boolean select' do
|
@@ -339,4 +410,45 @@ describe 'select input' do
|
|
339
410
|
end
|
340
411
|
end
|
341
412
|
|
413
|
+
describe "enums" do
|
414
|
+
describe ":collection is set" do
|
415
|
+
before do
|
416
|
+
@output_buffer = ''
|
417
|
+
@some_meta_descriptions = ["One", "Two", "Three"]
|
418
|
+
@new_post.stub!(:meta_description).any_number_of_times
|
419
|
+
end
|
420
|
+
|
421
|
+
describe ":as is not set" do
|
422
|
+
before do
|
423
|
+
semantic_form_for(@new_post) do |builder|
|
424
|
+
concat(builder.input(:meta_description, :collection => @some_meta_descriptions))
|
425
|
+
end
|
426
|
+
semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
427
|
+
concat(builder.input(:meta_description, :collection => @some_meta_descriptions))
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
it "should render a select field" do
|
432
|
+
output_buffer.should have_tag("form li select", :count => 2)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
describe ":as is set" do
|
437
|
+
before do
|
438
|
+
# Should not be a case, but just checking :as got highest priority in setting input type.
|
439
|
+
semantic_form_for(@new_post) do |builder|
|
440
|
+
concat(builder.input(:meta_description, :as => :string, :collection => @some_meta_descriptions))
|
441
|
+
end
|
442
|
+
semantic_form_for(:project, :url => 'http://test.host') do |builder|
|
443
|
+
concat(builder.input(:meta_description, :as => :string, :collection => @some_meta_descriptions))
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
it "should render a text field" do
|
448
|
+
output_buffer.should have_tag("form li input[@type='text']", :count => 2)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
342
454
|
end
|
@@ -38,5 +38,7 @@ describe 'time input' do
|
|
38
38
|
output_buffer.should have_tag('form li.time fieldset ol li', :count => 2)
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
it_should_select_existing_datetime_else_current(:hour, :minute, :second)
|
42
|
+
it_should_select_explicit_default_value_if_set(:hour, :minute, :second)
|
42
43
|
|
44
|
+
end
|
@@ -8,7 +8,7 @@ describe 'time_zone input' do
|
|
8
8
|
before do
|
9
9
|
@output_buffer = ''
|
10
10
|
mock_everything
|
11
|
-
|
11
|
+
|
12
12
|
semantic_form_for(@new_post) do |builder|
|
13
13
|
concat(builder.input(:time_zone))
|
14
14
|
end
|
@@ -56,4 +56,47 @@ describe 'time_zone input' do
|
|
56
56
|
output_buffer.should have_tag("form li select[@name=\"project[time_zone]\"]")
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
describe 'when :selected is set' do
|
61
|
+
before do
|
62
|
+
@output_buffer = ''
|
63
|
+
end
|
64
|
+
|
65
|
+
# Note: Not possible to override default selected value for time_zone input
|
66
|
+
# without overriding Rails time_zone_select. This Rails helper works "a bit different". =/
|
67
|
+
#
|
68
|
+
# describe "no selected items" do
|
69
|
+
# before do
|
70
|
+
# @new_post.stub!(:time_zone).and_return('Stockholm')
|
71
|
+
#
|
72
|
+
# semantic_form_for(@new_post) do |builder|
|
73
|
+
# concat(builder.input(:time_zone, :as => :time_zone, :selected => nil))
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# it 'should not have any selected item(s)' do
|
78
|
+
# output_buffer.should_not have_tag("form li select option[@selected='selected']")
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
|
82
|
+
describe "single selected item" do
|
83
|
+
before do
|
84
|
+
# Note: See above...only works for the "attribute is nil" case.
|
85
|
+
# @new_post.stub!(:time_zone).and_return('Stockholm')
|
86
|
+
@new_post.stub!(:time_zone).and_return(nil)
|
87
|
+
|
88
|
+
semantic_form_for(@new_post) do |builder|
|
89
|
+
concat(builder.input(:time_zone, :as => :time_zone, :selected => 'Melbourne'))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should have a selected item; the specified one' do
|
94
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", :count => 1)
|
95
|
+
output_buffer.should have_tag("form li select option[@selected='selected']", /Melbourne/i)
|
96
|
+
output_buffer.should have_tag("form li select option[@selected='selected'][@value='Melbourne']")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
59
102
|
end
|
data/spec/inputs_spec.rb
CHANGED
@@ -176,6 +176,7 @@ describe 'SemanticFormBuilder#inputs' do
|
|
176
176
|
@legend_text = "Advanced options"
|
177
177
|
@legend_text_using_name = "Advanced options 2"
|
178
178
|
@legend_text_using_title = "Advanced options 3"
|
179
|
+
@nested_forms_legend_text = "This is a nested form title"
|
179
180
|
semantic_form_for(@new_post) do |builder|
|
180
181
|
builder.inputs @legend_text do
|
181
182
|
end
|
@@ -183,6 +184,8 @@ describe 'SemanticFormBuilder#inputs' do
|
|
183
184
|
end
|
184
185
|
builder.inputs :title => @legend_text_using_title do
|
185
186
|
end
|
187
|
+
builder.inputs @nested_forms_legend_text, :for => :authors do |nf|
|
188
|
+
end
|
186
189
|
end
|
187
190
|
end
|
188
191
|
|
@@ -190,6 +193,7 @@ describe 'SemanticFormBuilder#inputs' do
|
|
190
193
|
output_buffer.should have_tag("form fieldset legend", /^#{@legend_text}$/)
|
191
194
|
output_buffer.should have_tag("form fieldset legend", /^#{@legend_text_using_name}$/)
|
192
195
|
output_buffer.should have_tag("form fieldset legend", /^#{@legend_text_using_title}$/)
|
196
|
+
output_buffer.should have_tag("form fieldset legend", /^#{@nested_forms_legend_text}$/)
|
193
197
|
end
|
194
198
|
end
|
195
199
|
|
@@ -198,12 +202,14 @@ describe 'SemanticFormBuilder#inputs' do
|
|
198
202
|
@localized_legend_text = "Localized advanced options"
|
199
203
|
@localized_legend_text_using_name = "Localized advanced options 2"
|
200
204
|
@localized_legend_text_using_title = "Localized advanced options 3"
|
205
|
+
@localized_nested_forms_legend_text = "This is a localized nested form title"
|
201
206
|
::I18n.backend.store_translations :en, :formtastic => {
|
202
207
|
:titles => {
|
203
208
|
:post => {
|
204
209
|
:advanced_options => @localized_legend_text,
|
205
210
|
:advanced_options_using_name => @localized_legend_text_using_name,
|
206
|
-
:advanced_options_using_title => @localized_legend_text_using_title
|
211
|
+
:advanced_options_using_title => @localized_legend_text_using_title,
|
212
|
+
:nested_forms_title => @localized_nested_forms_legend_text
|
207
213
|
}
|
208
214
|
}
|
209
215
|
}
|
@@ -214,6 +220,8 @@ describe 'SemanticFormBuilder#inputs' do
|
|
214
220
|
end
|
215
221
|
builder.inputs :title => :advanced_options_using_title do
|
216
222
|
end
|
223
|
+
builder.inputs :nested_forms_title, :for => :authors do |nf|
|
224
|
+
end
|
217
225
|
end
|
218
226
|
end
|
219
227
|
|
@@ -221,6 +229,7 @@ describe 'SemanticFormBuilder#inputs' do
|
|
221
229
|
output_buffer.should have_tag("form fieldset legend", /^#{@localized_legend_text}$/)
|
222
230
|
output_buffer.should have_tag("form fieldset legend", /^#{@localized_legend_text_using_name}$/)
|
223
231
|
output_buffer.should have_tag("form fieldset legend", /^#{@localized_legend_text_using_title}$/)
|
232
|
+
output_buffer.should have_tag("form fieldset legend", /^#{@localized_nested_forms_legend_text}$/)
|
224
233
|
end
|
225
234
|
end
|
226
235
|
end
|
@@ -35,7 +35,9 @@ describe 'SemanticFormBuilder#semantic_fields_for' do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
output_buffer.should have_tag('form fieldset.inputs #post_author_1_login_input')
|
38
|
-
|
38
|
+
# Not valid selector, so using good ol' regex
|
39
|
+
output_buffer.should_not =~ /id="post\[author\]_1_login_input"/
|
40
|
+
# <=> output_buffer.should_not have_tag('form fieldset.inputs #post[author]_1_login_input')
|
39
41
|
end
|
40
42
|
|
41
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -15,7 +15,7 @@ end
|
|
15
15
|
smart_require 'spec', 'spec', '>= 1.2.6'
|
16
16
|
smart_require false, 'rspec-rails', '>= 1.2.6'
|
17
17
|
smart_require 'hpricot', 'hpricot', '>= 0.6.1'
|
18
|
-
smart_require '
|
18
|
+
smart_require 'rspec_tag_matchers', 'rspec_tag_matchers', '>= 1.0.0'
|
19
19
|
smart_require 'active_support', 'activesupport', '>= 2.3.4'
|
20
20
|
smart_require 'action_controller', 'actionpack', '>= 2.3.4'
|
21
21
|
smart_require 'action_view', 'actionpack', '>= 2.3.4'
|
@@ -23,7 +23,7 @@ smart_require 'action_view', 'actionpack', '>= 2.3.4'
|
|
23
23
|
require 'custom_macros'
|
24
24
|
|
25
25
|
Spec::Runner.configure do |config|
|
26
|
-
config.include(
|
26
|
+
config.include(RspecTagMatchers)
|
27
27
|
config.include(CustomMacros)
|
28
28
|
end
|
29
29
|
|
@@ -124,6 +124,8 @@ module FormtasticSpecHelper
|
|
124
124
|
@new_post.stub!(:new_record?).and_return(true)
|
125
125
|
@new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
|
126
126
|
@new_post.stub!(:author).and_return(nil)
|
127
|
+
@new_post.stub!(:main_post).and_return(nil)
|
128
|
+
@new_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
|
127
129
|
|
128
130
|
@freds_post = mock('post')
|
129
131
|
@freds_post.stub!(:class).and_return(::Post)
|
@@ -150,7 +152,12 @@ module FormtasticSpecHelper
|
|
150
152
|
mock
|
151
153
|
when :authors
|
152
154
|
mock('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
|
155
|
+
when :sub_posts
|
156
|
+
mock('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
|
157
|
+
when :main_post
|
158
|
+
mock('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
|
153
159
|
end
|
160
|
+
|
154
161
|
end
|
155
162
|
::Post.stub!(:find).and_return([@freds_post])
|
156
163
|
::Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
|
@@ -174,6 +181,10 @@ module FormtasticSpecHelper
|
|
174
181
|
|
175
182
|
@new_post.stub!(:author).and_return(@bob)
|
176
183
|
@new_post.stub!(:author_id).and_return(@bob.id)
|
184
|
+
|
185
|
+
@new_post.should_receive(:publish_at=).any_number_of_times
|
186
|
+
@new_post.should_receive(:title=).any_number_of_times
|
187
|
+
@new_post.stub!(:main_post_id).and_return(nil)
|
177
188
|
|
178
189
|
end
|
179
190
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formtastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin French
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-12-03 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -43,17 +43,7 @@ dependencies:
|
|
43
43
|
version: 1.2.6
|
44
44
|
version:
|
45
45
|
- !ruby/object:Gem::Dependency
|
46
|
-
name:
|
47
|
-
type: :development
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 0.6.1
|
54
|
-
version:
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec_hpricot_matchers
|
46
|
+
name: rspec_tag_matchers
|
57
47
|
type: :development
|
58
48
|
version_requirement:
|
59
49
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +112,7 @@ has_rdoc: true
|
|
122
112
|
homepage: http://github.com/justinfrench/formtastic/tree/master
|
123
113
|
licenses: []
|
124
114
|
|
125
|
-
post_install_message: "\n ========================================================================\n Thanks for installing Formtastic!\n ------------------------------------------------------------------------\n You can now (optionally) run the
|
115
|
+
post_install_message: "\n ========================================================================\n Thanks for installing Formtastic!\n ------------------------------------------------------------------------\n You can now (optionally) run the generator to copy some stylesheets and\n a config initializer into your application:\n ./script/generate formtastic\n\n To generate some semantic form markup for your exisiting models, just run:\n ./script/generate form MODEL_NAME\n\n Find out more and get involved:\n http://github.com/justinfrench/formtastic\n http://groups.google.com.au/group/formtastic\n ========================================================================\n "
|
126
116
|
rdoc_options:
|
127
117
|
- --charset=UTF-8
|
128
118
|
require_paths:
|