mega-safe-tool 0.0.1

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 (171) hide show
  1. checksums.yaml +7 -0
  2. data/formtastic-6.0.0/Appraisals +23 -0
  3. data/formtastic-6.0.0/CONTRIBUTING.md +27 -0
  4. data/formtastic-6.0.0/Gemfile +8 -0
  5. data/formtastic-6.0.0/MIT-LICENSE +20 -0
  6. data/formtastic-6.0.0/README.md +600 -0
  7. data/formtastic-6.0.0/RELEASE_PROCESS +7 -0
  8. data/formtastic-6.0.0/Rakefile +54 -0
  9. data/formtastic-6.0.0/bin/appraisal +8 -0
  10. data/formtastic-6.0.0/formtastic.gemspec +45 -0
  11. data/formtastic-6.0.0/gemfiles/rails_72.gemfile +9 -0
  12. data/formtastic-6.0.0/gemfiles/rails_80.gemfile +9 -0
  13. data/formtastic-6.0.0/gemfiles/rails_81.gemfile +9 -0
  14. data/formtastic-6.0.0/gemfiles/rails_edge.gemfile +9 -0
  15. data/formtastic-6.0.0/lib/formtastic/action_class_finder.rb +19 -0
  16. data/formtastic-6.0.0/lib/formtastic/actions/base.rb +157 -0
  17. data/formtastic-6.0.0/lib/formtastic/actions/button_action.rb +68 -0
  18. data/formtastic-6.0.0/lib/formtastic/actions/buttonish.rb +18 -0
  19. data/formtastic-6.0.0/lib/formtastic/actions/input_action.rb +71 -0
  20. data/formtastic-6.0.0/lib/formtastic/actions/link_action.rb +89 -0
  21. data/formtastic-6.0.0/lib/formtastic/actions.rb +15 -0
  22. data/formtastic-6.0.0/lib/formtastic/deprecation.rb +6 -0
  23. data/formtastic-6.0.0/lib/formtastic/form_builder.rb +109 -0
  24. data/formtastic-6.0.0/lib/formtastic/helpers/action_helper.rb +115 -0
  25. data/formtastic-6.0.0/lib/formtastic/helpers/actions_helper.rb +169 -0
  26. data/formtastic-6.0.0/lib/formtastic/helpers/enum.rb +14 -0
  27. data/formtastic-6.0.0/lib/formtastic/helpers/errors_helper.rb +139 -0
  28. data/formtastic-6.0.0/lib/formtastic/helpers/fieldset_wrapper.rb +85 -0
  29. data/formtastic-6.0.0/lib/formtastic/helpers/file_column_detection.rb +17 -0
  30. data/formtastic-6.0.0/lib/formtastic/helpers/form_helper.rb +204 -0
  31. data/formtastic-6.0.0/lib/formtastic/helpers/input_helper.rb +349 -0
  32. data/formtastic-6.0.0/lib/formtastic/helpers/inputs_helper.rb +421 -0
  33. data/formtastic-6.0.0/lib/formtastic/helpers/reflection.rb +38 -0
  34. data/formtastic-6.0.0/lib/formtastic/helpers.rb +16 -0
  35. data/formtastic-6.0.0/lib/formtastic/html_attributes.rb +33 -0
  36. data/formtastic-6.0.0/lib/formtastic/i18n.rb +33 -0
  37. data/formtastic-6.0.0/lib/formtastic/input_class_finder.rb +19 -0
  38. data/formtastic-6.0.0/lib/formtastic/inputs/base/aria.rb +26 -0
  39. data/formtastic-6.0.0/lib/formtastic/inputs/base/associations.rb +32 -0
  40. data/formtastic-6.0.0/lib/formtastic/inputs/base/choices.rb +109 -0
  41. data/formtastic-6.0.0/lib/formtastic/inputs/base/collections.rb +158 -0
  42. data/formtastic-6.0.0/lib/formtastic/inputs/base/database.rb +20 -0
  43. data/formtastic-6.0.0/lib/formtastic/inputs/base/datetime_pickerish.rb +86 -0
  44. data/formtastic-6.0.0/lib/formtastic/inputs/base/errors.rb +59 -0
  45. data/formtastic-6.0.0/lib/formtastic/inputs/base/fileish.rb +24 -0
  46. data/formtastic-6.0.0/lib/formtastic/inputs/base/hints.rb +32 -0
  47. data/formtastic-6.0.0/lib/formtastic/inputs/base/html.rb +54 -0
  48. data/formtastic-6.0.0/lib/formtastic/inputs/base/labelling.rb +53 -0
  49. data/formtastic-6.0.0/lib/formtastic/inputs/base/naming.rb +43 -0
  50. data/formtastic-6.0.0/lib/formtastic/inputs/base/numeric.rb +51 -0
  51. data/formtastic-6.0.0/lib/formtastic/inputs/base/options.rb +18 -0
  52. data/formtastic-6.0.0/lib/formtastic/inputs/base/placeholder.rb +18 -0
  53. data/formtastic-6.0.0/lib/formtastic/inputs/base/stringish.rb +39 -0
  54. data/formtastic-6.0.0/lib/formtastic/inputs/base/timeish.rb +246 -0
  55. data/formtastic-6.0.0/lib/formtastic/inputs/base/validations.rb +250 -0
  56. data/formtastic-6.0.0/lib/formtastic/inputs/base/wrapping.rb +51 -0
  57. data/formtastic-6.0.0/lib/formtastic/inputs/base.rb +79 -0
  58. data/formtastic-6.0.0/lib/formtastic/inputs/boolean_input.rb +119 -0
  59. data/formtastic-6.0.0/lib/formtastic/inputs/check_boxes_input.rb +198 -0
  60. data/formtastic-6.0.0/lib/formtastic/inputs/color_input.rb +42 -0
  61. data/formtastic-6.0.0/lib/formtastic/inputs/country_input.rb +90 -0
  62. data/formtastic-6.0.0/lib/formtastic/inputs/datalist_input.rb +42 -0
  63. data/formtastic-6.0.0/lib/formtastic/inputs/date_picker_input.rb +94 -0
  64. data/formtastic-6.0.0/lib/formtastic/inputs/date_select_input.rb +35 -0
  65. data/formtastic-6.0.0/lib/formtastic/inputs/datetime_picker_input.rb +104 -0
  66. data/formtastic-6.0.0/lib/formtastic/inputs/datetime_select_input.rb +13 -0
  67. data/formtastic-6.0.0/lib/formtastic/inputs/email_input.rb +42 -0
  68. data/formtastic-6.0.0/lib/formtastic/inputs/file_input.rb +43 -0
  69. data/formtastic-6.0.0/lib/formtastic/inputs/hidden_input.rb +63 -0
  70. data/formtastic-6.0.0/lib/formtastic/inputs/number_input.rb +89 -0
  71. data/formtastic-6.0.0/lib/formtastic/inputs/password_input.rb +42 -0
  72. data/formtastic-6.0.0/lib/formtastic/inputs/phone_input.rb +43 -0
  73. data/formtastic-6.0.0/lib/formtastic/inputs/radio_input.rb +164 -0
  74. data/formtastic-6.0.0/lib/formtastic/inputs/range_input.rb +96 -0
  75. data/formtastic-6.0.0/lib/formtastic/inputs/search_input.rb +42 -0
  76. data/formtastic-6.0.0/lib/formtastic/inputs/select_input.rb +236 -0
  77. data/formtastic-6.0.0/lib/formtastic/inputs/string_input.rb +37 -0
  78. data/formtastic-6.0.0/lib/formtastic/inputs/text_input.rb +49 -0
  79. data/formtastic-6.0.0/lib/formtastic/inputs/time_picker_input.rb +100 -0
  80. data/formtastic-6.0.0/lib/formtastic/inputs/time_select_input.rb +39 -0
  81. data/formtastic-6.0.0/lib/formtastic/inputs/time_zone_input.rb +59 -0
  82. data/formtastic-6.0.0/lib/formtastic/inputs/url_input.rb +42 -0
  83. data/formtastic-6.0.0/lib/formtastic/inputs.rb +43 -0
  84. data/formtastic-6.0.0/lib/formtastic/localized_string.rb +18 -0
  85. data/formtastic-6.0.0/lib/formtastic/localizer.rb +151 -0
  86. data/formtastic-6.0.0/lib/formtastic/namespaced_class_finder.rb +98 -0
  87. data/formtastic-6.0.0/lib/formtastic/version.rb +4 -0
  88. data/formtastic-6.0.0/lib/formtastic.rb +48 -0
  89. data/formtastic-6.0.0/lib/generators/formtastic/form/form_generator.rb +111 -0
  90. data/formtastic-6.0.0/lib/generators/formtastic/input/input_generator.rb +47 -0
  91. data/formtastic-6.0.0/lib/generators/formtastic/install/install_generator.rb +23 -0
  92. data/formtastic-6.0.0/lib/generators/formtastic/stylesheets/stylesheets_generator.rb +15 -0
  93. data/formtastic-6.0.0/lib/generators/templates/_form.html.erb +11 -0
  94. data/formtastic-6.0.0/lib/generators/templates/_form.html.haml +8 -0
  95. data/formtastic-6.0.0/lib/generators/templates/_form.html.slim +8 -0
  96. data/formtastic-6.0.0/lib/generators/templates/formtastic.css +289 -0
  97. data/formtastic-6.0.0/lib/generators/templates/formtastic.rb +118 -0
  98. data/formtastic-6.0.0/lib/generators/templates/input.rb +19 -0
  99. data/formtastic-6.0.0/lib/locale/en.yml +10 -0
  100. data/formtastic-6.0.0/sample/basic_inputs.html +224 -0
  101. data/formtastic-6.0.0/sample/config.ru +69 -0
  102. data/formtastic-6.0.0/sample/index.html +14 -0
  103. data/formtastic-6.0.0/script/integration-template.rb +76 -0
  104. data/formtastic-6.0.0/script/integration.sh +32 -0
  105. data/formtastic-6.0.0/spec/action_class_finder_spec.rb +12 -0
  106. data/formtastic-6.0.0/spec/actions/button_action_spec.rb +63 -0
  107. data/formtastic-6.0.0/spec/actions/generic_action_spec.rb +521 -0
  108. data/formtastic-6.0.0/spec/actions/input_action_spec.rb +59 -0
  109. data/formtastic-6.0.0/spec/actions/link_action_spec.rb +92 -0
  110. data/formtastic-6.0.0/spec/builder/custom_builder_spec.rb +132 -0
  111. data/formtastic-6.0.0/spec/builder/error_proc_spec.rb +27 -0
  112. data/formtastic-6.0.0/spec/builder/semantic_fields_for_spec.rb +213 -0
  113. data/formtastic-6.0.0/spec/fast_spec_helper.rb +12 -0
  114. data/formtastic-6.0.0/spec/generators/formtastic/form/form_generator_spec.rb +132 -0
  115. data/formtastic-6.0.0/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
  116. data/formtastic-6.0.0/spec/generators/formtastic/install/install_generator_spec.rb +48 -0
  117. data/formtastic-6.0.0/spec/generators/formtastic/stylesheets/stylesheets_generator_spec.rb +22 -0
  118. data/formtastic-6.0.0/spec/helpers/action_helper_spec.rb +338 -0
  119. data/formtastic-6.0.0/spec/helpers/actions_helper_spec.rb +143 -0
  120. data/formtastic-6.0.0/spec/helpers/form_helper_spec.rb +224 -0
  121. data/formtastic-6.0.0/spec/helpers/input_helper_spec.rb +991 -0
  122. data/formtastic-6.0.0/spec/helpers/inputs_helper_spec.rb +669 -0
  123. data/formtastic-6.0.0/spec/helpers/reflection_helper_spec.rb +32 -0
  124. data/formtastic-6.0.0/spec/helpers/semantic_errors_helper_spec.rb +220 -0
  125. data/formtastic-6.0.0/spec/i18n_spec.rb +210 -0
  126. data/formtastic-6.0.0/spec/input_class_finder_spec.rb +10 -0
  127. data/formtastic-6.0.0/spec/inputs/base/collections_spec.rb +119 -0
  128. data/formtastic-6.0.0/spec/inputs/base/validations_spec.rb +481 -0
  129. data/formtastic-6.0.0/spec/inputs/boolean_input_spec.rb +254 -0
  130. data/formtastic-6.0.0/spec/inputs/check_boxes_input_spec.rb +547 -0
  131. data/formtastic-6.0.0/spec/inputs/color_input_spec.rb +85 -0
  132. data/formtastic-6.0.0/spec/inputs/country_input_spec.rb +133 -0
  133. data/formtastic-6.0.0/spec/inputs/custom_input_spec.rb +51 -0
  134. data/formtastic-6.0.0/spec/inputs/datalist_input_spec.rb +61 -0
  135. data/formtastic-6.0.0/spec/inputs/date_picker_input_spec.rb +449 -0
  136. data/formtastic-6.0.0/spec/inputs/date_select_input_spec.rb +249 -0
  137. data/formtastic-6.0.0/spec/inputs/datetime_picker_input_spec.rb +490 -0
  138. data/formtastic-6.0.0/spec/inputs/datetime_select_input_spec.rb +209 -0
  139. data/formtastic-6.0.0/spec/inputs/email_input_spec.rb +85 -0
  140. data/formtastic-6.0.0/spec/inputs/file_input_spec.rb +89 -0
  141. data/formtastic-6.0.0/spec/inputs/hidden_input_spec.rb +135 -0
  142. data/formtastic-6.0.0/spec/inputs/include_blank_spec.rb +78 -0
  143. data/formtastic-6.0.0/spec/inputs/label_spec.rb +181 -0
  144. data/formtastic-6.0.0/spec/inputs/number_input_spec.rb +815 -0
  145. data/formtastic-6.0.0/spec/inputs/password_input_spec.rb +99 -0
  146. data/formtastic-6.0.0/spec/inputs/phone_input_spec.rb +85 -0
  147. data/formtastic-6.0.0/spec/inputs/placeholder_spec.rb +71 -0
  148. data/formtastic-6.0.0/spec/inputs/radio_input_spec.rb +326 -0
  149. data/formtastic-6.0.0/spec/inputs/range_input_spec.rb +505 -0
  150. data/formtastic-6.0.0/spec/inputs/readonly_spec.rb +50 -0
  151. data/formtastic-6.0.0/spec/inputs/search_input_spec.rb +84 -0
  152. data/formtastic-6.0.0/spec/inputs/select_input_spec.rb +661 -0
  153. data/formtastic-6.0.0/spec/inputs/string_input_spec.rb +326 -0
  154. data/formtastic-6.0.0/spec/inputs/text_input_spec.rb +187 -0
  155. data/formtastic-6.0.0/spec/inputs/time_picker_input_spec.rb +455 -0
  156. data/formtastic-6.0.0/spec/inputs/time_select_input_spec.rb +261 -0
  157. data/formtastic-6.0.0/spec/inputs/time_zone_input_spec.rb +143 -0
  158. data/formtastic-6.0.0/spec/inputs/url_input_spec.rb +85 -0
  159. data/formtastic-6.0.0/spec/inputs/with_options_spec.rb +43 -0
  160. data/formtastic-6.0.0/spec/localizer_spec.rb +130 -0
  161. data/formtastic-6.0.0/spec/namespaced_class_finder_spec.rb +90 -0
  162. data/formtastic-6.0.0/spec/schema.rb +22 -0
  163. data/formtastic-6.0.0/spec/spec.opts +2 -0
  164. data/formtastic-6.0.0/spec/spec_helper.rb +466 -0
  165. data/formtastic-6.0.0/spec/support/custom_macros.rb +570 -0
  166. data/formtastic-6.0.0/spec/support/deprecation.rb +7 -0
  167. data/formtastic-6.0.0/spec/support/shared_examples.rb +13 -0
  168. data/formtastic-6.0.0/spec/support/specialized_class_finder_shared_example.rb +27 -0
  169. data/formtastic-6.0.0/spec/support/test_environment.rb +46 -0
  170. data/mega-safe-tool.gemspec +11 -0
  171. metadata +209 -0
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ module ActionHelper
5
+ # Renders an action for the form (such as a subit/reset button, or a cancel link).
6
+ #
7
+ # Each action is wrapped in an `<li class="action">` tag with other classes added based on the
8
+ # type of action being rendered, and is intended to be rendered inside a {#buttons}
9
+ # block which wraps the button in a `fieldset` and `ol`.
10
+ #
11
+ # The textual value of the label can be changed from the default through the `:label`
12
+ # argument or through i18n.
13
+ #
14
+ # If using i18n, you'll need to provide the following translations:
15
+ #
16
+ # en:
17
+ # formtastic:
18
+ # actions:
19
+ # create: "Create new %{model}"
20
+ # update: "Save %{model}"
21
+ # cancel: "Cancel"
22
+ # reset: "Reset form"
23
+ # submit: "Submit"
24
+ #
25
+ # For forms with an object present, the `update` key will be used if calling `persisted?` on
26
+ # the object returns true (saving changes to a record), otherwise the `create` key will be
27
+ # used. The `submit` key is used as a fallback when there is no object or we cannot determine
28
+ # if `create` or `update` is appropriate.
29
+ #
30
+ # @example Basic usage
31
+ # # form
32
+ # <%= semantic_form_for @post do |f| %>
33
+ # ...
34
+ # <%= f.actions do %>
35
+ # <%= f.action :submit %>
36
+ # <%= f.action :reset %>
37
+ # <%= f.action :cancel %>
38
+ # <% end %>
39
+ # <% end %>
40
+ #
41
+ # # output
42
+ # <form ...>
43
+ # ...
44
+ # <fieldset class="buttons">
45
+ # <ol>
46
+ # <li class="action input_action">
47
+ # <input name="commit" type="submit" value="Create Post">
48
+ # </li>
49
+ # <li class="action input_action">
50
+ # <input name="commit" type="reset" value="Reset Post">
51
+ # </li>
52
+ # <li class="action link_action">
53
+ # <a href="/posts">Cancel Post</a>
54
+ # </li>
55
+ # </ol>
56
+ # </fieldset>
57
+ # </form>
58
+ #
59
+ # @example Set the value through the `:label` option
60
+ # <%= f.action :submit, :label => "Go" %>
61
+ #
62
+ # @example Pass HTML attributes down to the tag inside the wrapper
63
+ # <%= f.action :submit, :button_html => { :class => 'pretty', :accesskey => 'g', :disable_with => "Wait..." } %>
64
+ #
65
+ # @example Pass HTML attributes down to the `<li>` wrapper
66
+ # <%= f.action :submit, :wrapper_html => { :class => 'special', :id => 'whatever' } %>
67
+ #
68
+ # @option *args :label [String, Symbol]
69
+ # Override the label text with a String or a symbold for an i18n translation key
70
+ #
71
+ # @option *args :button_html [Hash]
72
+ # Override or add to the HTML attributes to be passed down to the `<input>` tag
73
+ #
74
+ # @option *args :wrapper_html [Hash]
75
+ # Override or add to the HTML attributes to be passed down to the wrapping `<li>` tag
76
+ #
77
+ # @todo document i18n keys
78
+ def action(method, options = {})
79
+ options = options.dup # Allow options to be shared without being tainted by Formtastic
80
+ options[:as] ||= default_action_type(method, options)
81
+
82
+ klass = namespaced_action_class(options[:as])
83
+
84
+ klass.new(self, template, @object, @object_name, method, options).to_html
85
+ end
86
+
87
+ protected
88
+
89
+ def default_action_type(method, options = {}) # @private
90
+ case method
91
+ when :submit then :input
92
+ when :reset then :input
93
+ when :cancel then :link
94
+ else method
95
+ end
96
+ end
97
+
98
+ # Takes the `:as` option and attempts to return the corresponding action
99
+ # class. In the case of `:as => :awesome` it will first attempt to find a
100
+ # top level `AwesomeAction` class (to allow the application to subclass
101
+ # and modify to suit), falling back to `Formtastic::Actions::AwesomeAction`.
102
+ #
103
+ # Custom action namespaces to look into can be configured via the
104
+ # {Formtastic::FormBuilder.action_namespaces} configuration setting.
105
+ # @see Helpers::InputHelper#namespaced_input_class
106
+ # @see Formtastic::ActionClassFinder
107
+ def namespaced_action_class(as)
108
+ @action_class_finder ||= action_class_finder.new(self)
109
+ @action_class_finder.find(as)
110
+ rescue Formtastic::ActionClassFinder::NotFoundError => e
111
+ raise Formtastic::UnknownActionError, "Unable to find action #{e.message}"
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ # ActionsHelper encapsulates the responsibilities of the {#actions} DSL for acting on
5
+ # (submitting, cancelling, resetting) forms.
6
+ #
7
+ # {#actions} is a block helper used to wrap the form's actions (buttons, links) in a
8
+ # `<fieldset>` and `<ol>`, with each item in the list containing the markup representing a
9
+ # single action.
10
+ #
11
+ # <%= semantic_form_for @post do |f| %>
12
+ # ...
13
+ # <%= f.actions do %>
14
+ # <%= f.action :submit
15
+ # <%= f.action :cancel
16
+ # <% end %>
17
+ # <% end %>
18
+ #
19
+ # The HTML output will be something like:
20
+ #
21
+ # <form class="formtastic" method="post" action="...">
22
+ # ...
23
+ # <fieldset class="actions">
24
+ # <ol>
25
+ # <li class="action input_action">
26
+ # <input type="submit" name="commit" value="Create Post">
27
+ # </li>
28
+ # <li class="action input_action">
29
+ # <a href="/posts">Cancel Post</a>
30
+ # </li>
31
+ # </ol>
32
+ # </fieldset>
33
+ # </form>
34
+ #
35
+ # It's important to note that the `semantic_form_for` and {#actions} blocks wrap the
36
+ # standard Rails `form_for` helper and form builder, so you have full access to every standard
37
+ # Rails form helper, with any HTML markup and ERB syntax, allowing you to "break free" from
38
+ # Formtastic when it doesn't suit to create your own buttons, links and actions:
39
+ #
40
+ # <%= semantic_form_for @post do |f| %>
41
+ # ...
42
+ # <%= f.actions do %>
43
+ # <li class="save">
44
+ # <%= f.submit "Save" %>
45
+ # <li>
46
+ # <li class="cancel-link">
47
+ # Or <%= link_to "Cancel", posts_url %>
48
+ # <li>
49
+ # <% end %>
50
+ # <% end %>
51
+ #
52
+ # There are many other syntax variations and arguments to customize your form. See the
53
+ # full documentation of {#actions} and {#action} for details.
54
+ module ActionsHelper
55
+
56
+ include Formtastic::Helpers::FieldsetWrapper
57
+
58
+ # Creates a fieldset and ol tag wrapping for use around a set of buttons. It can be
59
+ # called either with a block (in which you can do the usual Rails form stuff, HTML, ERB, etc),
60
+ # or with a list of named actions. These two examples are functionally equivalent:
61
+ #
62
+ # # With a block:
63
+ # <% semantic_form_for @post do |f| %>
64
+ # ...
65
+ # <% f.actions do %>
66
+ # <%= f.action :submit %>
67
+ # <%= f.action :cancel %>
68
+ # <% end %>
69
+ # <% end %>
70
+ #
71
+ # # With a list of fields:
72
+ # <% semantic_form_for @post do |f| %>
73
+ # <%= f.actions :submit, :cancel %>
74
+ # <% end %>
75
+ #
76
+ # # Output:
77
+ # <form ...>
78
+ # <fieldset class="buttons">
79
+ # <ol>
80
+ # <li class="action input_action">
81
+ # <input type="submit" ...>
82
+ # </li>
83
+ # <li class="action link_action">
84
+ # <a href="...">...</a>
85
+ # </li>
86
+ # </ol>
87
+ # </fieldset>
88
+ # </form>
89
+ #
90
+ # All options except `:name` and `:title` are passed down to the fieldset as HTML
91
+ # attributes (`id`, `class`, `style`...). If provided, the `:name` or `:title` option is
92
+ # passed into a `<legend>` inside the `<fieldset>` to name the set of buttons.
93
+ #
94
+ # @example Quickly add button(s) to the form, accepting all default values, options and behaviors
95
+ # <% semantic_form_for @post do |f| %>
96
+ # ...
97
+ # <%= f.actions %>
98
+ # <% end %>
99
+ #
100
+ # @example Specify which named buttons you want, accepting all default values, options and behaviors
101
+ # <% semantic_form_for @post do |f| %>
102
+ # ...
103
+ # <%= f.actions :commit %>
104
+ # <% end %>
105
+ #
106
+ # @example Specify which named buttons you want, and name the fieldset
107
+ # <% semantic_form_for @post do |f| %>
108
+ # ...
109
+ # <%= f.actions :commit, :name => "Actions" %>
110
+ # or
111
+ # <%= f.actions :commit, :label => "Actions" %>
112
+ # <% end %>
113
+ #
114
+ # @example Get full control over the action options
115
+ # <% semantic_form_for @post do |f| %>
116
+ # ...
117
+ # <%= f.actions do %>
118
+ # <%= f.action :label => "Go", :button_html => { :class => "pretty" :disable_with => "Wait..." }, :wrapper_html => { ... }
119
+ # <% end %>
120
+ # <% end %>
121
+ #
122
+ # @example Make your own actions with standard Rails helpers or HTML
123
+ # <% semantic_form_for @post do |f| %>
124
+ # <%= f.actions do %>
125
+ # <li>
126
+ # ...
127
+ # </li>
128
+ # <% end %>
129
+ # <% end %>
130
+ #
131
+ # @example Add HTML attributes to the fieldset
132
+ # <% semantic_form_for @post do |f| %>
133
+ # ...
134
+ # <%= f.actions :commit, :style => "border:1px;" %>
135
+ # or
136
+ # <%= f.actions :style => "border:1px;" do %>
137
+ # ...
138
+ # <% end %>
139
+ # <% end %>
140
+ #
141
+ # @option *args :label [String, Symbol]
142
+ # Optionally specify text for the legend of the fieldset
143
+ #
144
+ # @option *args :name [String, Symbol]
145
+ # Optionally specify text for the legend of the fieldset (alias for `:label`)
146
+ #
147
+ # @todo document i18n keys
148
+ def actions(*args, &block)
149
+ html_options = args.extract_options!
150
+ html_options[:class] ||= "actions"
151
+
152
+ if block_given?
153
+ field_set_and_list_wrapping(html_options, &block)
154
+ else
155
+ args = default_actions if args.empty?
156
+ contents = args.map { |action_name| action(action_name) }
157
+ field_set_and_list_wrapping(html_options, contents)
158
+ end
159
+ end
160
+
161
+ protected
162
+
163
+ def default_actions
164
+ [:submit]
165
+ end
166
+
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ # @private
5
+ module Enum
6
+ # Returns the enum (if defined) for the given method
7
+ def enum_for(method) # @private
8
+ if @object.respond_to?(:defined_enums)
9
+ @object.defined_enums[method.to_s]
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ module ErrorsHelper
5
+ include Formtastic::Helpers::FileColumnDetection
6
+ include Formtastic::Helpers::Reflection
7
+ include Formtastic::LocalizedString
8
+
9
+ INLINE_ERROR_TYPES = [:sentence, :list, :first]
10
+
11
+ # Generates an unordered list of error messages on the base object and optionally for a given
12
+ # set of named attribute. This is idea for rendering a block of error messages at the top of
13
+ # the form for hidden/special/virtual attributes (the Paperclip Rails plugin does this), or
14
+ # errors on the base model.
15
+ #
16
+ # A hash can be used as the last set of arguments to pass HTML attributes to the `<ul>`
17
+ # wrapper.
18
+ #
19
+ # # in config/initializers/formtastic.rb
20
+ # Setting `Formtastic::FormBuilder.semantic_errors_link_to_inputs = true`
21
+ # will render attribute errors as links to the corresponding errored inputs.
22
+ #
23
+ # @example A list of errors on the base model
24
+ # <%= semantic_form_for ... %>
25
+ # <%= f.semantic_errors %>
26
+ # ...
27
+ # <% end %>
28
+ #
29
+ # @example A list of errors on the base and named attributes
30
+ # <%= semantic_form_for ... %>
31
+ # <%= f.semantic_errors :something_special %>
32
+ # ...
33
+ # <% end %>
34
+ #
35
+ # @example A list of errors on the base model, with custom HTML attributes
36
+ # <%= semantic_form_for ... %>
37
+ # <%= f.semantic_errors :class => "awesome" %>
38
+ # ...
39
+ # <% end %>
40
+ #
41
+ # @example A list of errors on the base model and named attributes, with custom HTML attributes
42
+ # <%= semantic_form_for ... %>
43
+ # <%= f.semantic_errors :something_special, :something_else, :class => "awesome", :onclick => "Awesome();" %>
44
+ # ...
45
+ # <% end %>
46
+ def semantic_errors(*args)
47
+ html_options = args.extract_options!
48
+ html_options[:class] ||= "errors"
49
+
50
+ if Formtastic::FormBuilder.semantic_errors_link_to_inputs
51
+ attribute_error_hash = semantic_error_hash_from_attributes(args)
52
+ return nil if @object.errors[:base].blank? && attribute_error_hash.blank?
53
+
54
+ template.content_tag(:ul, html_options) do
55
+ (
56
+ @object.errors[:base].map { |base_error| template.content_tag(:li, base_error) } <<
57
+ attribute_error_hash.map { |attribute, error_message|
58
+ template.content_tag(:li) do
59
+ template.content_tag(:a, href: "##{object_name}_#{attribute}") do
60
+ error_message
61
+ end
62
+ end
63
+ }
64
+ ).join.html_safe
65
+ end
66
+ else
67
+ full_errors = @object.errors[:base]
68
+ full_errors += semantic_error_list_from_attributes(args)
69
+ return nil if full_errors.blank?
70
+
71
+ template.content_tag(:ul, html_options) do
72
+ full_errors.map { |error| template.content_tag(:li, error) }.join.html_safe
73
+ end
74
+ end
75
+ end
76
+
77
+ protected
78
+
79
+ def error_keys(method, options)
80
+ @methods_for_error ||= {}
81
+ @methods_for_error[method] ||= begin
82
+ methods_for_error = [method.to_sym]
83
+ methods_for_error << file_metadata_suffixes.map{|suffix| "#{method}_#{suffix}".to_sym} if is_file?(method, options)
84
+ methods_for_error << [association_primary_key_for_method(method)] if [:belongs_to, :has_many].include? association_macro_for_method(method)
85
+ methods_for_error.flatten.compact.uniq
86
+ end
87
+ end
88
+
89
+ def has_errors?(method, options)
90
+ methods_for_error = error_keys(method,options)
91
+ @object && @object.respond_to?(:errors) && methods_for_error.any?{|error| !@object.errors[error].blank?}
92
+ end
93
+
94
+ def render_inline_errors?
95
+ @object && @object.respond_to?(:errors) && Formtastic::FormBuilder::INLINE_ERROR_TYPES.include?(inline_errors)
96
+ end
97
+
98
+ def semantic_error_list_from_attributes(*args)
99
+ attribute_errors = []
100
+ args = args.flatten
101
+ args.each do |attribute|
102
+ next if attribute == :base
103
+
104
+ full_message = error_message_for_attribute(attribute)
105
+
106
+ attribute_errors << full_message unless full_message.blank?
107
+ end
108
+
109
+ attribute_errors
110
+ end
111
+
112
+ # returns { 'attribute': 'error_message_for_attribute' }
113
+ def semantic_error_hash_from_attributes(*args)
114
+ attribute_error_hash = {}
115
+ args = args.flatten
116
+ args.each do |attribute|
117
+ next if attribute == :base
118
+
119
+ full_message = error_message_for_attribute(attribute)
120
+
121
+ attribute_error_hash[attribute] = full_message unless full_message.blank?
122
+ end
123
+
124
+ attribute_error_hash
125
+ end
126
+
127
+ # Returns "Attribute error_message_sentence" localized, humanized
128
+ def error_message_for_attribute(attribute)
129
+ attribute_string = localized_string(attribute, attribute.to_sym, :label) || humanized_attribute_name(attribute)
130
+ error_message = @object.errors[attribute.to_sym]&.to_sentence
131
+
132
+ return nil if error_message.blank?
133
+
134
+ full_message = [attribute_string, error_message].join(" ")
135
+ full_message
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ # @private
5
+ module FieldsetWrapper
6
+
7
+ protected
8
+
9
+ # Generates a fieldset and wraps the content in an ordered list. When working
10
+ # with nested attributes, it allows %i as interpolation option in :name. So you can do:
11
+ #
12
+ # f.inputs :name => 'Task #%i', :for => :tasks
13
+ #
14
+ # or the shorter equivalent:
15
+ #
16
+ # f.inputs 'Task #%i', :for => :tasks
17
+ #
18
+ # And it will generate a fieldset for each task with legend 'Task #1', 'Task #2',
19
+ # 'Task #3' and so on.
20
+ #
21
+ # Note: Special case for the inline inputs (non-block):
22
+ # f.inputs "My little legend", :title, :body, :author # Explicit legend string => "My little legend"
23
+ # f.inputs :my_little_legend, :title, :body, :author # Localized (118n) legend with I18n key => I18n.t(:my_little_legend, ...)
24
+ # f.inputs :title, :body, :author # First argument is a column => (no legend)
25
+ def field_set_and_list_wrapping(*args, &block) # @private
26
+ contents = args[-1].is_a?(::Hash) ? '' : args.pop.flatten
27
+ html_options = args.extract_options!
28
+
29
+ if block_given?
30
+ contents = if template.respond_to?(:is_haml?) && template.is_haml?
31
+ template.capture_haml(&block)
32
+ else
33
+ template.capture(&block)
34
+ end
35
+ end
36
+
37
+ # Work-around for empty contents block
38
+ contents ||= ""
39
+
40
+ # Ruby 1.9: String#to_s behavior changed, need to make an explicit join.
41
+ contents = contents.join if contents.respond_to?(:join)
42
+
43
+ legend = field_set_legend(html_options)
44
+ fieldset = template.content_tag(:fieldset,
45
+ legend.html_safe << template.content_tag(:ol, contents.html_safe),
46
+ html_options.except(:builder, :parent, :name)
47
+ )
48
+
49
+ fieldset
50
+ end
51
+
52
+ def field_set_legend(html_options)
53
+ legend = (html_options[:name] || '').to_s
54
+ # only applying if String includes '%i' avoids argument error when $DEBUG is true
55
+ legend %= parent_child_index(html_options[:parent]) if html_options[:parent] && legend.include?('%i')
56
+ legend = template.content_tag(:legend, template.content_tag(:span, legend.html_safe)) unless legend.blank?
57
+ legend
58
+ end
59
+
60
+ # Gets the nested_child_index value from the parent builder. It returns a hash with each
61
+ # association that the parent builds.
62
+ def parent_child_index(parent) # @private
63
+ # Could be {"post[authors_attributes]"=>0} or { :authors => 0 }
64
+ duck = parent[:builder].instance_variable_get('@nested_child_index')
65
+
66
+ # Could be symbol for the association, or a model (or an array of either, I think? TODO)
67
+ child = parent[:for]
68
+ # Pull a symbol or model out of Array (TODO: check if there's an Array)
69
+ child = child.first if child.respond_to?(:first)
70
+ # If it's an object, get a symbol from the class name
71
+ child = child.class.name.underscore.to_sym unless child.is_a?(Symbol)
72
+
73
+ key = "#{parent[:builder].object_name}[#{child}_attributes]"
74
+
75
+ # TODO: One of the tests produces a scenario where duck is "0" and the test looks for a "1"
76
+ # in the legend, so if we have a number, return it with a +1 until we can verify this scenario.
77
+ return duck + 1 if duck.is_a?(Integer)
78
+
79
+ # First try to extract key from duck Hash, then try child
80
+ (duck[key] || duck[child]).to_i + 1
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Helpers
4
+ # @private
5
+ module FileColumnDetection
6
+
7
+ def is_file?(method, options = {})
8
+ @files ||= {}
9
+ @files[method] ||= (options[:as].present? && options[:as] == :file) || begin
10
+ file = @object.send(method) if @object && @object.respond_to?(method)
11
+ file && file_methods.any?{|m| file.respond_to?(m)}
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end