simple_form 3.1.0 → 5.0.0

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.
Files changed (104) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +148 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +278 -68
  5. data/lib/generators/simple_form/install_generator.rb +1 -0
  6. data/lib/generators/simple_form/templates/README +3 -3
  7. data/lib/generators/simple_form/templates/_form.html.erb +2 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +2 -0
  9. data/lib/generators/simple_form/templates/_form.html.slim +1 -0
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +19 -9
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +367 -63
  12. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +23 -8
  13. data/lib/simple_form/action_view_extensions/builder.rb +1 -0
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +4 -1
  15. data/lib/simple_form/components/errors.rb +15 -2
  16. data/lib/simple_form/components/hints.rb +1 -0
  17. data/lib/simple_form/components/html5.rb +15 -4
  18. data/lib/simple_form/components/label_input.rb +2 -1
  19. data/lib/simple_form/components/labels.rb +12 -5
  20. data/lib/simple_form/components/maxlength.rb +8 -4
  21. data/lib/simple_form/components/min_max.rb +1 -0
  22. data/lib/simple_form/components/minlength.rb +38 -0
  23. data/lib/simple_form/components/pattern.rb +1 -0
  24. data/lib/simple_form/components/placeholders.rb +2 -1
  25. data/lib/simple_form/components/readonly.rb +1 -0
  26. data/lib/simple_form/components.rb +2 -0
  27. data/lib/simple_form/error_notification.rb +1 -0
  28. data/lib/simple_form/form_builder.rb +117 -35
  29. data/lib/simple_form/helpers/autofocus.rb +1 -0
  30. data/lib/simple_form/helpers/disabled.rb +1 -0
  31. data/lib/simple_form/helpers/readonly.rb +1 -0
  32. data/lib/simple_form/helpers/required.rb +1 -0
  33. data/lib/simple_form/helpers/validators.rb +2 -1
  34. data/lib/simple_form/helpers.rb +1 -0
  35. data/lib/simple_form/i18n_cache.rb +1 -0
  36. data/lib/simple_form/inputs/base.rb +36 -12
  37. data/lib/simple_form/inputs/block_input.rb +1 -0
  38. data/lib/simple_form/inputs/boolean_input.rb +14 -3
  39. data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
  40. data/lib/simple_form/inputs/collection_input.rb +7 -5
  41. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +3 -2
  42. data/lib/simple_form/inputs/collection_select_input.rb +1 -0
  43. data/lib/simple_form/inputs/color_input.rb +14 -0
  44. data/lib/simple_form/inputs/date_time_input.rb +13 -8
  45. data/lib/simple_form/inputs/file_input.rb +1 -0
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -0
  47. data/lib/simple_form/inputs/hidden_input.rb +1 -0
  48. data/lib/simple_form/inputs/numeric_input.rb +1 -0
  49. data/lib/simple_form/inputs/password_input.rb +2 -1
  50. data/lib/simple_form/inputs/priority_input.rb +1 -4
  51. data/lib/simple_form/inputs/range_input.rb +1 -0
  52. data/lib/simple_form/inputs/string_input.rb +3 -2
  53. data/lib/simple_form/inputs/text_input.rb +2 -1
  54. data/lib/simple_form/inputs.rb +2 -0
  55. data/lib/simple_form/map_type.rb +1 -0
  56. data/lib/simple_form/railtie.rb +1 -0
  57. data/lib/simple_form/tags.rb +7 -2
  58. data/lib/simple_form/version.rb +2 -1
  59. data/lib/simple_form/wrappers/builder.rb +1 -0
  60. data/lib/simple_form/wrappers/leaf.rb +2 -1
  61. data/lib/simple_form/wrappers/many.rb +1 -0
  62. data/lib/simple_form/wrappers/root.rb +2 -0
  63. data/lib/simple_form/wrappers/single.rb +2 -1
  64. data/lib/simple_form/wrappers.rb +1 -0
  65. data/lib/simple_form.rb +79 -14
  66. data/test/action_view_extensions/builder_test.rb +28 -9
  67. data/test/action_view_extensions/form_helper_test.rb +3 -2
  68. data/test/components/custom_components_test.rb +62 -0
  69. data/test/components/label_test.rb +33 -4
  70. data/test/form_builder/association_test.rb +33 -2
  71. data/test/form_builder/button_test.rb +1 -0
  72. data/test/form_builder/error_notification_test.rb +1 -0
  73. data/test/form_builder/error_test.rb +44 -9
  74. data/test/form_builder/general_test.rb +92 -20
  75. data/test/form_builder/hint_test.rb +6 -0
  76. data/test/form_builder/input_field_test.rb +76 -70
  77. data/test/form_builder/label_test.rb +27 -4
  78. data/test/form_builder/wrapper_test.rb +66 -14
  79. data/test/generators/simple_form_generator_test.rb +4 -3
  80. data/test/inputs/boolean_input_test.rb +35 -0
  81. data/test/inputs/collection_check_boxes_input_test.rb +38 -14
  82. data/test/inputs/collection_radio_buttons_input_test.rb +48 -24
  83. data/test/inputs/collection_select_input_test.rb +40 -39
  84. data/test/inputs/color_input_test.rb +10 -0
  85. data/test/inputs/datetime_input_test.rb +12 -8
  86. data/test/inputs/disabled_test.rb +14 -0
  87. data/test/inputs/discovery_test.rb +23 -0
  88. data/test/inputs/file_input_test.rb +1 -0
  89. data/test/inputs/general_test.rb +3 -2
  90. data/test/inputs/grouped_collection_select_input_test.rb +11 -10
  91. data/test/inputs/hidden_input_test.rb +1 -0
  92. data/test/inputs/numeric_input_test.rb +5 -1
  93. data/test/inputs/priority_input_test.rb +7 -6
  94. data/test/inputs/readonly_test.rb +1 -0
  95. data/test/inputs/required_test.rb +45 -0
  96. data/test/inputs/string_input_test.rb +18 -16
  97. data/test/inputs/text_input_test.rb +13 -0
  98. data/test/simple_form_test.rb +1 -0
  99. data/test/support/discovery_inputs.rb +8 -0
  100. data/test/support/misc_helpers.rb +44 -2
  101. data/test/support/mock_controller.rb +7 -1
  102. data/test/support/models.rb +105 -22
  103. data/test/test_helper.rb +14 -3
  104. metadata +42 -36
data/README.md CHANGED
@@ -32,13 +32,6 @@ Run the generator:
32
32
  rails generate simple_form:install
33
33
  ```
34
34
 
35
- Also, if you want to use the country select, you will need the
36
- [country_select gem](https://rubygems.org/gems/country_select), add it to your Gemfile:
37
-
38
- ```ruby
39
- gem 'country_select'
40
- ```
41
-
42
35
  ### Bootstrap
43
36
 
44
37
  **Simple Form** can be easily integrated to the [Bootstrap](http://getbootstrap.com/).
@@ -70,6 +63,22 @@ You will need to provide your own CSS styles for hints.
70
63
 
71
64
  Please see the [instructions on how to install Foundation in a Rails app](http://foundation.zurb.com/docs/applications.html).
72
65
 
66
+ ### Country Select
67
+
68
+ If you want to use the country select, you will need the
69
+ [country_select gem](https://rubygems.org/gems/country_select), add it to your Gemfile:
70
+
71
+ ```ruby
72
+ gem 'country_select'
73
+ ```
74
+
75
+ If you don't want to use the gem you can easily override this behaviour by mapping the
76
+ country inputs to something else, with a line like this in your `simple_form.rb` initializer:
77
+
78
+ ```ruby
79
+ config.input_mappings = { /country/ => :string }
80
+ ```
81
+
73
82
  ## Usage
74
83
 
75
84
  **Simple Form** was designed to be customized as you need to. Basically it's a stack of components that
@@ -91,12 +100,12 @@ To start using **Simple Form** you just have to use the helper it provides:
91
100
  This will generate an entire form with labels for user name and password as well, and render errors
92
101
  by default when you render the form with invalid data (after submitting for example).
93
102
 
94
- You can overwrite the default label by passing it to the input method. You can also add a hint or
95
- even a placeholder. For boolean inputs, you can add an inline label as well:
103
+ You can overwrite the default label by passing it to the input method. You can also add a hint,
104
+ an error, or even a placeholder. For boolean inputs, you can add an inline label as well:
96
105
 
97
106
  ```erb
98
107
  <%= simple_form_for @user do |f| %>
99
- <%= f.input :username, label: 'Your username please' %>
108
+ <%= f.input :username, label: 'Your username please', error: 'Username is mandatory, please specify one' %>
100
109
  <%= f.input :password, hint: 'No special characters.' %>
101
110
  <%= f.input :email, placeholder: 'user@domain.com' %>
102
111
  <%= f.input :remember_me, inline_label: 'Yes, remember me' %>
@@ -104,7 +113,7 @@ even a placeholder. For boolean inputs, you can add an inline label as well:
104
113
  <% end %>
105
114
  ```
106
115
 
107
- In some cases you may want to disable labels, hints or error. Or you may want to configure the html
116
+ In some cases you may want to disable labels, hints or errors. Or you may want to configure the html
108
117
  of any of them:
109
118
 
110
119
  ```erb
@@ -155,8 +164,9 @@ any html attribute to that wrapper as well using the `:wrapper_html` option, lik
155
164
 
156
165
  Required fields are marked with an * prepended to their labels.
157
166
 
158
- By default all inputs are required. When the form object has `presence` validations attached to its
159
- fields, **Simple Form** tells required and optional fields apart. For performance reasons, this
167
+ By default all inputs are required. When the form object includes `ActiveModel::Validations`
168
+ (which, for example, happens with Active Record models), fields are required only when there is `presence` validation.
169
+ Otherwise, **Simple Form** will mark fields as optional. For performance reasons, this
160
170
  detection is skipped on validations that make use of conditional options, such as `:if` and `:unless`.
161
171
 
162
172
  And of course, the `required` property of any input can be overwritten as needed:
@@ -204,7 +214,7 @@ the wrapper as well:
204
214
  <% end %>
205
215
  ```
206
216
 
207
- **Simple Form** accepts same options as their corresponding input type helper in Rails:
217
+ **Simple Form** inputs accept the same options as their corresponding input type helper in Rails:
208
218
 
209
219
  ```erb
210
220
  <%= simple_form_for @user do |f| %>
@@ -259,7 +269,6 @@ end
259
269
  ```
260
270
 
261
271
  For check boxes and radio buttons you can remove the label changing `boolean_style` from default value `:nested` to `:inline`.
262
- Also, `item_wrapper_tag` will not work when `boolean_style` is set to `:nested`.
263
272
 
264
273
  Example:
265
274
 
@@ -279,13 +288,6 @@ end
279
288
  </form>
280
289
  ```
281
290
 
282
- Produces:
283
-
284
- ```html
285
- <input class="string required" id="user_name" maxlength="100"
286
- name="user[name]" size="100" type="text" value="Carlos" />
287
- ```
288
-
289
291
  To view the actual RDocs for this, check them out here - http://rubydoc.info/github/plataformatec/simple_form/master/SimpleForm/FormBuilder:input_field
290
292
 
291
293
  ### Collections
@@ -315,12 +317,26 @@ Collection inputs accept two other options beside collections:
315
317
 
316
318
  Those methods are useful to manipulate the given collection. Both of these options also accept
317
319
  lambda/procs in case you want to calculate the value or label in a special way eg. custom
318
- translation. All other options given are sent straight to the underlying helper. For example, you
319
- can give prompt as:
320
+ translation. You can also define a `to_label` method on your model as **Simple Form** will search for
321
+ and use `:to_label` as a `:label_method` first if it is found.
322
+
323
+ By default, **Simple Form** will use the first item from an array as the label and the second one as the value.
324
+ If you want to change this behavior you must make it explicit, like this:
325
+
326
+ ```erb
327
+ <%= simple_form_for @user do |f| %>
328
+ <%= f.input :gender, as: :radio_buttons, collection: [['0', 'female'], ['1', 'male']], label_method: :second, value_method: :first %>
329
+ <% end %>
330
+ ```
331
+
332
+ All other options given are sent straight to the underlying helper. For example, you can give prompt as:
320
333
 
321
334
  ```ruby
322
- f.input :age, collection: 18..60, prompt: "Select your age"
335
+ f.input :age, collection: 18..60, prompt: "Select your age", selected: 21
323
336
  ```
337
+ Extra options are passed into helper [`collection_select`](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select).
338
+
339
+ You may also find it useful to explicitly pass a value to the optional `:selected`, especially if passing a collection of nested objects.
324
340
 
325
341
  It is also possible to create grouped collection selects, that will use the html *optgroup* tags, like this:
326
342
 
@@ -404,7 +420,7 @@ The association helper just invokes `input` under the hood, so all options avail
404
420
  the collection by hand, all together with the prompt:
405
421
 
406
422
  ```ruby
407
- f.association :company, collection: Company.active.all(order: 'name'), prompt: "Choose a Company"
423
+ f.association :company, collection: Company.active.order(:name), prompt: "Choose a Company"
408
424
  ```
409
425
 
410
426
  In case you want to declare different labels and values:
@@ -435,6 +451,16 @@ The button method also accepts optional parameters, that are delegated to the un
435
451
  <%= f.button :submit, "Custom Button Text", class: "my-button" %>
436
452
  ```
437
453
 
454
+ To create a `<button>` element, use the following syntax:
455
+
456
+ ```erb
457
+ <%= f.button :button, "Custom Button Text" %>
458
+
459
+ <%= f.button :button do %>
460
+ Custom Button Text
461
+ <% end %>
462
+ ```
463
+
438
464
  ### Wrapping Rails Form Helpers
439
465
 
440
466
  Say you wanted to use a rails form helper but still wrap it in **Simple Form** goodness? You can, by
@@ -474,7 +500,7 @@ Creates a collection of radio inputs with labels associated (same API as `collec
474
500
 
475
501
  ```ruby
476
502
  form_for @user do |f|
477
- f.collection_radio_buttons :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
503
+ f.collection_radio_buttons :options, [[true, 'Yes'], [false, 'No']], :first, :last
478
504
  end
479
505
  ```
480
506
 
@@ -491,7 +517,7 @@ Creates a collection of checkboxes with labels associated (same API as `collecti
491
517
 
492
518
  ```ruby
493
519
  form_for @user do |f|
494
- f.collection_check_boxes :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
520
+ f.collection_check_boxes :options, [[true, 'Yes'], [false, 'No']], :first, :last
495
521
  end
496
522
  ```
497
523
 
@@ -512,37 +538,47 @@ form_for @user do |f|
512
538
  end
513
539
  ```
514
540
 
541
+ To add a CSS class to the label item, you can use the `item_label_class` option:
542
+
543
+ ```ruby
544
+ f.collection_check_boxes :role_ids, Role.all, :id, :name, item_label_class: 'my-custom-class'
545
+ ```
546
+
515
547
  ## Available input types and defaults for each column type
516
548
 
517
549
  The following table shows the html element you will get for each attribute
518
550
  according to its database definition. These defaults can be changed by
519
551
  specifying the helper method in the column `Mapping` as the `as:` option.
520
552
 
521
- Mapping | Generated HTML Element | Database Column Type
522
- --------------- |:-------------------------------------|:--------------------
523
- `boolean` | `input[type=checkbox]` | `boolean`
524
- `string` | `input[type=text]` | `string`
525
- `email` | `input[type=email]` | `string` with `name =~ /email/`
526
- `url` | `input[type=url]` | `string` with `name =~ /url/`
527
- `tel` | `input[type=tel]` | `string` with `name =~ /phone/`
528
- `password` | `input[type=password]` | `string` with `name =~ /password/`
529
- `search` | `input[type=search]` | -
530
- `uuid` | `input[type=text]` | `uuid`
531
- `text` | `textarea` | `text`
532
- `file` | `input[type=file]` | `string` responding to file methods
533
- `hidden` | `input[type=hidden]` | -
534
- `integer` | `input[type=number]` | `integer`
535
- `float` | `input[type=number]` | `float`
536
- `decimal` | `input[type=number]` | `decimal`
537
- `range` | `input[type=range]` | -
538
- `datetime` | `datetime select` | `datetime/timestamp`
539
- `date` | `date select` | `date`
540
- `time` | `time select` | `time`
541
- `select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations
542
- `radio_buttons` | collection of `input[type=radio]` | `belongs_to` associations
543
- `check_boxes` | collection of `input[type=checkbox]` | `has_many`/`has_and_belongs_to_many` associations
544
- `country` | `select` (countries as options) | `string` with `name =~ /country/`
545
- `time_zone` | `select` (timezones as options) | `string` with `name =~ /time_zone/`
553
+ Mapping | Generated HTML Element | Database Column Type
554
+ --------------- |--------------------------------------|---------------------
555
+ `boolean` | `input[type=checkbox]` | `boolean`
556
+ `string` | `input[type=text]` | `string`
557
+ `citext` | `input[type=text]` | `citext`
558
+ `email` | `input[type=email]` | `string` with `name =~ /email/`
559
+ `url` | `input[type=url]` | `string` with `name =~ /url/`
560
+ `tel` | `input[type=tel]` | `string` with `name =~ /phone/`
561
+ `password` | `input[type=password]` | `string` with `name =~ /password/`
562
+ `search` | `input[type=search]` | -
563
+ `uuid` | `input[type=text]` | `uuid`
564
+ `text` | `textarea` | `text`
565
+ `hstore` | `textarea` | `hstore`
566
+ `json` | `textarea` | `json`
567
+ `jsonb` | `textarea` | `jsonb`
568
+ `file` | `input[type=file]` | `string` responding to file methods
569
+ `hidden` | `input[type=hidden]` | -
570
+ `integer` | `input[type=number]` | `integer`
571
+ `float` | `input[type=number]` | `float`
572
+ `decimal` | `input[type=number]` | `decimal`
573
+ `range` | `input[type=range]` | -
574
+ `datetime` | `datetime select` | `datetime/timestamp`
575
+ `date` | `date select` | `date`
576
+ `time` | `time select` | `time`
577
+ `select` | `select` | `belongs_to`/`has_many`/`has_and_belongs_to_many` associations
578
+ `radio_buttons` | collection of `input[type=radio]` | `belongs_to` associations
579
+ `check_boxes` | collection of `input[type=checkbox]` | `has_many`/`has_and_belongs_to_many` associations
580
+ `country` | `select` (countries as options) | `string` with `name =~ /country/`
581
+ `time_zone` | `select` (timezones as options) | `string` with `name =~ /time_zone/`
546
582
 
547
583
  ## Custom inputs
548
584
 
@@ -660,7 +696,7 @@ en:
660
696
  age: 'Rather not say'
661
697
  prompts:
662
698
  user:
663
- gender: 'Select your gender'
699
+ role: 'Select your role'
664
700
  ```
665
701
 
666
702
  And your forms will use this information to render the components for you.
@@ -715,16 +751,16 @@ For `:prompt` and `:include_blank` the I18n lookup is optional and to enable it
715
751
  `:translate` as value.
716
752
 
717
753
  ```ruby
718
- f.input :gender, prompt: :translate
754
+ f.input :role, prompt: :translate
719
755
  ```
720
756
 
721
757
  **Simple Form** also has support for translating options in collection helpers. For instance, given a
722
- User with a `:gender` attribute, you might want to create a select box showing translated labels
723
- that would post either `male` or `female` as value. With **Simple Form** you could create an input
758
+ User with a `:role` attribute, you might want to create a select box showing translated labels
759
+ that would post either `:admin` or `:editor` as value. With **Simple Form** you could create an input
724
760
  like this:
725
761
 
726
762
  ```ruby
727
- f.input :gender, collection: [:male, :female]
763
+ f.input :role, collection: [:admin, :editor]
728
764
  ```
729
765
 
730
766
  And **Simple Form** will try a lookup like this in your locale file, to find the right labels to show:
@@ -734,9 +770,9 @@ en:
734
770
  simple_form:
735
771
  options:
736
772
  user:
737
- gender:
738
- male: 'Male'
739
- female: 'Female'
773
+ role:
774
+ admin: 'Administrator'
775
+ editor: 'Editor'
740
776
  ```
741
777
 
742
778
  You can also use the `defaults` key as you would do with labels, hints and placeholders. It is
@@ -789,6 +825,22 @@ object itself. Thus, similarly, if a form for an `Admin::User` object is defined
789
825
  `simple_form_for @admin_user, as: :some_user`, **Simple Form** will look for translations
790
826
  under `some_user` instead of `admin_user`.
791
827
 
828
+ When translating `simple_fields_for` attributes be sure to use the same name you pass to it, e.g. `simple_fields_for :posts` should be placed under `posts` not `post`:
829
+
830
+ ```yaml
831
+ en:
832
+ simple_form:
833
+ labels:
834
+ posts:
835
+ title: 'Post title'
836
+ hints:
837
+ posts:
838
+ title: 'A good title'
839
+ placeholders:
840
+ posts:
841
+ title: 'Once upon a time...'
842
+ ```
843
+
792
844
  ## Configuration
793
845
 
794
846
  **Simple Form** has several configuration options. You can read and change them in the initializer
@@ -803,7 +855,8 @@ The syntax looks like this:
803
855
 
804
856
  ```ruby
805
857
  config.wrappers tag: :div, class: :input,
806
- error_class: :field_with_errors do |b|
858
+ error_class: :field_with_errors,
859
+ valid_class: :field_without_errors do |b|
807
860
 
808
861
  # Form extensions
809
862
  b.use :html5
@@ -852,11 +905,12 @@ You can customize _Form components_ passing options to them:
852
905
 
853
906
  ```ruby
854
907
  config.wrappers do |b|
855
- b.use :label_input, class: 'label-input-class'
908
+ b.use :label_input, class: 'label-input-class', error_class: 'is-invalid', valid_class: 'is-valid'
856
909
  end
857
910
  ```
858
911
 
859
- This you set the input and label class to `'label-input-class'`.
912
+ This sets the input and label classes to `'label-input-class'` and will set the class `'is-invalid'`
913
+ if the input has errors and `'is-valid'` if the input is valid.
860
914
 
861
915
  If you want to customize the custom _Form components_ on demand you can give it a name like this:
862
916
 
@@ -935,6 +989,92 @@ when the content is present.
935
989
  end
936
990
  ```
937
991
 
992
+ ## Custom Components
993
+
994
+ When you use custom wrappers, you might also be looking for a way to add custom components to your
995
+ wrapper. The default components are:
996
+
997
+ ```ruby
998
+ :label # The <label> tag alone
999
+ :input # The <input> tag alone
1000
+ :label_input # The <label> and the <input> tags
1001
+ :hint # The hint for the input
1002
+ :error # The error for the input
1003
+ ```
1004
+
1005
+ A custom component might be interesting for you if your views look something like this:
1006
+
1007
+ ```erb
1008
+ <%= simple_form_for @blog do |f| %>
1009
+ <div class="row">
1010
+ <div class="span1 number">
1011
+ 1
1012
+ </div>
1013
+ <div class="span8">
1014
+ <%= f.input :title %>
1015
+ </div>
1016
+ </div>
1017
+ <div class="row">
1018
+ <div class="span1 number">
1019
+ 2
1020
+ </div>
1021
+ <div class="span8">
1022
+ <%= f.input :body, as: :text %>
1023
+ </div>
1024
+ </div>
1025
+ <% end %>
1026
+ ```
1027
+
1028
+ A cleaner method to create your views would be:
1029
+
1030
+ ```erb
1031
+ <%= simple_form_for @blog, wrapper: :with_numbers do |f| %>
1032
+ <%= f.input :title, number: 1 %>
1033
+ <%= f.input :body, as: :text, number: 2 %>
1034
+ <% end %>
1035
+ ```
1036
+
1037
+ To use the number option on the input, first, tells to Simple Form the place where the components
1038
+ will be:
1039
+
1040
+ ``` ruby
1041
+ # config/initializers/simple_form.rb
1042
+ Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
1043
+ ```
1044
+
1045
+ Create a new component within the path specified above:
1046
+
1047
+ ```ruby
1048
+ # lib/components/numbers_component.rb
1049
+ module NumbersComponent
1050
+ # To avoid deprecation warning, you need to make the wrapper_options explicit
1051
+ # even when they won't be used.
1052
+ def number(wrapper_options = nil)
1053
+ @number ||= begin
1054
+ options[:number].to_s.html_safe if options[:number].present?
1055
+ end
1056
+ end
1057
+ end
1058
+
1059
+ SimpleForm.include_component(NumbersComponent)
1060
+ ```
1061
+
1062
+ Finally, add a new wrapper to the config/initializers/simple_form.rb file:
1063
+
1064
+ ```ruby
1065
+ config.wrappers :with_numbers, tag: 'div', class: 'row', error_class: 'error' do |b|
1066
+ b.use :html5
1067
+ b.use :number, wrap_with: { tag: 'div', class: 'span1 number'}
1068
+ b.wrapper tag: 'div', class: 'span8' do |ba|
1069
+ ba.use :placeholder
1070
+ ba.use :label
1071
+ ba.use :input
1072
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
1073
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
1074
+ end
1075
+ end
1076
+ ```
1077
+
938
1078
  ## HTML 5 Notice
939
1079
 
940
1080
  By default, **Simple Form** will generate input field types and attributes that are supported in HTML5,
@@ -947,8 +1087,8 @@ required attribute to force a value into an input and will prevent form submissi
947
1087
  Depending on the design of the application this may or may not be desired. In many cases it can
948
1088
  break existing UI's.
949
1089
 
950
- It is possible to disable all HTML 5 extensions in **Simple Form** removing the `html5` component
951
- from the wrapper used to render the inputs.
1090
+ It is possible to disable all HTML 5 extensions in **Simple Form** by removing the `html5`
1091
+ component from the wrapper used to render the inputs.
952
1092
 
953
1093
  For example, change:
954
1094
 
@@ -1000,6 +1140,76 @@ by passing the html5 option:
1000
1140
  <%= f.input :expires_at, as: :date, html5: true %>
1001
1141
  ```
1002
1142
 
1143
+ ### Using non Active Record objects
1144
+
1145
+ There are few ways to build forms with objects that don't inherit from Active Record, as
1146
+ follows:
1147
+
1148
+ You can include the module `ActiveModel::Model`.
1149
+
1150
+ ```ruby
1151
+ class User
1152
+ include ActiveModel::Model
1153
+
1154
+ attr_accessor :id, :name
1155
+ end
1156
+ ```
1157
+
1158
+ If you are using Presenters or Decorators that inherit from `SimpleDelegator` you can delegate
1159
+ it to the model.
1160
+
1161
+ ```ruby
1162
+ class UserPresenter < SimpleDelegator
1163
+ # Without that, Simple Form will consider the user model as the object.
1164
+ def to_model
1165
+ self
1166
+ end
1167
+ end
1168
+ ```
1169
+
1170
+ You can define all methods required by the helpers.
1171
+
1172
+ ```ruby
1173
+ class User
1174
+ extend ActiveModel::Naming
1175
+
1176
+ attr_accessor :id, :name
1177
+
1178
+ def to_model
1179
+ self
1180
+ end
1181
+
1182
+ def to_key
1183
+ id
1184
+ end
1185
+
1186
+ def persisted?
1187
+ false
1188
+ end
1189
+ end
1190
+ ```
1191
+
1192
+ If your object doesn't implement those methods, you must make explicit it when you are
1193
+ building the form
1194
+
1195
+ ```ruby
1196
+ class User
1197
+ attr_accessor :id, :name
1198
+
1199
+ # The only method required to use the f.submit helper.
1200
+ def persisted?
1201
+ false
1202
+ end
1203
+ end
1204
+ ```
1205
+
1206
+ ```erb
1207
+ <%= simple_form_for(@user, as: :user, method: :post, url: users_path) do |f| %>
1208
+ <%= f.input :name %>
1209
+ <%= f.submit 'New user' %>
1210
+ <% end %>
1211
+ ```
1212
+
1003
1213
  ## Information
1004
1214
 
1005
1215
  ### Google Group
@@ -1018,7 +1228,7 @@ http://rubydoc.info/github/plataformatec/simple_form/master/frames
1018
1228
  ### Bug reports
1019
1229
 
1020
1230
  If you discover any bugs, feel free to create an issue on GitHub. Please add as much information as
1021
- possible to help us fixing the possible bug. We also encourage you to help even more by forking and
1231
+ possible to help us in fixing the potential bug. We also encourage you to help even more by forking and
1022
1232
  sending us a pull request.
1023
1233
 
1024
1234
  https://github.com/plataformatec/simple_form/issues
@@ -1037,7 +1247,7 @@ https://github.com/plataformatec/simple_form/issues
1037
1247
 
1038
1248
  ## License
1039
1249
 
1040
- MIT License. Copyright 2009-2014 Plataformatec. http://plataformatec.com.br
1250
+ MIT License. Copyright 2009-2019 Plataformatec. http://plataformatec.com.br
1041
1251
 
1042
1252
  You are not granted rights or licenses to the trademarks of the Plataformatec, including without
1043
1253
  limitation the Simple Form name or logo.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Generators
3
4
  class InstallGenerator < Rails::Generators::Base
@@ -3,9 +3,9 @@
3
3
  Be sure to have a copy of the Bootstrap stylesheet available on your
4
4
  application, you can get it on http://getbootstrap.com/.
5
5
 
6
- Inside your views, use the 'simple_form_for' with one of the Bootstrap form
7
- classes, '.form-horizontal' or '.form-inline', as the following:
6
+ Inside your views, use the 'simple_form_for' with the Bootstrap form
7
+ class, '.form-inline', as the following:
8
8
 
9
- = simple_form_for(@user, html: { class: 'form-horizontal' }) do |form|
9
+ = simple_form_for(@user, html: { class: 'form-inline' }) do |form|
10
10
 
11
11
  ===============================================================================
@@ -1,5 +1,7 @@
1
+ <%# frozen_string_literal: true %>
1
2
  <%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
2
3
  <%%= f.error_notification %>
4
+ <%%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
3
5
 
4
6
  <div class="form-inputs">
5
7
  <%- attributes.each do |attribute| -%>
@@ -1,5 +1,7 @@
1
+ -# frozen_string_literal: true
1
2
  = simple_form_for(@<%= singular_table_name %>) do |f|
2
3
  = f.error_notification
4
+ = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
3
5
 
4
6
  .form-inputs
5
7
  <%- attributes.each do |attribute| -%>
@@ -1,5 +1,6 @@
1
1
  = simple_form_for(@<%= singular_table_name %>) do |f|
2
2
  = f.error_notification
3
+ = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
3
4
 
4
5
  .form-inputs
5
6
  <%- attributes.each do |attribute| -%>
@@ -1,3 +1,11 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Uncomment this and change the path if necessary to include your own
4
+ # components.
5
+ # See https://github.com/plataformatec/simple_form#custom-components to know
6
+ # more about custom components.
7
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8
+ #
1
9
  # Use this setup block to configure all options available in SimpleForm.
2
10
  SimpleForm.setup do |config|
3
11
  # Wrappers are used by the form builder to generate a
@@ -6,7 +14,7 @@ SimpleForm.setup do |config|
6
14
  # stack. The options given below are used to wrap the
7
15
  # whole input.
8
16
  config.wrappers :default, class: :input,
9
- hint_class: :field_with_hint, error_class: :field_with_errors do |b|
17
+ hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
10
18
  ## Extensions enabled by default
11
19
  # Any of these extensions can be disabled for a
12
20
  # given input by passing: `f.input EXTENSION_NAME => false`.
@@ -28,8 +36,12 @@ SimpleForm.setup do |config|
28
36
  # extensions by default, you can change `b.optional` to `b.use`.
29
37
 
30
38
  # Calculates maxlength from length validations for string inputs
39
+ # and/or database column lengths
31
40
  b.optional :maxlength
32
41
 
42
+ # Calculate minlength from length validations for string inputs
43
+ b.optional :minlength
44
+
33
45
  # Calculates pattern from format validations for string inputs
34
46
  b.optional :pattern
35
47
 
@@ -40,6 +52,7 @@ SimpleForm.setup do |config|
40
52
  b.optional :readonly
41
53
 
42
54
  ## Inputs
55
+ # b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
43
56
  b.use :label_input
44
57
  b.use :hint, wrap_with: { tag: :span, class: :hint }
45
58
  b.use :error, wrap_with: { tag: :span, class: :error }
@@ -74,9 +87,6 @@ SimpleForm.setup do |config|
74
87
  # CSS class to add for error notification helper.
75
88
  config.error_notification_class = 'error_notification'
76
89
 
77
- # ID to add for error notification helper.
78
- # config.error_notification_id = nil
79
-
80
90
  # Series of attempts to detect a default label method for collection.
81
91
  # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
82
92
 
@@ -90,8 +100,7 @@ SimpleForm.setup do |config|
90
100
  # config.collection_wrapper_class = nil
91
101
 
92
102
  # You can wrap each item in a collection of radio/check boxes with a tag,
93
- # defaulting to :span. Please note that when using :boolean_style = :nested,
94
- # SimpleForm will force this option to be a label.
103
+ # defaulting to :span.
95
104
  # config.item_wrapper_tag = :span
96
105
 
97
106
  # You can define a class to use in all item wrappers. Defaulting to none.
@@ -120,9 +129,6 @@ SimpleForm.setup do |config|
120
129
  # change this configuration to true.
121
130
  config.browser_validations = false
122
131
 
123
- # Collection of methods to detect if a file type was given.
124
- # config.file_methods = [ :mounted_as, :file?, :public_filename ]
125
-
126
132
  # Custom mappings for input types. This should be a hash containing a regexp
127
133
  # to match as key, and the input type that will be used when the field name
128
134
  # matches the regexp as value.
@@ -163,4 +169,8 @@ SimpleForm.setup do |config|
163
169
 
164
170
  # Defines which i18n scope will be used in Simple Form.
165
171
  # config.i18n_scope = 'simple_form'
172
+
173
+ # Defines validation classes to the input_field. By default it's nil.
174
+ # config.input_field_valid_class = 'is-valid'
175
+ # config.input_field_error_class = 'is-invalid'
166
176
  end