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,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
module Inputs
|
|
4
|
+
|
|
5
|
+
# Outputs a simple `<label>` with a HTML5 `<input type="url">` wrapped in the standard
|
|
6
|
+
# `<li>` wrapper. This is the default input choice for all attributes matching
|
|
7
|
+
# `/^url$|^website$|_url$/`, but can be applied to any text-like input with `:as => :url`.
|
|
8
|
+
#
|
|
9
|
+
# @example Full form context and output
|
|
10
|
+
#
|
|
11
|
+
# <%= semantic_form_for(@user) do |f| %>
|
|
12
|
+
# <%= f.inputs do %>
|
|
13
|
+
# <%= f.input :home_page, :as => :url %>
|
|
14
|
+
# <% end %>
|
|
15
|
+
# <% end %>
|
|
16
|
+
#
|
|
17
|
+
# <form...>
|
|
18
|
+
# <fieldset>
|
|
19
|
+
# <ol>
|
|
20
|
+
# <li class="url">
|
|
21
|
+
# <label for="user_home_page">Home page</label>
|
|
22
|
+
# <input type="number" id="user_home_page" name="user[home_page]">
|
|
23
|
+
# </li>
|
|
24
|
+
# </ol>
|
|
25
|
+
# </fieldset>
|
|
26
|
+
# </form>
|
|
27
|
+
#
|
|
28
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
|
29
|
+
class UrlInput
|
|
30
|
+
include Base
|
|
31
|
+
include Base::Stringish
|
|
32
|
+
include Base::Placeholder
|
|
33
|
+
|
|
34
|
+
def to_html
|
|
35
|
+
input_wrapping do
|
|
36
|
+
label_html <<
|
|
37
|
+
builder.url_field(method, input_html_options)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
module Inputs
|
|
4
|
+
extend ActiveSupport::Autoload
|
|
5
|
+
|
|
6
|
+
autoload :Base
|
|
7
|
+
autoload :Basic
|
|
8
|
+
autoload :Timeish
|
|
9
|
+
|
|
10
|
+
eager_autoload do
|
|
11
|
+
autoload :BooleanInput
|
|
12
|
+
autoload :CheckBoxesInput
|
|
13
|
+
autoload :ColorInput
|
|
14
|
+
autoload :CountryInput
|
|
15
|
+
autoload :DatalistInput
|
|
16
|
+
autoload :DateInput
|
|
17
|
+
autoload :DatePickerInput
|
|
18
|
+
autoload :DatetimePickerInput
|
|
19
|
+
autoload :DateSelectInput
|
|
20
|
+
autoload :DatetimeInput
|
|
21
|
+
autoload :DatetimeSelectInput
|
|
22
|
+
autoload :EmailInput
|
|
23
|
+
autoload :FileInput
|
|
24
|
+
autoload :HiddenInput
|
|
25
|
+
autoload :NumberInput
|
|
26
|
+
autoload :NumericInput
|
|
27
|
+
autoload :PasswordInput
|
|
28
|
+
autoload :PhoneInput
|
|
29
|
+
autoload :RadioInput
|
|
30
|
+
autoload :RangeInput
|
|
31
|
+
autoload :SearchInput
|
|
32
|
+
autoload :SelectInput
|
|
33
|
+
autoload :StringInput
|
|
34
|
+
autoload :TextInput
|
|
35
|
+
autoload :TimeInput
|
|
36
|
+
autoload :TimePickerInput
|
|
37
|
+
autoload :TimeSelectInput
|
|
38
|
+
autoload :TimeZoneInput
|
|
39
|
+
autoload :UrlInput
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
module LocalizedString
|
|
4
|
+
|
|
5
|
+
def model_name
|
|
6
|
+
@object.present? ? @object.class.name : @object_name.to_s.classify
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
protected
|
|
10
|
+
|
|
11
|
+
def localized_string(key, value, type, options = {}) # @private
|
|
12
|
+
current_builder = respond_to?(:builder) ? builder : self
|
|
13
|
+
localizer = Formtastic::FormBuilder.i18n_localizer.new(current_builder)
|
|
14
|
+
localizer.localize(key, value, type, options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
# Implementation for looking up localized values within Formtastic using I18n, if no
|
|
4
|
+
# explicit value (like the `:label` option) is set and I18n-lookups are enabled in the
|
|
5
|
+
# configuration.
|
|
6
|
+
#
|
|
7
|
+
# You can subclass this to implement your own Localizer, and configure Formtastic to use this
|
|
8
|
+
# localizer with:
|
|
9
|
+
#
|
|
10
|
+
# Formtastic::FormBuilder.i18n_localizer
|
|
11
|
+
#
|
|
12
|
+
# Enabled/disable i18n lookups completely with:
|
|
13
|
+
#
|
|
14
|
+
# Formtastic::FormBuilder.i18n_lookups_by_default = true/false
|
|
15
|
+
#
|
|
16
|
+
# Lookup priority:
|
|
17
|
+
#
|
|
18
|
+
# 'formtastic.%{type}.%{model}.%{action}.%{attribute}'
|
|
19
|
+
# 'formtastic.%{type}.%{model}.%{attribute}'
|
|
20
|
+
# 'formtastic.%{type}.%{attribute}'
|
|
21
|
+
#
|
|
22
|
+
# Example:
|
|
23
|
+
#
|
|
24
|
+
# 'formtastic.labels.post.edit.title'
|
|
25
|
+
# 'formtastic.labels.post.title'
|
|
26
|
+
# 'formtastic.labels.title'
|
|
27
|
+
class Localizer
|
|
28
|
+
class Cache
|
|
29
|
+
def get(key)
|
|
30
|
+
cache[key]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def has_key?(key)
|
|
34
|
+
cache.has_key?(key)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def set(key, result)
|
|
38
|
+
cache[key] = result
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cache
|
|
42
|
+
@cache ||= {}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def clear!
|
|
46
|
+
cache.clear
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
attr_accessor :builder
|
|
51
|
+
|
|
52
|
+
def self.cache
|
|
53
|
+
@cache ||= Cache.new
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def initialize(current_builder)
|
|
57
|
+
self.builder = current_builder
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def localize(key, value, type, options = {}) # @private
|
|
61
|
+
key = value if value.is_a?(::Symbol)
|
|
62
|
+
|
|
63
|
+
if value.is_a?(::String)
|
|
64
|
+
escape_html_entities(value)
|
|
65
|
+
else
|
|
66
|
+
use_i18n = value.nil? ? i18n_lookups_by_default : (value != false)
|
|
67
|
+
use_cache = i18n_cache_lookups
|
|
68
|
+
cache = self.class.cache
|
|
69
|
+
|
|
70
|
+
if use_i18n
|
|
71
|
+
model_name, nested_model_name = normalize_model_name(builder.model_name.underscore)
|
|
72
|
+
|
|
73
|
+
action_name = builder.template.params[:action].to_s rescue ''
|
|
74
|
+
attribute_name = key.to_s
|
|
75
|
+
|
|
76
|
+
# look in the cache first
|
|
77
|
+
if use_cache
|
|
78
|
+
cache_key = [::I18n.locale, action_name, model_name, nested_model_name, attribute_name, key, value, type, options]
|
|
79
|
+
return cache.get(cache_key) if cache.has_key?(cache_key)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
defaults = Formtastic::I18n::SCOPES.reject do |i18n_scope|
|
|
83
|
+
nested_model_name.nil? && i18n_scope.match(/nested_model/)
|
|
84
|
+
end.collect do |i18n_scope|
|
|
85
|
+
i18n_path = i18n_scope.dup
|
|
86
|
+
i18n_path.gsub!('%{action}', action_name)
|
|
87
|
+
i18n_path.gsub!('%{model}', model_name)
|
|
88
|
+
i18n_path.gsub!('%{nested_model}', nested_model_name) unless nested_model_name.nil?
|
|
89
|
+
i18n_path.gsub!('%{attribute}', attribute_name)
|
|
90
|
+
i18n_path.tr!('..', '.')
|
|
91
|
+
i18n_path.to_sym
|
|
92
|
+
end
|
|
93
|
+
defaults << ''
|
|
94
|
+
|
|
95
|
+
defaults.uniq!
|
|
96
|
+
|
|
97
|
+
default_key = defaults.shift
|
|
98
|
+
i18n_value = Formtastic::I18n.t(default_key,
|
|
99
|
+
options.merge(:default => defaults, :scope => type.to_s.pluralize.to_sym))
|
|
100
|
+
i18n_value = i18n_value.is_a?(::String) ? i18n_value : nil
|
|
101
|
+
if i18n_value.blank? && type == :label
|
|
102
|
+
# This is effectively what Rails label helper does for i18n lookup
|
|
103
|
+
options[:scope] = [:helpers, type]
|
|
104
|
+
options[:default] = defaults
|
|
105
|
+
i18n_value = ::I18n.t(default_key, **options)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# save the result to the cache
|
|
109
|
+
result = (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil
|
|
110
|
+
cache.set(cache_key, result) if use_cache
|
|
111
|
+
result
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
protected
|
|
117
|
+
|
|
118
|
+
def normalize_model_name(name)
|
|
119
|
+
if name =~ /(.+)\[(.+)\]/
|
|
120
|
+
# Nested builder case with :post rather than @post
|
|
121
|
+
# TODO: check if this is no longer required with a minimum of Rails 4.1
|
|
122
|
+
[$1, $2]
|
|
123
|
+
elsif builder.respond_to?(:options) && builder.options.key?(:as)
|
|
124
|
+
[builder.options[:as].to_s]
|
|
125
|
+
elsif builder.respond_to?(:options) && builder.options.key?(:parent_builder)
|
|
126
|
+
# Rails 3.0+ nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
|
|
127
|
+
[builder.options[:parent_builder].object_name.to_s, name]
|
|
128
|
+
else
|
|
129
|
+
# Non-nested case
|
|
130
|
+
[name]
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def escape_html_entities(string) # @private
|
|
135
|
+
if (builder.escape_html_entities_in_hints_and_labels) ||
|
|
136
|
+
(self.respond_to?(:escape_html_entities_in_hints_and_labels) && escape_html_entities_in_hints_and_labels)
|
|
137
|
+
string = builder.template.escape_once(string) unless string.respond_to?(:html_safe?) && string.html_safe? == true # Accept html_safe flag as indicator to skip escaping
|
|
138
|
+
end
|
|
139
|
+
string
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def i18n_lookups_by_default
|
|
143
|
+
builder.i18n_lookups_by_default
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def i18n_cache_lookups
|
|
147
|
+
builder.i18n_cache_lookups
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
# This class implements class resolution in a namespace chain. It
|
|
4
|
+
# is used both by Formtastic::Helpers::InputHelper and
|
|
5
|
+
# Formtastic::Helpers::ActionHelper to look up action and input classes.
|
|
6
|
+
#
|
|
7
|
+
# @example Implementing own class finder
|
|
8
|
+
# # You can implement own class finder that for example prefixes the class name or uses custom module.
|
|
9
|
+
# class MyInputClassFinder < Formtastic::NamespacedClassFinder
|
|
10
|
+
# def initialize(namespaces)
|
|
11
|
+
# super [MyNamespace] + namespaces # first lookup in MyNamespace then the defaults
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# private
|
|
15
|
+
#
|
|
16
|
+
# def class_name(as)
|
|
17
|
+
# "My#{super}Input" # for example MyStringInput
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# # in config/initializers/formtastic.rb
|
|
22
|
+
# Formtastic::FormBuilder.input_class_finder = MyInputClassFinder
|
|
23
|
+
#
|
|
24
|
+
|
|
25
|
+
class NamespacedClassFinder
|
|
26
|
+
attr_reader :namespaces # @private
|
|
27
|
+
|
|
28
|
+
# @private
|
|
29
|
+
class NotFoundError < NameError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.use_const_defined?
|
|
33
|
+
defined?(Rails) && ::Rails.application && ::Rails.application.config.respond_to?(:eager_load) && ::Rails.application.config.eager_load
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.finder_method
|
|
37
|
+
@finder_method ||= use_const_defined? ? :find_with_const_defined : :find_by_trying
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param namespaces [Array<Module>]
|
|
41
|
+
def initialize(namespaces)
|
|
42
|
+
@namespaces = namespaces.flatten
|
|
43
|
+
@cache = {}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Looks up the given reference in the configured namespaces.
|
|
47
|
+
#
|
|
48
|
+
# Two finder methods are provided, one for development tries to
|
|
49
|
+
# reference the constant directly, triggering Rails' autoloading
|
|
50
|
+
# const_missing machinery; the second one instead for production
|
|
51
|
+
# checks with .const_defined before referencing the constant.
|
|
52
|
+
#
|
|
53
|
+
def find(as)
|
|
54
|
+
@cache[as] ||= resolve(as)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def resolve(as)
|
|
58
|
+
class_name = class_name(as)
|
|
59
|
+
|
|
60
|
+
finder(class_name) or raise NotFoundError, "class #{class_name}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Converts symbol to class name
|
|
64
|
+
# Overridden in subclasses to create `StringInput` and `ButtonAction`
|
|
65
|
+
# @example
|
|
66
|
+
# class_name(:string) == "String"
|
|
67
|
+
|
|
68
|
+
def class_name(as)
|
|
69
|
+
as.to_s.camelize
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def finder(class_name) # @private
|
|
75
|
+
send(self.class.finder_method, class_name)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Looks up the given class name in the configured namespaces in order,
|
|
79
|
+
# returning the first one that has the class name constant defined.
|
|
80
|
+
def find_with_const_defined(class_name)
|
|
81
|
+
@namespaces.find do |namespace|
|
|
82
|
+
if namespace.const_defined?(class_name)
|
|
83
|
+
break namespace.const_get(class_name)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Use auto-loading in development environment
|
|
89
|
+
def find_by_trying(class_name)
|
|
90
|
+
@namespaces.find do |namespace|
|
|
91
|
+
begin
|
|
92
|
+
break namespace.const_get(class_name)
|
|
93
|
+
rescue NameError
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Formtastic
|
|
4
|
+
extend ActiveSupport::Autoload
|
|
5
|
+
|
|
6
|
+
autoload :Helpers
|
|
7
|
+
autoload :HtmlAttributes
|
|
8
|
+
autoload :LocalizedString
|
|
9
|
+
autoload :Localizer
|
|
10
|
+
autoload :NamespacedClassFinder
|
|
11
|
+
autoload :InputClassFinder
|
|
12
|
+
autoload :ActionClassFinder
|
|
13
|
+
autoload :Deprecation
|
|
14
|
+
|
|
15
|
+
eager_autoload do
|
|
16
|
+
autoload :I18n
|
|
17
|
+
autoload :FormBuilder
|
|
18
|
+
autoload :Inputs
|
|
19
|
+
autoload :Actions
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @public
|
|
23
|
+
class UnknownInputError < NameError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @private
|
|
27
|
+
class UnknownActionError < NameError
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @private
|
|
31
|
+
class PolymorphicInputWithoutCollectionError < ArgumentError
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @private
|
|
35
|
+
class UnsupportedMethodForAction < ArgumentError
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @private
|
|
39
|
+
class UnsupportedEnumCollection < NameError
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if defined?(::Rails)
|
|
45
|
+
ActiveSupport.on_load(:action_view) do
|
|
46
|
+
include Formtastic::Helpers::FormHelper
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
# Generates a Formtastic form partial based on an existing model. It will not overwrite existing
|
|
4
|
+
# files without confirmation.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# !!!shell
|
|
8
|
+
# $ rails generate formtastic:form Post
|
|
9
|
+
# @example Copy the partial code to the pasteboard rather than generating a partial
|
|
10
|
+
# !!!shell
|
|
11
|
+
# $ rails generate formtastic:form Post --copy
|
|
12
|
+
# @example Return HAML or Slim output instead of default ERB
|
|
13
|
+
# !!!shell
|
|
14
|
+
# $ rails generate formtastic:form Post --template-engine haml
|
|
15
|
+
# $ rails generate formtastic:form Post --template-engine slim
|
|
16
|
+
# @example Generate a form for specific model attributes
|
|
17
|
+
# !!!shell
|
|
18
|
+
# $ rails generate formtastic:form Post title:string body:text
|
|
19
|
+
# @example Generate a form for a specific controller
|
|
20
|
+
# !!!shell
|
|
21
|
+
# $ rails generate formtastic:form Post --controller admin/posts
|
|
22
|
+
class FormGenerator < Rails::Generators::NamedBase
|
|
23
|
+
desc "Generates a Formtastic form partial based on an existing model."
|
|
24
|
+
|
|
25
|
+
argument :name, :type => :string, :required => true, :banner => 'MODEL_NAME'
|
|
26
|
+
argument :attributes, :type => :array, :default => [], :banner => 'attribute attribute'
|
|
27
|
+
|
|
28
|
+
source_root File.expand_path('../../../templates', __FILE__)
|
|
29
|
+
|
|
30
|
+
class_option :template_engine
|
|
31
|
+
|
|
32
|
+
class_option :copy, :type => :boolean, :default => false, :group => :formtastic,
|
|
33
|
+
:desc => 'Copy the generated code the clipboard instead of generating a partial file."'
|
|
34
|
+
|
|
35
|
+
class_option :controller, :type => :string, :default => nil, :group => :formtastic,
|
|
36
|
+
:desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
|
|
37
|
+
|
|
38
|
+
def create_or_show
|
|
39
|
+
@attributes = reflected_attributes if @attributes.empty?
|
|
40
|
+
|
|
41
|
+
engine = options[:template_engine]
|
|
42
|
+
|
|
43
|
+
if options[:copy]
|
|
44
|
+
template = File.read("#{self.class.source_root}/_form.html.#{engine}")
|
|
45
|
+
erb = ERB.new(template, trim_mode: '-')
|
|
46
|
+
generated_code = erb.result(binding).strip rescue nil
|
|
47
|
+
puts "The following code has been copied to the clipboard, just paste it in your views:" if save_to_clipboard(generated_code)
|
|
48
|
+
puts generated_code || "Error: Nothing generated. Does the model exist?"
|
|
49
|
+
else
|
|
50
|
+
empty_directory "app/views/#{controller_path}"
|
|
51
|
+
template "_form.html.#{engine}", "app/views/#{controller_path}/_form.html.#{engine}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
protected
|
|
56
|
+
|
|
57
|
+
def controller_path
|
|
58
|
+
@controller_path ||= if options[:controller]
|
|
59
|
+
options[:controller].underscore
|
|
60
|
+
else
|
|
61
|
+
name.underscore.pluralize
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def reflected_attributes
|
|
66
|
+
columns = content_columns
|
|
67
|
+
columns += association_columns
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def model
|
|
71
|
+
@model ||= name.camelize.constantize
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Collects content columns (non-relation columns) for the current class.
|
|
75
|
+
# Skips Active Record Timestamps.
|
|
76
|
+
def content_columns
|
|
77
|
+
model.content_columns.select do |column|
|
|
78
|
+
!Formtastic::FormBuilder.skipped_columns.include? column.name.to_sym
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Collects association columns (relation columns) for the current class. Skips polymorphic
|
|
83
|
+
# associations because we can't guess which class to use for an automatically generated input.
|
|
84
|
+
def association_columns
|
|
85
|
+
model.reflect_on_all_associations(:belongs_to).select do |association_reflection|
|
|
86
|
+
association_reflection.options[:polymorphic] != true
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def save_to_clipboard(data)
|
|
91
|
+
return unless data
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
case RUBY_PLATFORM
|
|
95
|
+
when /win32/
|
|
96
|
+
require 'win32/clipboard'
|
|
97
|
+
::Win32::Clipboard.data = data
|
|
98
|
+
when /darwin/ # mac
|
|
99
|
+
`echo "#{data}" | pbcopy`
|
|
100
|
+
else # linux/unix
|
|
101
|
+
`echo "#{data}" | xsel --clipboard` || `echo "#{data}" | xclip`
|
|
102
|
+
end
|
|
103
|
+
rescue LoadError
|
|
104
|
+
false
|
|
105
|
+
else
|
|
106
|
+
true
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
|
|
4
|
+
# Modify existing inputs, subclass them, or create your own from scratch.
|
|
5
|
+
# @example
|
|
6
|
+
# !!!shell
|
|
7
|
+
# $ rails generate formtastic:input HatSize
|
|
8
|
+
|
|
9
|
+
# @example Define input name using underscore convention
|
|
10
|
+
# !!!shell
|
|
11
|
+
# $ rails generate formtastic:input hat_size
|
|
12
|
+
|
|
13
|
+
# @example Override an existing input behavior
|
|
14
|
+
# !!!shell
|
|
15
|
+
# $ rails generate formtastic:input string --extend
|
|
16
|
+
|
|
17
|
+
# @example Extend an existing input behavior
|
|
18
|
+
# !!!shell
|
|
19
|
+
# $ rails generate formtastic:input FlexibleText --extend string
|
|
20
|
+
class InputGenerator < Rails::Generators::NamedBase
|
|
21
|
+
|
|
22
|
+
argument :name, :type => :string, :required => true, :banner => 'FILE_NAME'
|
|
23
|
+
|
|
24
|
+
source_root File.expand_path('../../../templates', __FILE__)
|
|
25
|
+
|
|
26
|
+
class_option :extend
|
|
27
|
+
|
|
28
|
+
def create
|
|
29
|
+
normalize_file_name
|
|
30
|
+
define_extension_sentence
|
|
31
|
+
template "input.rb", "app/inputs/#{name.underscore}_input.rb"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def normalize_file_name
|
|
37
|
+
name.chomp!("Input") if name.ends_with?("Input")
|
|
38
|
+
name.chomp!("_input") if name.ends_with?("_input")
|
|
39
|
+
name.chomp!("input") if name.ends_with?("input")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def define_extension_sentence
|
|
43
|
+
@extension_sentence = "< Formtastic::Inputs::#{name.camelize}Input" if options[:extend] == "extend"
|
|
44
|
+
@extension_sentence ||= "< Formtastic::Inputs::#{options[:extend].camelize}Input" if options[:extend]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Formtastic
|
|
4
|
+
# Copies a config initializer to config/initializers/formtastic.rb
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# !!!shell
|
|
8
|
+
# $ rails generate formtastic:install
|
|
9
|
+
class InstallGenerator < Rails::Generators::Base
|
|
10
|
+
source_root File.expand_path('../../../templates', __FILE__)
|
|
11
|
+
class_option :template_engine
|
|
12
|
+
|
|
13
|
+
desc "Copies a config initializer to config/initializers/formtastic.rb"
|
|
14
|
+
def copy_files
|
|
15
|
+
copy_file 'formtastic.rb', 'config/initializers/formtastic.rb'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def copy_scaffold_template
|
|
19
|
+
engine = options[:template_engine]
|
|
20
|
+
copy_file "_form.html.#{engine}", "lib/templates/#{engine}/scaffold/_form.html.#{engine}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
# Copies a stylesheet into to app/assets/stylesheets/formtastic.css
|
|
3
|
+
#
|
|
4
|
+
# @example
|
|
5
|
+
# !!!shell
|
|
6
|
+
# $ rails generate formtastic:stylesheets
|
|
7
|
+
class StylesheetsGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path("../../../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
desc "Copies Formtastic example stylesheet into your app"
|
|
11
|
+
def copy_files
|
|
12
|
+
copy_file "formtastic.css", "app/assets/stylesheets/formtastic.css"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<%%= semantic_form_for @<%= singular_name %> do |f| %>
|
|
2
|
+
<%%= f.inputs do %>
|
|
3
|
+
<%- attributes.each do |attribute| -%>
|
|
4
|
+
<%%= f.input :<%= attribute.name %> %>
|
|
5
|
+
<%- end -%>
|
|
6
|
+
<%% end %>
|
|
7
|
+
|
|
8
|
+
<%%= f.actions do %>
|
|
9
|
+
<%%= f.action :submit, :as => :input %>
|
|
10
|
+
<%% end %>
|
|
11
|
+
<%% end %>
|