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.
- checksums.yaml +7 -0
- data/formtastic-6.0.0/Appraisals +23 -0
- data/formtastic-6.0.0/CONTRIBUTING.md +27 -0
- data/formtastic-6.0.0/Gemfile +8 -0
- data/formtastic-6.0.0/MIT-LICENSE +20 -0
- data/formtastic-6.0.0/README.md +600 -0
- data/formtastic-6.0.0/RELEASE_PROCESS +7 -0
- data/formtastic-6.0.0/Rakefile +54 -0
- data/formtastic-6.0.0/bin/appraisal +8 -0
- data/formtastic-6.0.0/formtastic.gemspec +45 -0
- data/formtastic-6.0.0/gemfiles/rails_72.gemfile +9 -0
- data/formtastic-6.0.0/gemfiles/rails_80.gemfile +9 -0
- data/formtastic-6.0.0/gemfiles/rails_81.gemfile +9 -0
- data/formtastic-6.0.0/gemfiles/rails_edge.gemfile +9 -0
- data/formtastic-6.0.0/lib/formtastic/action_class_finder.rb +19 -0
- data/formtastic-6.0.0/lib/formtastic/actions/base.rb +157 -0
- data/formtastic-6.0.0/lib/formtastic/actions/button_action.rb +68 -0
- data/formtastic-6.0.0/lib/formtastic/actions/buttonish.rb +18 -0
- data/formtastic-6.0.0/lib/formtastic/actions/input_action.rb +71 -0
- data/formtastic-6.0.0/lib/formtastic/actions/link_action.rb +89 -0
- data/formtastic-6.0.0/lib/formtastic/actions.rb +15 -0
- data/formtastic-6.0.0/lib/formtastic/deprecation.rb +6 -0
- data/formtastic-6.0.0/lib/formtastic/form_builder.rb +109 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/action_helper.rb +115 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/actions_helper.rb +169 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/enum.rb +14 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/errors_helper.rb +139 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/fieldset_wrapper.rb +85 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/file_column_detection.rb +17 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/form_helper.rb +204 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/input_helper.rb +349 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/inputs_helper.rb +421 -0
- data/formtastic-6.0.0/lib/formtastic/helpers/reflection.rb +38 -0
- data/formtastic-6.0.0/lib/formtastic/helpers.rb +16 -0
- data/formtastic-6.0.0/lib/formtastic/html_attributes.rb +33 -0
- data/formtastic-6.0.0/lib/formtastic/i18n.rb +33 -0
- data/formtastic-6.0.0/lib/formtastic/input_class_finder.rb +19 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/aria.rb +26 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/associations.rb +32 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/choices.rb +109 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/collections.rb +158 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/database.rb +20 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/datetime_pickerish.rb +86 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/errors.rb +59 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/fileish.rb +24 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/hints.rb +32 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/html.rb +54 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/labelling.rb +53 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/naming.rb +43 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/numeric.rb +51 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/options.rb +18 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/placeholder.rb +18 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/stringish.rb +39 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/timeish.rb +246 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/validations.rb +250 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base/wrapping.rb +51 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/base.rb +79 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/boolean_input.rb +119 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/check_boxes_input.rb +198 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/color_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/country_input.rb +90 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/datalist_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/date_picker_input.rb +94 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/date_select_input.rb +35 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/datetime_picker_input.rb +104 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/datetime_select_input.rb +13 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/email_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/file_input.rb +43 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/hidden_input.rb +63 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/number_input.rb +89 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/password_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/phone_input.rb +43 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/radio_input.rb +164 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/range_input.rb +96 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/search_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/select_input.rb +236 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/string_input.rb +37 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/text_input.rb +49 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/time_picker_input.rb +100 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/time_select_input.rb +39 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/time_zone_input.rb +59 -0
- data/formtastic-6.0.0/lib/formtastic/inputs/url_input.rb +42 -0
- data/formtastic-6.0.0/lib/formtastic/inputs.rb +43 -0
- data/formtastic-6.0.0/lib/formtastic/localized_string.rb +18 -0
- data/formtastic-6.0.0/lib/formtastic/localizer.rb +151 -0
- data/formtastic-6.0.0/lib/formtastic/namespaced_class_finder.rb +98 -0
- data/formtastic-6.0.0/lib/formtastic/version.rb +4 -0
- data/formtastic-6.0.0/lib/formtastic.rb +48 -0
- data/formtastic-6.0.0/lib/generators/formtastic/form/form_generator.rb +111 -0
- data/formtastic-6.0.0/lib/generators/formtastic/input/input_generator.rb +47 -0
- data/formtastic-6.0.0/lib/generators/formtastic/install/install_generator.rb +23 -0
- data/formtastic-6.0.0/lib/generators/formtastic/stylesheets/stylesheets_generator.rb +15 -0
- data/formtastic-6.0.0/lib/generators/templates/_form.html.erb +11 -0
- data/formtastic-6.0.0/lib/generators/templates/_form.html.haml +8 -0
- data/formtastic-6.0.0/lib/generators/templates/_form.html.slim +8 -0
- data/formtastic-6.0.0/lib/generators/templates/formtastic.css +289 -0
- data/formtastic-6.0.0/lib/generators/templates/formtastic.rb +118 -0
- data/formtastic-6.0.0/lib/generators/templates/input.rb +19 -0
- data/formtastic-6.0.0/lib/locale/en.yml +10 -0
- data/formtastic-6.0.0/sample/basic_inputs.html +224 -0
- data/formtastic-6.0.0/sample/config.ru +69 -0
- data/formtastic-6.0.0/sample/index.html +14 -0
- data/formtastic-6.0.0/script/integration-template.rb +76 -0
- data/formtastic-6.0.0/script/integration.sh +32 -0
- data/formtastic-6.0.0/spec/action_class_finder_spec.rb +12 -0
- data/formtastic-6.0.0/spec/actions/button_action_spec.rb +63 -0
- data/formtastic-6.0.0/spec/actions/generic_action_spec.rb +521 -0
- data/formtastic-6.0.0/spec/actions/input_action_spec.rb +59 -0
- data/formtastic-6.0.0/spec/actions/link_action_spec.rb +92 -0
- data/formtastic-6.0.0/spec/builder/custom_builder_spec.rb +132 -0
- data/formtastic-6.0.0/spec/builder/error_proc_spec.rb +27 -0
- data/formtastic-6.0.0/spec/builder/semantic_fields_for_spec.rb +213 -0
- data/formtastic-6.0.0/spec/fast_spec_helper.rb +12 -0
- data/formtastic-6.0.0/spec/generators/formtastic/form/form_generator_spec.rb +132 -0
- data/formtastic-6.0.0/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
- data/formtastic-6.0.0/spec/generators/formtastic/install/install_generator_spec.rb +48 -0
- data/formtastic-6.0.0/spec/generators/formtastic/stylesheets/stylesheets_generator_spec.rb +22 -0
- data/formtastic-6.0.0/spec/helpers/action_helper_spec.rb +338 -0
- data/formtastic-6.0.0/spec/helpers/actions_helper_spec.rb +143 -0
- data/formtastic-6.0.0/spec/helpers/form_helper_spec.rb +224 -0
- data/formtastic-6.0.0/spec/helpers/input_helper_spec.rb +991 -0
- data/formtastic-6.0.0/spec/helpers/inputs_helper_spec.rb +669 -0
- data/formtastic-6.0.0/spec/helpers/reflection_helper_spec.rb +32 -0
- data/formtastic-6.0.0/spec/helpers/semantic_errors_helper_spec.rb +220 -0
- data/formtastic-6.0.0/spec/i18n_spec.rb +210 -0
- data/formtastic-6.0.0/spec/input_class_finder_spec.rb +10 -0
- data/formtastic-6.0.0/spec/inputs/base/collections_spec.rb +119 -0
- data/formtastic-6.0.0/spec/inputs/base/validations_spec.rb +481 -0
- data/formtastic-6.0.0/spec/inputs/boolean_input_spec.rb +254 -0
- data/formtastic-6.0.0/spec/inputs/check_boxes_input_spec.rb +547 -0
- data/formtastic-6.0.0/spec/inputs/color_input_spec.rb +85 -0
- data/formtastic-6.0.0/spec/inputs/country_input_spec.rb +133 -0
- data/formtastic-6.0.0/spec/inputs/custom_input_spec.rb +51 -0
- data/formtastic-6.0.0/spec/inputs/datalist_input_spec.rb +61 -0
- data/formtastic-6.0.0/spec/inputs/date_picker_input_spec.rb +449 -0
- data/formtastic-6.0.0/spec/inputs/date_select_input_spec.rb +249 -0
- data/formtastic-6.0.0/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/formtastic-6.0.0/spec/inputs/datetime_select_input_spec.rb +209 -0
- data/formtastic-6.0.0/spec/inputs/email_input_spec.rb +85 -0
- data/formtastic-6.0.0/spec/inputs/file_input_spec.rb +89 -0
- data/formtastic-6.0.0/spec/inputs/hidden_input_spec.rb +135 -0
- data/formtastic-6.0.0/spec/inputs/include_blank_spec.rb +78 -0
- data/formtastic-6.0.0/spec/inputs/label_spec.rb +181 -0
- data/formtastic-6.0.0/spec/inputs/number_input_spec.rb +815 -0
- data/formtastic-6.0.0/spec/inputs/password_input_spec.rb +99 -0
- data/formtastic-6.0.0/spec/inputs/phone_input_spec.rb +85 -0
- data/formtastic-6.0.0/spec/inputs/placeholder_spec.rb +71 -0
- data/formtastic-6.0.0/spec/inputs/radio_input_spec.rb +326 -0
- data/formtastic-6.0.0/spec/inputs/range_input_spec.rb +505 -0
- data/formtastic-6.0.0/spec/inputs/readonly_spec.rb +50 -0
- data/formtastic-6.0.0/spec/inputs/search_input_spec.rb +84 -0
- data/formtastic-6.0.0/spec/inputs/select_input_spec.rb +661 -0
- data/formtastic-6.0.0/spec/inputs/string_input_spec.rb +326 -0
- data/formtastic-6.0.0/spec/inputs/text_input_spec.rb +187 -0
- data/formtastic-6.0.0/spec/inputs/time_picker_input_spec.rb +455 -0
- data/formtastic-6.0.0/spec/inputs/time_select_input_spec.rb +261 -0
- data/formtastic-6.0.0/spec/inputs/time_zone_input_spec.rb +143 -0
- data/formtastic-6.0.0/spec/inputs/url_input_spec.rb +85 -0
- data/formtastic-6.0.0/spec/inputs/with_options_spec.rb +43 -0
- data/formtastic-6.0.0/spec/localizer_spec.rb +130 -0
- data/formtastic-6.0.0/spec/namespaced_class_finder_spec.rb +90 -0
- data/formtastic-6.0.0/spec/schema.rb +22 -0
- data/formtastic-6.0.0/spec/spec.opts +2 -0
- data/formtastic-6.0.0/spec/spec_helper.rb +466 -0
- data/formtastic-6.0.0/spec/support/custom_macros.rb +570 -0
- data/formtastic-6.0.0/spec/support/deprecation.rb +7 -0
- data/formtastic-6.0.0/spec/support/shared_examples.rb +13 -0
- data/formtastic-6.0.0/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/formtastic-6.0.0/spec/support/test_environment.rb +46 -0
- data/mega-safe-tool.gemspec +11 -0
- 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
|