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,109 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Choices
6
+
7
+ def choices_wrapping(&block)
8
+ template.content_tag(:fieldset,
9
+ template.capture(&block),
10
+ choices_wrapping_html_options
11
+ )
12
+ end
13
+
14
+ def choices_wrapping_html_options
15
+ { :class => "choices" }
16
+ end
17
+
18
+ def choices_group_wrapping(&block)
19
+ template.content_tag(:ol,
20
+ template.capture(&block),
21
+ choices_group_wrapping_html_options
22
+ )
23
+ end
24
+
25
+ def choices_group_wrapping_html_options
26
+ { :class => "choices-group" }
27
+ end
28
+
29
+ def choice_wrapping(html_options, &block)
30
+ template.content_tag(:li,
31
+ template.capture(&block),
32
+ html_options
33
+ )
34
+ end
35
+
36
+ def choice_wrapping_html_options(choice)
37
+ classes = ['choice']
38
+ classes << "#{sanitized_method_name.singularize}_#{choice_html_safe_value(choice)}" if value_as_class?
39
+
40
+ { :class => classes.join(" ") }
41
+ end
42
+
43
+ def choice_html(choice)
44
+ raise "choice_html() needs to be implemented when including Formtastic::Inputs::Base::Choices"
45
+ end
46
+
47
+ def choice_label(choice)
48
+ if choice.is_a?(Array)
49
+ choice.first
50
+ else
51
+ choice
52
+ end.to_s
53
+ end
54
+
55
+ def choice_value(choice)
56
+ choice.is_a?(Array) ? choice[1] : choice
57
+ end
58
+
59
+ def choice_html_options(choice)
60
+ custom_choice_html_options(choice).merge(default_choice_html_options(choice))
61
+ end
62
+
63
+ def default_choice_html_options(choice)
64
+ { :id => choice_input_dom_id(choice) }
65
+ end
66
+
67
+ def custom_choice_html_options(choice)
68
+ (choice.is_a?(Array) && choice.size > 2) ? choice[-1] : {}
69
+ end
70
+
71
+ def choice_html_safe_value(choice)
72
+ choice_value(choice).to_s.gsub(/\s/, '_').gsub(/[^\w-]/, '').downcase
73
+ end
74
+
75
+ def choice_input_dom_id(choice)
76
+ [
77
+ builder.dom_id_namespace,
78
+ sanitized_object_name,
79
+ builder.options[:index],
80
+ association_primary_key || method,
81
+ choice_html_safe_value(choice)
82
+ ].compact.reject { |i| i.blank? }.join("_")
83
+ end
84
+
85
+ def value_as_class?
86
+ options[:value_as_class]
87
+ end
88
+
89
+ def legend_html
90
+ if render_label?
91
+ template.content_tag(:legend,
92
+ template.content_tag(:label, label_text),
93
+ label_html_options.merge(:class => "label")
94
+ )
95
+ else
96
+ +"".html_safe
97
+ end
98
+ end
99
+
100
+ # Override to remove the for attribute since this isn't associated with any element, as it's
101
+ # nested inside the legend.
102
+ def label_html_options
103
+ super.merge(:for => nil)
104
+ end
105
+
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Collections
6
+
7
+ def label_method
8
+ @label_method ||= (label_method_from_options || label_and_value_method.first)
9
+ end
10
+
11
+ def label_method_from_options
12
+ options[:member_label]
13
+ end
14
+
15
+ def value_method
16
+ @value_method ||= (value_method_from_options || label_and_value_method[-1])
17
+ end
18
+
19
+ def value_method_from_options
20
+ options[:member_value]
21
+ end
22
+
23
+ def label_and_value_method
24
+ @label_and_value_method ||= label_and_value_method_from_collection(raw_collection)
25
+ end
26
+
27
+ def label_and_value_method_from_collection(_collection)
28
+ sample = _collection.first || _collection[-1]
29
+
30
+ case sample
31
+ when Array
32
+ label, value = :first, :last
33
+ when Integer
34
+ label, value = :to_s, :to_i
35
+ when Symbol, String, NilClass
36
+ label, value = :to_s, :to_s
37
+ end
38
+
39
+ # Order of preference: user supplied method, class defaults, auto-detect
40
+ label ||= builder.collection_label_methods.find { |m| sample.respond_to?(m) }
41
+ value ||= builder.collection_value_methods.find { |m| sample.respond_to?(m) }
42
+
43
+ [label, value]
44
+ end
45
+
46
+ def raw_collection
47
+ @raw_collection ||= (collection_from_options || collection_from_enum || collection_from_association || collection_for_boolean)
48
+ end
49
+
50
+ def collection
51
+ # Return if we have a plain string
52
+ return raw_collection if raw_collection.is_a?(String)
53
+
54
+ # Return if we have an Array of strings, integers or arrays
55
+ return raw_collection if (raw_collection.instance_of?(Array) || raw_collection.instance_of?(Range)) &&
56
+ ([Array, String, Symbol].include?(raw_collection.first.class) || raw_collection.first.is_a?(Integer)) &&
57
+ !(options.include?(:member_label) || options.include?(:member_value))
58
+
59
+ raw_collection.map { |o| [send_or_call(label_method, o), send_or_call(value_method, o)] }
60
+ end
61
+
62
+ def collection_from_options
63
+ items = options[:collection]
64
+ case items
65
+ when Hash
66
+ items.to_a
67
+ when Range
68
+ items.to_a.collect{ |c| [c.to_s, c] }
69
+ else
70
+ items
71
+ end
72
+ end
73
+
74
+ def collection_from_association
75
+ if reflection
76
+ if reflection.respond_to?(:options)
77
+ raise PolymorphicInputWithoutCollectionError.new(
78
+ "A collection must be supplied for #{method} input. Collections cannot be guessed for polymorphic associations."
79
+ ) if reflection.options[:polymorphic] == true
80
+ end
81
+
82
+ return reflection.klass.merge(reflection.scope) if reflection.scope
83
+
84
+ conditions_from_reflection = (reflection.respond_to?(:options) && reflection.options[:conditions]) || {}
85
+ conditions_from_reflection = conditions_from_reflection.call if conditions_from_reflection.is_a?(Proc)
86
+
87
+ scope_conditions = conditions_from_reflection.empty? ? nil : {:conditions => conditions_from_reflection}
88
+ where_conditions = (scope_conditions && scope_conditions[:conditions]) || {}
89
+
90
+ reflection.klass.where(where_conditions)
91
+ end
92
+ end
93
+
94
+ # Assuming the following model:
95
+ #
96
+ # class Post < ActiveRecord::Base
97
+ # enum :status => [ :active, :archived ]
98
+ # end
99
+ #
100
+ # We would end up with a collection like this:
101
+ #
102
+ # [["Active", "active"], ["Archived", "archived"]
103
+ #
104
+ # The first element in each array uses String#humanize, but I18n
105
+ # translations are available too. Set them with the following structure.
106
+ #
107
+ # en:
108
+ # activerecord:
109
+ # attributes:
110
+ # post:
111
+ # statuses:
112
+ # active: Custom Active Label Here
113
+ # archived: Custom Archived Label Here
114
+ def collection_from_enum
115
+ if collection_from_enum?
116
+ method_name = method.to_s
117
+
118
+ enum_options_hash = object.defined_enums[method_name]
119
+ enum_options_hash.map do |name, value|
120
+ key = "activerecord.attributes.#{object.model_name.i18n_key}.#{method_name.pluralize}.#{name}"
121
+ label = ::I18n.translate(key, :default => name.humanize)
122
+ [label, name]
123
+ end
124
+ end
125
+ end
126
+
127
+ def collection_from_enum?
128
+ object.respond_to?(:defined_enums) && object.defined_enums.has_key?(method.to_s)
129
+ end
130
+
131
+ def collection_for_boolean
132
+ true_text = options[:true] || Formtastic::I18n.t(:yes)
133
+ false_text = options[:false] || Formtastic::I18n.t(:no)
134
+
135
+ # TODO options[:value_as_class] = true unless options.key?(:value_as_class)
136
+
137
+ [ [true_text, true], [false_text, false] ]
138
+ end
139
+
140
+ def send_or_call(duck, object)
141
+ if duck.respond_to?(:call)
142
+ duck.call(object)
143
+ elsif object.respond_to? duck.to_sym
144
+ object.send(duck)
145
+ end
146
+ end
147
+
148
+ # Avoids an issue where `send_or_call` can be a String and duck can be something simple like
149
+ # `:first`, which obviously String responds to.
150
+ def send_or_call_or_object(duck, object)
151
+ return object if object.is_a?(String) || object.is_a?(Integer) || object.is_a?(Symbol) # TODO what about other classes etc?
152
+ send_or_call(duck, object)
153
+ end
154
+
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Database
6
+
7
+ def column
8
+ if object.respond_to?(:column_for_attribute)
9
+ object.column_for_attribute(method)
10
+ end
11
+ end
12
+
13
+ def column?
14
+ !column.nil?
15
+ end
16
+
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module DatetimePickerish
6
+ include Base::Placeholder
7
+
8
+ def html_input_type
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def default_size
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def value
17
+ raise NotImplementedError
18
+ end
19
+
20
+ def input_html_options
21
+ super.merge(extra_input_html_options)
22
+ end
23
+
24
+ def extra_input_html_options
25
+ {
26
+ :type => html_input_type,
27
+ :size => size,
28
+ :maxlength => maxlength,
29
+ :step => step,
30
+ :value => value
31
+ }
32
+ end
33
+
34
+ def size
35
+ return options[:size] if options.key?(:size)
36
+ return options[:input_html][:size] if options[:input_html] && options[:input_html].key?(:size)
37
+ default_size
38
+ end
39
+
40
+ def step
41
+ return step_from_macro(options[:input_html][:step]) if options[:input_html] && options[:input_html][:step] && options[:input_html][:step].is_a?(Symbol)
42
+ return options[:input_html][:step] if options[:input_html] && options[:input_html].key?(:step)
43
+ default_step
44
+ end
45
+
46
+ def maxlength
47
+ return options[:maxlength] if options.key?(:maxlength)
48
+ return options[:input_html][:maxlength] if options[:input_html] && options[:input_html].key?(:maxlength)
49
+ default_size
50
+ end
51
+
52
+ def default_maxlength
53
+ default_size
54
+ end
55
+
56
+ def default_step
57
+ 1
58
+ end
59
+
60
+ protected
61
+
62
+ def step_from_macro(sym)
63
+ case sym
64
+
65
+ # date
66
+ when :day then "1"
67
+ when :seven_days, :week then "7"
68
+ when :two_weeks, :fortnight then "14"
69
+ when :four_weeks then "28"
70
+ when :thirty_days then "30"
71
+
72
+ # time
73
+ when :second then "1"
74
+ when :minute then "60"
75
+ when :fifteen_minutes, :quarter_hour then "900"
76
+ when :thirty_minutes, :half_hour then "1800"
77
+ when :sixty_minutes, :hour then "3600"
78
+
79
+ else sym
80
+ end
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Errors
6
+
7
+ def error_html
8
+ errors? ? send(:"error_#{builder.inline_errors}_html") : +""
9
+ end
10
+
11
+ def error_sentence_html
12
+ error_class = builder.default_inline_error_class
13
+ template.content_tag(:p, errors.to_sentence, id: "#{method}_error", :class => error_class)
14
+ end
15
+
16
+ def error_list_html
17
+ error_class = builder.default_error_list_class
18
+ list_elements = []
19
+ errors.each do |error|
20
+ list_elements << template.content_tag(:li, error.html_safe)
21
+ end
22
+ template.content_tag(:ul, list_elements.join("\n").html_safe, :class => error_class)
23
+ end
24
+
25
+ def error_first_html
26
+ error_class = builder.default_inline_error_class
27
+ template.content_tag(:p, errors.first.untaint.html_safe, :class => error_class)
28
+ end
29
+
30
+ def error_none_html
31
+ +""
32
+ end
33
+
34
+ def errors?
35
+ !errors.blank?
36
+ end
37
+
38
+ def errors
39
+ errors = []
40
+ if object && object.respond_to?(:errors)
41
+ error_keys.each do |key|
42
+ errors << object.errors[key] unless object.errors[key].blank?
43
+ end
44
+ end
45
+ errors.flatten.compact.uniq
46
+ end
47
+
48
+ def error_keys
49
+ keys = [method.to_sym]
50
+ keys << builder.file_metadata_suffixes.map{|suffix| "#{method}_#{suffix}".to_sym} if file?
51
+ keys << association_primary_key if belongs_to? || has_many?
52
+ keys.flatten.compact.uniq
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Fileish
6
+
7
+ def file?
8
+ @file ||= begin
9
+ # TODO return true if self.is_a?(Formtastic::Inputs::FileInput::Woo)
10
+ object && object.respond_to?(method) && builder.file_methods.any? { |m| object.send(method).respond_to?(m) }
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+
21
+
22
+
23
+
24
+
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Hints
6
+
7
+ def hint_html
8
+ if hint?
9
+ template.content_tag(
10
+ :p,
11
+ hint_text.html_safe,
12
+ :class => builder.default_hint_class
13
+ )
14
+ end
15
+ end
16
+
17
+ def hint?
18
+ !hint_text.blank? && !hint_text.kind_of?(Hash)
19
+ end
20
+
21
+ def hint_text
22
+ localized_string(method, options[:hint], :hint)
23
+ end
24
+
25
+ def hint_text_from_options
26
+ options[:hint]
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Html
6
+
7
+ # Defines how the instance of an input should be rendered to a HTML string.
8
+ #
9
+ # @abstract Implement this method in your input class to describe how the input should render itself.
10
+ #
11
+ # @example A basic label and text field input inside a standard wrapping might look like this:
12
+ # def to_html
13
+ # input_wrapping do
14
+ # label_html <<
15
+ # builder.text_field(method, input_html_options)
16
+ # end
17
+ # end
18
+ def to_html
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def input_html_options
23
+ {
24
+ :id => dom_id,
25
+ :required => required_attribute?,
26
+ :autofocus => autofocus?,
27
+ :readonly => readonly?
28
+ }.merge(options[:input_html] || {}).merge(error_aria_attributes)
29
+ end
30
+
31
+ def dom_id
32
+ [
33
+ builder.dom_id_namespace,
34
+ sanitized_object_name,
35
+ dom_index,
36
+ association_primary_key || sanitized_method_name
37
+ ].reject { |x| x.blank? }.join('_')
38
+ end
39
+
40
+ def dom_index
41
+ if builder.options.has_key?(:index)
42
+ builder.options[:index]
43
+ elsif !builder.auto_index.blank?
44
+ # TODO there's no coverage for this case, not sure how to create a scenario for it
45
+ builder.auto_index
46
+ else
47
+ +""
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Labelling
6
+
7
+ include Formtastic::LocalizedString
8
+
9
+ def label_html
10
+ render_label? ? builder.label(input_name, label_text, label_html_options) : +"".html_safe
11
+ end
12
+
13
+ def label_html_options
14
+ {
15
+ :for => input_html_options[:id],
16
+ :class => ['label'],
17
+ }.merge(options[:label_html] || {})
18
+ end
19
+
20
+ def label_text
21
+ ((localized_label || humanized_method_name) + requirement_text).html_safe
22
+ end
23
+
24
+ # TODO: why does this need to be memoized in order to make the inputs_spec tests pass?
25
+ def requirement_text_or_proc
26
+ @requirement_text_or_proc ||= required? ? builder.required_string : builder.optional_string
27
+ end
28
+
29
+ def requirement_text
30
+ if requirement_text_or_proc.respond_to?(:call)
31
+ requirement_text_or_proc.call
32
+ else
33
+ requirement_text_or_proc
34
+ end
35
+ end
36
+
37
+ def label_from_options
38
+ options[:label]
39
+ end
40
+
41
+ def localized_label
42
+ localized_string(method, label_from_options || method, :label)
43
+ end
44
+
45
+ def render_label?
46
+ return false if options[:label] == false
47
+ true
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Naming
6
+
7
+ def as
8
+ self.class.name.split("::")[-1].underscore.gsub(/_input$/, '')
9
+ end
10
+
11
+ def sanitized_object_name
12
+ object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
13
+ end
14
+
15
+ def sanitized_method_name
16
+ @sanitized_method_name ||= method.to_s.gsub(/[\?\/\-]$/, '')
17
+ end
18
+
19
+ def attributized_method_name
20
+ method.to_s.gsub(/_id$/, '').to_sym
21
+ end
22
+
23
+ def humanized_method_name
24
+ if builder.label_str_method != :humanize
25
+ # Special case where label_str_method should trump the human_attribute_name
26
+ # TODO: is this actually a desired bheavior, or should we ditch label_str_method and
27
+ # rely purely on :human_attribute_name.
28
+ method.to_s.send(builder.label_str_method)
29
+ elsif object && object.class.respond_to?(:human_attribute_name)
30
+ object.class.human_attribute_name(method.to_s)
31
+ else
32
+ method.to_s.send(builder.label_str_method)
33
+ end
34
+ end
35
+
36
+ def input_name
37
+ association_primary_key
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Numeric
6
+ def input_html_options
7
+ defaults = super
8
+
9
+ # override rails default size - does not apply to numeric inputs
10
+ #@todo document/spec
11
+ defaults[:size] = nil
12
+
13
+ if in_option
14
+ defaults[:min] = in_option.to_a.min
15
+ defaults[:max] = in_option.to_a.max
16
+ else
17
+ defaults[:min] ||= min_option
18
+ defaults[:max] ||= max_option
19
+ end
20
+ defaults[:step] ||= step_option
21
+ defaults
22
+ end
23
+
24
+ def step_option
25
+ return options[:step] if options.key?(:step)
26
+ validation_step
27
+ end
28
+
29
+ def min_option
30
+ return options[:min] if options.key?(:min)
31
+ validation_min
32
+ end
33
+
34
+ def max_option
35
+ return options[:max] if options.key?(:max)
36
+ validation_max
37
+ end
38
+
39
+ def in_option
40
+ options[:in]
41
+ end
42
+
43
+ def wrapper_html_options
44
+ new_class = [super[:class], "numeric", "stringish"].compact.join(" ")
45
+ super.merge(:class => new_class)
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end