techthumb-formtastic 1.rails3.sha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +584 -0
  3. data/Rakefile +127 -0
  4. data/generators/form/USAGE +16 -0
  5. data/generators/form/form_generator.rb +120 -0
  6. data/generators/form/templates/view__form.html.erb +5 -0
  7. data/generators/form/templates/view__form.html.haml +4 -0
  8. data/generators/formtastic/formtastic_generator.rb +24 -0
  9. data/generators/formtastic/templates/formtastic.css +131 -0
  10. data/generators/formtastic/templates/formtastic.rb +54 -0
  11. data/generators/formtastic/templates/formtastic_changes.css +14 -0
  12. data/generators/formtastic_stylesheets/formtastic_stylesheets_generator.rb +16 -0
  13. data/init.rb +5 -0
  14. data/lib/formtastic/i18n.rb +35 -0
  15. data/lib/formtastic/layout_helper.rb +10 -0
  16. data/lib/formtastic/railtie.rb +12 -0
  17. data/lib/formtastic/util.rb +36 -0
  18. data/lib/formtastic.rb +1870 -0
  19. data/lib/generators/formtastic/form/form_generator.rb +86 -0
  20. data/lib/generators/formtastic/install/install_generator.rb +24 -0
  21. data/lib/locale/en.yml +8 -0
  22. data/rails/init.rb +2 -0
  23. data/spec/buttons_spec.rb +166 -0
  24. data/spec/commit_button_spec.rb +401 -0
  25. data/spec/custom_builder_spec.rb +98 -0
  26. data/spec/defaults_spec.rb +20 -0
  27. data/spec/error_proc_spec.rb +27 -0
  28. data/spec/errors_spec.rb +105 -0
  29. data/spec/form_helper_spec.rb +142 -0
  30. data/spec/helpers/layout_helper_spec.rb +21 -0
  31. data/spec/i18n_spec.rb +152 -0
  32. data/spec/include_blank_spec.rb +74 -0
  33. data/spec/input_spec.rb +786 -0
  34. data/spec/inputs/boolean_input_spec.rb +104 -0
  35. data/spec/inputs/check_boxes_input_spec.rb +426 -0
  36. data/spec/inputs/country_input_spec.rb +118 -0
  37. data/spec/inputs/date_input_spec.rb +168 -0
  38. data/spec/inputs/datetime_input_spec.rb +310 -0
  39. data/spec/inputs/file_input_spec.rb +34 -0
  40. data/spec/inputs/hidden_input_spec.rb +78 -0
  41. data/spec/inputs/numeric_input_spec.rb +44 -0
  42. data/spec/inputs/password_input_spec.rb +46 -0
  43. data/spec/inputs/radio_input_spec.rb +243 -0
  44. data/spec/inputs/select_input_spec.rb +546 -0
  45. data/spec/inputs/string_input_spec.rb +64 -0
  46. data/spec/inputs/text_input_spec.rb +34 -0
  47. data/spec/inputs/time_input_spec.rb +206 -0
  48. data/spec/inputs/time_zone_input_spec.rb +110 -0
  49. data/spec/inputs_spec.rb +476 -0
  50. data/spec/label_spec.rb +89 -0
  51. data/spec/semantic_errors_spec.rb +98 -0
  52. data/spec/semantic_fields_for_spec.rb +45 -0
  53. data/spec/spec.opts +2 -0
  54. data/spec/spec_helper.rb +289 -0
  55. data/spec/support/custom_macros.rb +494 -0
  56. data/spec/support/output_buffer.rb +4 -0
  57. data/spec/support/test_environment.rb +45 -0
  58. metadata +235 -0
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'SemanticFormBuilder#semantic_fields_for' do
5
+
6
+ include FormtasticSpecHelper
7
+
8
+ before do
9
+ @output_buffer = ''
10
+ mock_everything
11
+ @new_post.stub!(:author).and_return(::Author.new)
12
+ end
13
+
14
+ it 'yields an instance of SemanticFormHelper.builder' do
15
+ semantic_form_for(@new_post) do |builder|
16
+ builder.semantic_fields_for(:author) do |nested_builder|
17
+ nested_builder.class.should == ::Formtastic::SemanticFormHelper.builder
18
+ end
19
+ end
20
+ end
21
+
22
+ it 'nests the object name' do
23
+ semantic_form_for(@new_post) do |builder|
24
+ builder.semantic_fields_for(@bob) do |nested_builder|
25
+ nested_builder.object_name.should == 'post[author]'
26
+ end
27
+ end
28
+ end
29
+
30
+ it 'should sanitize html id for li tag' do
31
+ @bob.stub!(:column_for_attribute).and_return(mock('column', :type => :string, :limit => 255))
32
+ form = semantic_form_for(@new_post) do |builder|
33
+ concat(builder.semantic_fields_for(@bob, :index => 1) do |nested_builder|
34
+ concat(nested_builder.inputs(:login))
35
+ end)
36
+ end
37
+ output_buffer.concat(form) if Formtastic::Util.rails3?
38
+ output_buffer.should have_tag('form fieldset.inputs #post_author_1_login_input')
39
+ # Not valid selector, so using good ol' regex
40
+ output_buffer.should_not =~ /id="post\[author\]_1_login_input"/
41
+ # <=> output_buffer.should_not have_tag('form fieldset.inputs #post[author]_1_login_input')
42
+ end
43
+
44
+ end
45
+
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=progress
@@ -0,0 +1,289 @@
1
+ # coding: utf-8
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'action_pack'
5
+ require 'action_view'
6
+ require 'action_controller'
7
+ require 'action_mailer'
8
+
9
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/util'))
10
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
11
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/layout_helper'))
12
+
13
+ # Requires supporting files with custom matchers and macros, etc,
14
+ # in ./support/ and its subdirectories in alphabetic order.
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each {|f| require f}
16
+
17
+ module FormtasticSpecHelper
18
+ include ActionPack
19
+ include ActionView::Context if defined?(ActionView::Context)
20
+ include ActionController::RecordIdentifier
21
+ include ActionView::Helpers::FormHelper
22
+ include ActionView::Helpers::FormTagHelper
23
+ include ActionView::Helpers::FormOptionsHelper
24
+ include ActionView::Helpers::UrlHelper
25
+ include ActionView::Helpers::TagHelper
26
+ include ActionView::Helpers::TextHelper
27
+ include ActionView::Helpers::ActiveRecordHelper if defined?(ActionView::Helpers::ActiveRecordHelper)
28
+ include ActionView::Helpers::ActiveModelHelper if defined?(ActionView::Helpers::ActiveModelHelper)
29
+ include ActionView::Helpers::DateHelper
30
+ include ActionView::Helpers::CaptureHelper
31
+ include ActionView::Helpers::AssetTagHelper
32
+ include ActiveSupport
33
+ include ActionController::PolymorphicRoutes if defined?(ActionController::PolymorphicRoutes)
34
+
35
+ include Formtastic::SemanticFormHelper
36
+
37
+ def rails3?
38
+ ActionPack::VERSION::MAJOR > 2
39
+ end
40
+
41
+ def rails2?
42
+ ActionPack::VERSION::MAJOR == 2
43
+ end
44
+
45
+ def default_input_type(column_type, column_name = :generic_column_name)
46
+ @new_post.stub!(column_name)
47
+ @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => column_type)) unless column_type.nil?
48
+
49
+ semantic_form_for(@new_post) do |builder|
50
+ @default_type = builder.send(:default_input_type, column_name)
51
+ end
52
+
53
+ return @default_type
54
+ end
55
+
56
+ def active_model_presence_validator(attributes, options = {})
57
+ presence_validator = mock('ActiveModel::Validations::PresenceValidator', :attributes => attributes, :options => options)
58
+ presence_validator.stub!(:kind).and_return(:presence)
59
+ presence_validator
60
+ end
61
+
62
+ class ::Post
63
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
64
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
65
+
66
+ def id
67
+ end
68
+
69
+ def persisted?
70
+ end
71
+ end
72
+ module ::Namespaced
73
+ class Post
74
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
75
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
76
+
77
+ def id
78
+ end
79
+
80
+ def persisted?
81
+ end
82
+ end
83
+ end
84
+ class ::Author
85
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
86
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
87
+
88
+ def to_label
89
+ end
90
+ end
91
+ class ::Continent
92
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
93
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
94
+ end
95
+ class ::PostModel
96
+ extend ActiveModel::Naming if defined?(ActiveModel::Naming)
97
+ include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
98
+ end
99
+
100
+ def mock_everything
101
+
102
+ # Resource-oriented styles like form_for(@post) will expect a path method for the object,
103
+ # so we're defining some here.
104
+ def post_models_path; "/postmodels/1"; end
105
+
106
+ def post_path(o); "/posts/1"; end
107
+ def posts_path; "/posts"; end
108
+ def new_post_path; "/posts/new"; end
109
+
110
+ def author_path(o); "/authors/1"; end
111
+ def authors_path; "/authors"; end
112
+ def new_author_path; "/authors/new"; end
113
+
114
+ @fred = mock('user')
115
+ @fred.stub!(:to_ary)
116
+ @fred.stub!(:class).and_return(::Author)
117
+ @fred.stub!(:to_label).and_return('Fred Smith')
118
+ @fred.stub!(:login).and_return('fred_smith')
119
+ @fred.stub!(:id).and_return(37)
120
+ @fred.stub!(:new_record?).and_return(false)
121
+ @fred.stub!(:errors).and_return(mock('errors', :[] => nil))
122
+ @fred.stub!(:to_key).and_return(nil)
123
+ @fred.stub!(:persisted?).and_return(nil)
124
+
125
+ @bob = mock('user')
126
+ @bob.stub!(:to_ary)
127
+ @bob.stub!(:class).and_return(::Author)
128
+ @bob.stub!(:to_label).and_return('Bob Rock')
129
+ @bob.stub!(:login).and_return('bob')
130
+ @bob.stub!(:created_at)
131
+ @bob.stub!(:id).and_return(42)
132
+ @bob.stub!(:posts).and_return([])
133
+ @bob.stub!(:post_ids).and_return([])
134
+ @bob.stub!(:new_record?).and_return(false)
135
+ @bob.stub!(:errors).and_return(mock('errors', :[] => nil))
136
+ @bob.stub!(:to_key).and_return(nil)
137
+ @bob.stub!(:persisted?).and_return(nil)
138
+
139
+ @james = mock('user')
140
+ @james.stub!(:to_ary)
141
+ @james.stub!(:class).and_return(::Author)
142
+ @james.stub!(:to_label).and_return('James Shock')
143
+ @james.stub!(:login).and_return('james')
144
+ @james.stub!(:id).and_return(75)
145
+ @james.stub!(:posts).and_return([])
146
+ @james.stub!(:post_ids).and_return([])
147
+ @james.stub!(:new_record?).and_return(false)
148
+ @james.stub!(:errors).and_return(mock('errors', :[] => nil))
149
+ @james.stub!(:to_key).and_return(nil)
150
+ @james.stub!(:persisted?).and_return(nil)
151
+
152
+
153
+ ::Author.stub!(:find).and_return([@fred, @bob])
154
+ ::Author.stub!(:all).and_return([@fred, @bob])
155
+ ::Author.stub!(:to_ary)
156
+ ::Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
157
+ ::Author.stub!(:human_name).and_return('::Author')
158
+ ::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
159
+ ::Author.stub!(:content_columns).and_return([mock('column', :name => 'login'), mock('column', :name => 'created_at')])
160
+ ::Author.stub!(:to_key).and_return(nil)
161
+ ::Author.stub!(:persisted?).and_return(nil)
162
+
163
+ # Sometimes we need a mock @post object and some Authors for belongs_to
164
+ @new_post = mock('post')
165
+ @new_post.stub!(:to_ary)
166
+ @new_post.stub!(:class).and_return(::Post)
167
+ @new_post.stub!(:id).and_return(nil)
168
+ @new_post.stub!(:new_record?).and_return(true)
169
+ @new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
170
+ @new_post.stub!(:author).and_return(nil)
171
+ @new_post.stub!(:reviewer).and_return(nil)
172
+ @new_post.stub!(:main_post).and_return(nil)
173
+ @new_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
174
+ @new_post.stub!(:to_key).and_return(nil)
175
+ @new_post.stub!(:to_model).and_return(@new_post)
176
+ @new_post.stub!(:persisted?).and_return(nil)
177
+
178
+ @freds_post = mock('post')
179
+ @freds_post.stub!(:to_ary)
180
+ @freds_post.stub!(:class).and_return(::Post)
181
+ @freds_post.stub!(:to_label).and_return('Fred Smith')
182
+ @freds_post.stub!(:id).and_return(19)
183
+ @freds_post.stub!(:author).and_return(@fred)
184
+ @freds_post.stub!(:author_id).and_return(@fred.id)
185
+ @freds_post.stub!(:authors).and_return([@fred])
186
+ @freds_post.stub!(:author_ids).and_return([@fred.id])
187
+ @freds_post.stub!(:new_record?).and_return(false)
188
+ @freds_post.stub!(:errors).and_return(mock('errors', :[] => nil))
189
+ @freds_post.stub!(:to_key).and_return(nil)
190
+ @freds_post.stub!(:persisted?).and_return(nil)
191
+ @fred.stub!(:posts).and_return([@freds_post])
192
+ @fred.stub!(:post_ids).and_return([@freds_post.id])
193
+
194
+ ::Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
195
+ ::Post.stub!(:human_name).and_return('Post')
196
+ ::Post.stub!(:reflect_on_all_validations).and_return([])
197
+ ::Post.stub!(:reflect_on_validations_for).and_return([])
198
+ ::Post.stub!(:reflections).and_return({})
199
+ ::Post.stub!(:reflect_on_association).and_return do |column_name|
200
+ case column_name
201
+ when :author, :author_status
202
+ mock = mock('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
203
+ mock.stub!(:[]).with(:class_name).and_return("Author")
204
+ mock
205
+ when :reviewer
206
+ mock = mock('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
207
+ mock.stub!(:[]).with(:class_name).and_return("Author")
208
+ mock
209
+ when :authors
210
+ mock('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
211
+ when :sub_posts
212
+ mock('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
213
+ when :main_post
214
+ mock('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
215
+ end
216
+
217
+ end
218
+ ::Post.stub!(:find).and_return([@freds_post])
219
+ ::Post.stub!(:all).and_return([@freds_post])
220
+ ::Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
221
+ ::Post.stub!(:to_key).and_return(nil)
222
+ ::Post.stub!(:persisted?).and_return(nil)
223
+ ::Post.stub!(:to_ary)
224
+
225
+ @new_post.stub!(:title)
226
+ @new_post.stub!(:to_ary)
227
+ @new_post.stub!(:body)
228
+ @new_post.stub!(:published)
229
+ @new_post.stub!(:publish_at)
230
+ @new_post.stub!(:created_at)
231
+ @new_post.stub!(:secret)
232
+ @new_post.stub!(:time_zone)
233
+ @new_post.stub!(:category_name)
234
+ @new_post.stub!(:allow_comments)
235
+ @new_post.stub!(:country)
236
+ @new_post.stub!(:country_subdivision)
237
+ @new_post.stub!(:country_code)
238
+ @new_post.stub!(:column_for_attribute).with(:meta_description).and_return(mock('column', :type => :string, :limit => 255))
239
+ @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 50))
240
+ @new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
241
+ @new_post.stub!(:column_for_attribute).with(:published).and_return(mock('column', :type => :boolean))
242
+ @new_post.stub!(:column_for_attribute).with(:publish_at).and_return(mock('column', :type => :date))
243
+ @new_post.stub!(:column_for_attribute).with(:time_zone).and_return(mock('column', :type => :string))
244
+ @new_post.stub!(:column_for_attribute).with(:allow_comments).and_return(mock('column', :type => :boolean))
245
+ @new_post.stub!(:column_for_attribute).with(:author).and_return(mock('column', :type => :integer))
246
+ @new_post.stub!(:column_for_attribute).with(:country).and_return(mock('column', :type => :string, :limit => 255))
247
+ @new_post.stub!(:column_for_attribute).with(:country_subdivision).and_return(mock('column', :type => :string, :limit => 255))
248
+ @new_post.stub!(:column_for_attribute).with(:country_code).and_return(mock('column', :type => :string, :limit => 255))
249
+
250
+ @new_post.stub!(:author).and_return(@bob)
251
+ @new_post.stub!(:author_id).and_return(@bob.id)
252
+
253
+ @new_post.stub!(:reviewer).and_return(@fred)
254
+ @new_post.stub!(:reviewer_id).and_return(@fred.id)
255
+
256
+ @new_post.should_receive(:publish_at=).any_number_of_times
257
+ @new_post.should_receive(:title=).any_number_of_times
258
+ @new_post.stub!(:main_post_id).and_return(nil)
259
+
260
+ end
261
+
262
+ def self.included(base)
263
+ base.class_eval do
264
+
265
+ attr_accessor :output_buffer
266
+
267
+ def protect_against_forgery?
268
+ false
269
+ end
270
+
271
+ end
272
+ end
273
+
274
+ def with_config(config_method_name, value, &block)
275
+ old_value = ::Formtastic::SemanticFormBuilder.send(config_method_name)
276
+ ::Formtastic::SemanticFormBuilder.send(:"#{config_method_name}=", value)
277
+ yield
278
+ ::Formtastic::SemanticFormBuilder.send(:"#{config_method_name}=", old_value)
279
+ end
280
+
281
+ def with_deprecation_silenced(&block)
282
+ ::ActiveSupport::Deprecation.silenced = true
283
+ yield
284
+ ::ActiveSupport::Deprecation.silenced = false
285
+ end
286
+
287
+ end
288
+
289
+ ::ActiveSupport::Deprecation.silenced = false