simple_form 2.1.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -51
  3. data/README.md +195 -161
  4. data/lib/generators/simple_form/install_generator.rb +4 -4
  5. data/lib/generators/simple_form/templates/README +2 -2
  6. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +16 -13
  7. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +16 -16
  8. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +3 -3
  9. data/lib/simple_form/action_view_extensions/builder.rb +1 -320
  10. data/lib/simple_form/action_view_extensions/builder.rb.orig +247 -0
  11. data/lib/simple_form/action_view_extensions/form_helper.rb +2 -9
  12. data/lib/simple_form/components/errors.rb +1 -7
  13. data/lib/simple_form/components/hints.rb +2 -7
  14. data/lib/simple_form/components/html5.rb +5 -2
  15. data/lib/simple_form/components/labels.rb +4 -4
  16. data/lib/simple_form/components/maxlength.rb +1 -8
  17. data/lib/simple_form/components/pattern.rb +2 -2
  18. data/lib/simple_form/components.rb +1 -1
  19. data/lib/simple_form/error_notification.rb +2 -2
  20. data/lib/simple_form/form_builder.rb +154 -50
  21. data/lib/simple_form/form_builder.rb.orig +486 -0
  22. data/lib/simple_form/helpers.rb +1 -1
  23. data/lib/simple_form/inputs/base.rb +7 -10
  24. data/lib/simple_form/inputs/block_input.rb +1 -1
  25. data/lib/simple_form/inputs/boolean_input.rb +6 -5
  26. data/lib/simple_form/inputs/collection_input.rb +7 -7
  27. data/lib/simple_form/inputs/date_time_input.rb +1 -1
  28. data/lib/simple_form/inputs/numeric_input.rb +0 -6
  29. data/lib/simple_form/inputs/password_input.rb +0 -1
  30. data/lib/simple_form/inputs/string_input.rb +0 -1
  31. data/lib/simple_form/railtie.rb +7 -0
  32. data/lib/simple_form/tags.rb +62 -0
  33. data/lib/simple_form/version.rb +1 -1
  34. data/lib/simple_form/version.rb.orig +7 -0
  35. data/lib/simple_form/wrappers/builder.rb +5 -29
  36. data/lib/simple_form/wrappers/many.rb +1 -1
  37. data/lib/simple_form/wrappers/root.rb +1 -1
  38. data/lib/simple_form/wrappers.rb +1 -1
  39. data/lib/simple_form.rb +43 -47
  40. data/test/action_view_extensions/builder_test.rb +78 -99
  41. data/test/action_view_extensions/form_helper_test.rb +25 -16
  42. data/test/components/label_test.rb +46 -46
  43. data/test/form_builder/association_test.rb +47 -29
  44. data/test/form_builder/button_test.rb +4 -4
  45. data/test/form_builder/error_notification_test.rb +8 -8
  46. data/test/form_builder/error_test.rb +18 -65
  47. data/test/form_builder/general_test.rb +62 -63
  48. data/test/form_builder/hint_test.rb +23 -29
  49. data/test/form_builder/input_field_test.rb +29 -12
  50. data/test/form_builder/label_test.rb +7 -17
  51. data/test/form_builder/wrapper_test.rb +21 -21
  52. data/test/inputs/boolean_input_test.rb +24 -24
  53. data/test/inputs/collection_check_boxes_input_test.rb +66 -55
  54. data/test/inputs/collection_radio_buttons_input_test.rb +81 -79
  55. data/test/inputs/collection_select_input_test.rb +76 -51
  56. data/test/inputs/datetime_input_test.rb +17 -11
  57. data/test/inputs/disabled_test.rb +10 -10
  58. data/test/inputs/discovery_test.rb +4 -4
  59. data/test/inputs/file_input_test.rb +1 -1
  60. data/test/inputs/general_test.rb +28 -12
  61. data/test/inputs/grouped_collection_select_input_test.rb +33 -20
  62. data/test/inputs/hidden_input_test.rb +3 -2
  63. data/test/inputs/numeric_input_test.rb +3 -3
  64. data/test/inputs/priority_input_test.rb +9 -3
  65. data/test/inputs/readonly_test.rb +12 -12
  66. data/test/inputs/required_test.rb +5 -5
  67. data/test/inputs/string_input_test.rb +15 -25
  68. data/test/inputs/text_input_test.rb +1 -1
  69. data/test/support/misc_helpers.rb +46 -24
  70. data/test/support/mock_controller.rb +6 -6
  71. data/test/support/models.rb +77 -62
  72. data/test/test_helper.rb +17 -34
  73. metadata +39 -22
  74. data/lib/simple_form/core_ext/hash.rb +0 -16
@@ -0,0 +1,486 @@
1
+ <<<<<<< HEAD
2
+ require 'simple_form/core_ext/hash'
3
+ =======
4
+ require 'active_support/core_ext/object/deep_dup'
5
+ require 'simple_form/map_type'
6
+ >>>>>>> beeac4d... These modules don't need to be autoloaded
7
+
8
+ module SimpleForm
9
+ class FormBuilder < ActionView::Helpers::FormBuilder
10
+ attr_reader :template, :object_name, :object, :wrapper
11
+
12
+ # When action is create or update, we still should use new and edit
13
+ ACTIONS = {
14
+ :create => :new,
15
+ :update => :edit
16
+ }
17
+
18
+ extend MapType
19
+ include SimpleForm::Inputs
20
+
21
+ map_type :text, :to => SimpleForm::Inputs::TextInput
22
+ map_type :file, :to => SimpleForm::Inputs::FileInput
23
+ map_type :string, :email, :search, :tel, :url, :to => SimpleForm::Inputs::StringInput
24
+ map_type :password, :to => SimpleForm::Inputs::PasswordInput
25
+ map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput
26
+ map_type :range, :to => SimpleForm::Inputs::RangeInput
27
+ map_type :check_boxes, :to => SimpleForm::Inputs::CollectionCheckBoxesInput
28
+ map_type :radio_buttons, :to => SimpleForm::Inputs::CollectionRadioButtonsInput
29
+ map_type :select, :to => SimpleForm::Inputs::CollectionSelectInput
30
+ map_type :grouped_select, :to => SimpleForm::Inputs::GroupedCollectionSelectInput
31
+ map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
32
+ map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
33
+ map_type :boolean, :to => SimpleForm::Inputs::BooleanInput
34
+
35
+ def self.discovery_cache
36
+ @discovery_cache ||= {}
37
+ end
38
+
39
+ def initialize(*) #:nodoc:
40
+ super
41
+ @defaults = options[:defaults]
42
+ @wrapper = SimpleForm.wrapper(options[:wrapper] || SimpleForm.default_wrapper)
43
+ end
44
+
45
+ # Basic input helper, combines all components in the stack to generate
46
+ # input html based on options the user define and some guesses through
47
+ # database column information. By default a call to input will generate
48
+ # label + input + hint (when defined) + errors (when exists), and all can
49
+ # be configured inside a wrapper html.
50
+ #
51
+ # == Examples
52
+ #
53
+ # # Imagine @user has error "can't be blank" on name
54
+ # simple_form_for @user do |f|
55
+ # f.input :name, :hint => 'My hint'
56
+ # end
57
+ #
58
+ # This is the output html (only the input portion, not the form):
59
+ #
60
+ # <label class="string required" for="user_name">
61
+ # <abbr title="required">*</abbr> Super User Name!
62
+ # </label>
63
+ # <input class="string required" id="user_name" maxlength="100"
64
+ # name="user[name]" size="100" type="text" value="Carlos" />
65
+ # <span class="hint">My hint</span>
66
+ # <span class="error">can't be blank</span>
67
+ #
68
+ # Each database type will render a default input, based on some mappings and
69
+ # heuristic to determine which is the best option.
70
+ #
71
+ # You have some options for the input to enable/disable some functions:
72
+ #
73
+ # :as => allows you to define the input type you want, for instance you
74
+ # can use it to generate a text field for a date column.
75
+ #
76
+ # :required => defines whether this attribute is required or not. True
77
+ # by default.
78
+ #
79
+ # The fact SimpleForm is built in components allow the interface to be unified.
80
+ # So, for instance, if you need to disable :hint for a given input, you can pass
81
+ # :hint => false. The same works for :error, :label and :wrapper.
82
+ #
83
+ # Besides the html for any component can be changed. So, if you want to change
84
+ # the label html you just need to give a hash to :label_html. To configure the
85
+ # input html, supply :input_html instead and so on.
86
+ #
87
+ # == Options
88
+ #
89
+ # Some inputs, as datetime, time and select allow you to give extra options, like
90
+ # prompt and/or include blank. Such options are given in plainly:
91
+ #
92
+ # f.input :created_at, :include_blank => true
93
+ #
94
+ # == Collection
95
+ #
96
+ # When playing with collections (:radio_buttons, :check_boxes and :select
97
+ # inputs), you have three extra options:
98
+ #
99
+ # :collection => use to determine the collection to generate the radio or select
100
+ #
101
+ # :label_method => the method to apply on the array collection to get the label
102
+ #
103
+ # :value_method => the method to apply on the array collection to get the value
104
+ #
105
+ # == Priority
106
+ #
107
+ # Some inputs, as :time_zone and :country accepts a :priority option. If none is
108
+ # given SimpleForm.time_zone_priority and SimpleForm.country_priority are used respectively.
109
+ #
110
+ def input(attribute_name, options={}, &block)
111
+ options = @defaults.deep_dup.deep_merge(options) if @defaults
112
+ input = find_input(attribute_name, options, &block)
113
+
114
+ chosen =
115
+ if name = options[:wrapper] || find_wrapper_mapping(input.input_type)
116
+ name.respond_to?(:render) ? name : SimpleForm.wrapper(name)
117
+ else
118
+ wrapper
119
+ end
120
+
121
+ chosen.render input
122
+ end
123
+ alias :attribute :input
124
+
125
+ # Creates a input tag for the given attribute. All the given options
126
+ # are sent as :input_html.
127
+ #
128
+ # == Examples
129
+ #
130
+ # simple_form_for @user do |f|
131
+ # f.input_field :name
132
+ # end
133
+ #
134
+ # This is the output html (only the input portion, not the form):
135
+ #
136
+ # <input class="string required" id="user_name" maxlength="100"
137
+ # name="user[name]" size="100" type="text" value="Carlos" />
138
+ #
139
+ def input_field(attribute_name, options={})
140
+ options = options.dup
141
+ options[:input_html] = options.except(:as, :collection, :label_method, :value_method)
142
+ options = @defaults.deep_dup.deep_merge(options) if @defaults
143
+
144
+ SimpleForm::Wrappers::Root.new([:input], :wrapper => false).render find_input(attribute_name, options)
145
+ end
146
+
147
+ # Helper for dealing with association selects/radios, generating the
148
+ # collection automatically. It's just a wrapper to input, so all options
149
+ # supported in input are also supported by association. Some extra options
150
+ # can also be given:
151
+ #
152
+ # == Examples
153
+ #
154
+ # simple_form_for @user do |f|
155
+ # f.association :company # Company.all
156
+ # end
157
+ #
158
+ # f.association :company, :collection => Company.all(:order => 'name')
159
+ # # Same as using :order option, but overriding collection
160
+ #
161
+ # == Block
162
+ #
163
+ # When a block is given, association simple behaves as a proxy to
164
+ # simple_fields_for:
165
+ #
166
+ # f.association :company do |c|
167
+ # c.input :name
168
+ # c.input :type
169
+ # end
170
+ #
171
+ # From the options above, only :collection can also be supplied.
172
+ #
173
+ def association(association, options={}, &block)
174
+ options = options.dup
175
+
176
+ return simple_fields_for(*[association,
177
+ options.delete(:collection), options].compact, &block) if block_given?
178
+
179
+ raise ArgumentError, "Association cannot be used in forms not associated with an object" unless @object
180
+
181
+ reflection = find_association_reflection(association)
182
+ raise "Association #{association.inspect} not found" unless reflection
183
+
184
+ options[:as] ||= :select
185
+ options[:collection] ||= options.fetch(:collection) {
186
+ reflection.klass.all(reflection.options.slice(:conditions, :order))
187
+ }
188
+
189
+ attribute = case reflection.macro
190
+ when :belongs_to
191
+ (reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
192
+ when :has_one
193
+ raise ArgumentError, ":has_one associations are not supported by f.association"
194
+ else
195
+ if options[:as] == :select
196
+ html_options = options[:input_html] ||= {}
197
+ html_options[:size] ||= 5
198
+ html_options[:multiple] = true unless html_options.key?(:multiple)
199
+ end
200
+
201
+ # Force the association to be preloaded for performance.
202
+ if options[:preload] != false && object.respond_to?(association)
203
+ target = object.send(association)
204
+ target.to_a if target.respond_to?(:to_a)
205
+ end
206
+
207
+ :"#{reflection.name.to_s.singularize}_ids"
208
+ end
209
+
210
+ input(attribute, options.merge(:reflection => reflection))
211
+ end
212
+
213
+ # Creates a button:
214
+ #
215
+ # form_for @user do |f|
216
+ # f.button :submit
217
+ # end
218
+ #
219
+ # It just acts as a proxy to method name given. We also alias original Rails
220
+ # button implementation (3.2 forward (to delegate to the original when
221
+ # calling `f.button :button`.
222
+ #
223
+ # TODO: remove if condition when supporting only Rails 3.2 forward.
224
+ alias_method :button_button, :button if method_defined?(:button)
225
+ def button(type, *args, &block)
226
+ options = args.extract_options!.dup
227
+ options[:class] = [SimpleForm.button_class, options[:class]].compact
228
+ args << options
229
+ if respond_to?("#{type}_button")
230
+ send("#{type}_button", *args, &block)
231
+ else
232
+ send(type, *args, &block)
233
+ end
234
+ end
235
+
236
+ # Creates an error tag based on the given attribute, only when the attribute
237
+ # contains errors. All the given options are sent as :error_html.
238
+ #
239
+ # == Examples
240
+ #
241
+ # f.error :name
242
+ # f.error :name, :id => "cool_error"
243
+ #
244
+ def error(attribute_name, options={})
245
+ options = options.dup
246
+
247
+ options[:error_html] = options.except(:error_tag, :error_prefix, :error_method)
248
+ column = find_attribute_column(attribute_name)
249
+ input_type = default_input_type(attribute_name, column, options)
250
+ wrapper.find(:error).
251
+ render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
252
+ end
253
+
254
+ # Return the error but also considering its name. This is used
255
+ # when errors for a hidden field need to be shown.
256
+ #
257
+ # == Examples
258
+ #
259
+ # f.full_error :token #=> <span class="error">Token is invalid</span>
260
+ #
261
+ def full_error(attribute_name, options={})
262
+ options = options.dup
263
+
264
+ options[:error_prefix] ||= if object.class.respond_to?(:human_attribute_name)
265
+ object.class.human_attribute_name(attribute_name.to_s)
266
+ else
267
+ attribute_name.to_s.humanize
268
+ end
269
+
270
+ error(attribute_name, options)
271
+ end
272
+
273
+ # Creates a hint tag for the given attribute. Accepts a symbol indicating
274
+ # an attribute for I18n lookup or a string. All the given options are sent
275
+ # as :hint_html.
276
+ #
277
+ # == Examples
278
+ #
279
+ # f.hint :name # Do I18n lookup
280
+ # f.hint :name, :id => "cool_hint"
281
+ # f.hint "Don't forget to accept this"
282
+ #
283
+ def hint(attribute_name, options={})
284
+ options = options.dup
285
+
286
+ options[:hint_html] = options.except(:hint_tag, :hint)
287
+ if attribute_name.is_a?(String)
288
+ options[:hint] = attribute_name
289
+ attribute_name, column, input_type = nil, nil, nil
290
+ else
291
+ column = find_attribute_column(attribute_name)
292
+ input_type = default_input_type(attribute_name, column, options)
293
+ end
294
+
295
+ wrapper.find(:hint).
296
+ render(SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options))
297
+ end
298
+
299
+ # Creates a default label tag for the given attribute. You can give a label
300
+ # through the :label option or using i18n. All the given options are sent
301
+ # as :label_html.
302
+ #
303
+ # == Examples
304
+ #
305
+ # f.label :name # Do I18n lookup
306
+ # f.label :name, "Name" # Same behavior as Rails, do not add required tag
307
+ # f.label :name, :label => "Name" # Same as above, but adds required tag
308
+ #
309
+ # f.label :name, :required => false
310
+ # f.label :name, :id => "cool_label"
311
+ #
312
+ def label(attribute_name, *args)
313
+ return super if args.first.is_a?(String) || block_given?
314
+
315
+ options = args.extract_options!.dup
316
+ options[:label_html] = options.except(:label, :required, :as)
317
+
318
+ column = find_attribute_column(attribute_name)
319
+ input_type = default_input_type(attribute_name, column, options)
320
+ SimpleForm::Inputs::Base.new(self, attribute_name, column, input_type, options).label
321
+ end
322
+
323
+ # Creates an error notification message that only appears when the form object
324
+ # has some error. You can give a specific message with the :message option,
325
+ # otherwise it will look for a message using I18n. All other options given are
326
+ # passed straight as html options to the html tag.
327
+ #
328
+ # == Examples
329
+ #
330
+ # f.error_notification
331
+ # f.error_notification :message => 'Something went wrong'
332
+ # f.error_notification :id => 'user_error_message', :class => 'form_error'
333
+ #
334
+ def error_notification(options={})
335
+ SimpleForm::ErrorNotification.new(self, options).render
336
+ end
337
+
338
+ # Extract the model names from the object_name mess, ignoring numeric and
339
+ # explicit child indexes.
340
+ #
341
+ # Example:
342
+ #
343
+ # route[blocks_attributes][0][blocks_learning_object_attributes][1][foo_attributes]
344
+ # ["route", "blocks", "blocks_learning_object", "foo"]
345
+ #
346
+ def lookup_model_names
347
+ @lookup_model_names ||= begin
348
+ child_index = options[:child_index]
349
+ names = object_name.to_s.scan(/([a-zA-Z_]+)/).flatten
350
+ names.delete(child_index) if child_index
351
+ names.each { |name| name.gsub!('_attributes', '') }
352
+ names.freeze
353
+ end
354
+ end
355
+
356
+ # The action to be used in lookup.
357
+ def lookup_action
358
+ @lookup_action ||= begin
359
+ action = template.controller.action_name
360
+ return unless action
361
+ action = action.to_sym
362
+ ACTIONS[action] || action
363
+ end
364
+ end
365
+
366
+ private
367
+
368
+ # Find an input based on the attribute name.
369
+ def find_input(attribute_name, options={}, &block) #:nodoc:
370
+ column = find_attribute_column(attribute_name)
371
+ input_type = default_input_type(attribute_name, column, options)
372
+
373
+ if input_type == :radio
374
+ SimpleForm.deprecation_warn "Using `:as => :radio` as input type is " \
375
+ "deprecated, please change it to `:as => :radio_buttons`."
376
+ input_type = :radio_buttons
377
+ end
378
+
379
+ if block_given?
380
+ SimpleForm::Inputs::BlockInput.new(self, attribute_name, column, input_type, options, &block)
381
+ else
382
+ find_mapping(input_type).new(self, attribute_name, column, input_type, options)
383
+ end
384
+ end
385
+
386
+ # Attempt to guess the better input type given the defined options. By
387
+ # default alwayls fallback to the user :as option, or to a :select when a
388
+ # collection is given.
389
+ def default_input_type(attribute_name, column, options) #:nodoc:
390
+ return options[:as].to_sym if options[:as]
391
+ return :select if options[:collection]
392
+ custom_type = find_custom_type(attribute_name.to_s) and return custom_type
393
+
394
+ input_type = column.try(:type)
395
+ case input_type
396
+ when :timestamp
397
+ :datetime
398
+ when :string, nil
399
+ case attribute_name.to_s
400
+ when /password/ then :password
401
+ when /time_zone/ then :time_zone
402
+ when /country/ then :country
403
+ when /email/ then :email
404
+ when /phone/ then :tel
405
+ when /url/ then :url
406
+ else
407
+ file_method?(attribute_name) ? :file : (input_type || :string)
408
+ end
409
+ else
410
+ input_type
411
+ end
412
+ end
413
+
414
+ def find_custom_type(attribute_name) #:nodoc:
415
+ SimpleForm.input_mappings.find { |match, type|
416
+ attribute_name =~ match
417
+ }.try(:last) if SimpleForm.input_mappings
418
+ end
419
+
420
+ def file_method?(attribute_name) #:nodoc:
421
+ file = @object.send(attribute_name) if @object.respond_to?(attribute_name)
422
+ file && SimpleForm.file_methods.any? { |m| file.respond_to?(m) }
423
+ end
424
+
425
+ def find_attribute_column(attribute_name) #:nodoc:
426
+ if @object.respond_to?(:column_for_attribute)
427
+ @object.column_for_attribute(attribute_name)
428
+ end
429
+ end
430
+
431
+ def find_association_reflection(association) #:nodoc:
432
+ if @object.class.respond_to?(:reflect_on_association)
433
+ @object.class.reflect_on_association(association)
434
+ end
435
+ end
436
+
437
+ # Attempts to find a mapping. It follows the following rules:
438
+ #
439
+ # 1) It tries to find a registered mapping, if succeeds:
440
+ # a) Try to find an alternative with the same name in the Object scope
441
+ # b) Or use the found mapping
442
+ # 2) If not, fallbacks to #{input_type}Input
443
+ # 3) If not, fallbacks to SimpleForm::Inputs::#{input_type}Input
444
+ def find_mapping(input_type) #:nodoc:
445
+ discovery_cache[input_type] ||=
446
+ if mapping = self.class.mappings[input_type]
447
+ mapping_override(mapping) || mapping
448
+ else
449
+ camelized = "#{input_type.to_s.camelize}Input"
450
+ attempt_mapping(camelized, Object) || attempt_mapping(camelized, self.class) ||
451
+ raise("No input found for #{input_type}")
452
+ end
453
+ end
454
+
455
+ def find_wrapper_mapping(input_type) #:nodoc:
456
+ SimpleForm.wrapper_mappings && SimpleForm.wrapper_mappings[input_type]
457
+ end
458
+
459
+ # If cache_discovery is enabled, use the class level cache that persists
460
+ # between requests, otherwise use the instance one.
461
+ def discovery_cache #:nodoc:
462
+ if SimpleForm.cache_discovery
463
+ self.class.discovery_cache
464
+ else
465
+ @discovery_cache ||= {}
466
+ end
467
+ end
468
+
469
+ def mapping_override(klass) #:nodoc:
470
+ name = klass.name
471
+ if name =~ /^SimpleForm::Inputs/
472
+ attempt_mapping name.split("::").last, Object
473
+ end
474
+ end
475
+
476
+ def attempt_mapping(mapping, at) #:nodoc:
477
+ return if SimpleForm.inputs_discovery == false && at == Object
478
+
479
+ begin
480
+ at.const_get(mapping)
481
+ rescue NameError => e
482
+ raise if e.message !~ /#{mapping}$/
483
+ end
484
+ end
485
+ end
486
+ end
@@ -1,7 +1,7 @@
1
1
  module SimpleForm
2
2
  # Helpers are made of several helpers that cannot be turned on automatically.
3
3
  # For instance, disabled cannot be turned on automatically, it requires the
4
- # user to explicitly pass the option :disabled => true so it may work.
4
+ # user to explicitly pass the option disabled: true so it may work.
5
5
  module Helpers
6
6
  autoload :Autofocus, 'simple_form/helpers/autofocus'
7
7
  autoload :Disabled, 'simple_form/helpers/disabled'
@@ -1,11 +1,8 @@
1
1
  require 'simple_form/i18n_cache'
2
- require 'active_support/core_ext/string/output_safety'
3
2
 
4
3
  module SimpleForm
5
4
  module Inputs
6
5
  class Base
7
- include ERB::Util
8
-
9
6
  extend I18nCache
10
7
 
11
8
  include SimpleForm::Helpers::Autofocus
@@ -27,7 +24,7 @@ module SimpleForm
27
24
  attr_reader :attribute_name, :column, :input_type, :reflection,
28
25
  :options, :input_html_options, :input_html_classes, :html_classes
29
26
 
30
- delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, :to => :@builder
27
+ delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
31
28
 
32
29
  class_attribute :default_options
33
30
  self.default_options = {}
@@ -45,7 +42,7 @@ module SimpleForm
45
42
  end
46
43
 
47
44
  # Always enabled.
48
- enable :hint, :error
45
+ enable :hint
49
46
 
50
47
  # Usually disabled, needs to be enabled explicitly passing true as option.
51
48
  disable :maxlength, :placeholder, :pattern, :min_max
@@ -68,6 +65,10 @@ module SimpleForm
68
65
  @html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
69
66
 
70
67
  @input_html_classes = @html_classes.dup
68
+ if SimpleForm.input_class && !input_html_classes.empty?
69
+ input_html_classes << SimpleForm.input_class
70
+ end
71
+
71
72
  @input_html_options = html_options_for(:input, input_html_classes).tap do |o|
72
73
  o[:readonly] = true if has_readonly?
73
74
  o[:disabled] = true if has_disabled?
@@ -93,10 +94,6 @@ module SimpleForm
93
94
 
94
95
  private
95
96
 
96
- def add_size!
97
- input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
98
- end
99
-
100
97
  def limit
101
98
  if column
102
99
  decimal_or_float? ? decimal_limit : column_limit
@@ -182,7 +179,7 @@ module SimpleForm
182
179
  lookups << :"defaults.#{reflection_or_attribute_name}"
183
180
  lookups << default
184
181
 
185
- I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups).presence
182
+ I18n.t(lookups.shift, scope: :"simple_form.#{namespace}", default: lookups).presence
186
183
  end
187
184
  end
188
185
  end
@@ -11,4 +11,4 @@ module SimpleForm
11
11
  end
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -4,7 +4,7 @@ module SimpleForm
4
4
  def input
5
5
  if nested_boolean_style?
6
6
  build_hidden_field_for_checkbox +
7
- template.label_tag(nil, :class => "checkbox") {
7
+ template.label_tag(nil, class: "checkbox") {
8
8
  build_check_box_without_hidden_field + inline_label
9
9
  }
10
10
  else
@@ -35,7 +35,7 @@ module SimpleForm
35
35
  # reuse the method for nested boolean style, but with no unchecked value,
36
36
  # which won't generate the hidden checkbox. This is the default functionality
37
37
  # in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
38
- def build_check_box(unchecked_value = unchecked_value())
38
+ def build_check_box(unchecked_value = unchecked_value)
39
39
  @builder.check_box(attribute_name, input_html_options, checked_value, unchecked_value)
40
40
  end
41
41
 
@@ -50,9 +50,10 @@ module SimpleForm
50
50
  # we need the hidden field to be *outside* the label (otherwise it
51
51
  # generates invalid html - html5 only).
52
52
  def build_hidden_field_for_checkbox
53
- @builder.hidden_field(attribute_name, :value => unchecked_value, :id => nil,
54
- :disabled => input_html_options[:disabled],
55
- :name => input_html_options[:name])
53
+ options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
54
+ options[:name] = input_html_options[:name] if input_html_options.has_key?(:name)
55
+
56
+ @builder.hidden_field(attribute_name, options)
56
57
  end
57
58
 
58
59
  def inline_label
@@ -7,8 +7,8 @@ module SimpleForm
7
7
  # "simple_form.no" keys. See the example locale file.
8
8
  def self.boolean_collection
9
9
  i18n_cache :boolean_collection do
10
- [ [I18n.t(:"simple_form.yes", :default => 'Yes'), true],
11
- [I18n.t(:"simple_form.no", :default => 'No'), false] ]
10
+ [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
11
+ [I18n.t(:"simple_form.no", default: 'No'), false] ]
12
12
  end
13
13
  end
14
14
 
@@ -33,7 +33,7 @@ module SimpleForm
33
33
  end
34
34
 
35
35
  def has_required?
36
- super && (input_options[:include_blank] || input_options[:prompt] || multiple?)
36
+ super && (input_options[:include_blank] || multiple?)
37
37
  end
38
38
 
39
39
  # Check if :include_blank must be included by default.
@@ -66,14 +66,14 @@ module SimpleForm
66
66
  collection_translated = translate_collection if collection_classes == [Symbol]
67
67
 
68
68
  if collection_translated || collection_classes.include?(Array)
69
- { :label => :first, :value => :last }
69
+ { label: :first, value: :second }
70
70
  elsif collection_includes_basic_objects?(collection_classes)
71
- { :label => :to_s, :value => :to_s }
71
+ { label: :to_s, value: :to_s }
72
72
  else
73
73
  sample = collection.first || collection.last
74
74
 
75
- { :label => SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
76
- :value => SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
75
+ { label: SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
76
+ value: SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
77
77
  end
78
78
  end
79
79
 
@@ -11,7 +11,7 @@ module SimpleForm
11
11
  position = case input_type
12
12
  when :date, :datetime
13
13
  date_order = input_options[:order] || I18n.t('date.order')
14
- date_order.first
14
+ date_order.first.to_sym
15
15
  else
16
16
  :hour
17
17
  end
@@ -4,7 +4,6 @@ module SimpleForm
4
4
  enable :placeholder, :min_max
5
5
 
6
6
  def input
7
- add_size!
8
7
  input_html_classes.unshift("numeric")
9
8
  if html5?
10
9
  input_html_options[:type] ||= "number"
@@ -14,11 +13,6 @@ module SimpleForm
14
13
  end
15
14
 
16
15
  private
17
-
18
- # Rails adds the size attr by default, if the :size key does not exist.
19
- def add_size!
20
- input_html_options[:size] ||= nil
21
- end
22
16
  end
23
17
  end
24
18
  end
@@ -4,7 +4,6 @@ module SimpleForm
4
4
  enable :placeholder, :maxlength
5
5
 
6
6
  def input
7
- add_size!
8
7
  @builder.password_field(attribute_name, input_html_options)
9
8
  end
10
9
  end
@@ -9,7 +9,6 @@ module SimpleForm
9
9
  input_html_options[:type] ||= input_type if html5?
10
10
  end
11
11
 
12
- add_size!
13
12
  @builder.text_field(attribute_name, input_html_options)
14
13
  end
15
14
 
@@ -0,0 +1,7 @@
1
+ require 'rails/railtie'
2
+
3
+ module SimpleForm
4
+ class Railtie < Rails::Railtie
5
+ config.eager_load_namespaces << SimpleForm
6
+ end
7
+ end