formtastic 1.2.4 → 3.1.5

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 (189) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +46 -0
  5. data/.yardopts +1 -0
  6. data/Appraisals +43 -0
  7. data/CHANGELOG +54 -0
  8. data/DEPRECATIONS +52 -0
  9. data/Gemfile +3 -0
  10. data/README.md +629 -0
  11. data/RELEASE_PROCESS +6 -0
  12. data/Rakefile +35 -0
  13. data/app/assets/stylesheets/formtastic.css +289 -0
  14. data/app/assets/stylesheets/formtastic_ie6.css +33 -0
  15. data/app/assets/stylesheets/formtastic_ie7.css +23 -0
  16. data/formtastic.gemspec +42 -0
  17. data/gemfiles/rails_3.2.gemfile +9 -0
  18. data/gemfiles/rails_4.0.4.gemfile +8 -0
  19. data/gemfiles/rails_4.1.gemfile +8 -0
  20. data/gemfiles/rails_4.2.gemfile +8 -0
  21. data/gemfiles/rails_4.gemfile +8 -0
  22. data/gemfiles/rails_5.0.gemfile +8 -0
  23. data/gemfiles/rails_edge.gemfile +15 -0
  24. data/lib/formtastic.rb +40 -1945
  25. data/lib/formtastic/action_class_finder.rb +18 -0
  26. data/lib/formtastic/actions.rb +11 -0
  27. data/lib/formtastic/actions/base.rb +156 -0
  28. data/lib/formtastic/actions/button_action.rb +67 -0
  29. data/lib/formtastic/actions/buttonish.rb +17 -0
  30. data/lib/formtastic/actions/input_action.rb +70 -0
  31. data/lib/formtastic/actions/link_action.rb +88 -0
  32. data/lib/formtastic/deprecation.rb +42 -0
  33. data/lib/formtastic/engine.rb +11 -0
  34. data/lib/formtastic/form_builder.rb +124 -0
  35. data/lib/formtastic/helpers.rb +16 -0
  36. data/lib/formtastic/helpers/action_helper.rb +162 -0
  37. data/lib/formtastic/helpers/actions_helper.rb +168 -0
  38. data/lib/formtastic/helpers/enum.rb +13 -0
  39. data/lib/formtastic/helpers/errors_helper.rb +81 -0
  40. data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
  41. data/lib/formtastic/helpers/file_column_detection.rb +16 -0
  42. data/lib/formtastic/helpers/form_helper.rb +203 -0
  43. data/lib/formtastic/helpers/input_helper.rb +407 -0
  44. data/lib/formtastic/helpers/inputs_helper.rb +411 -0
  45. data/lib/formtastic/helpers/reflection.rb +37 -0
  46. data/lib/formtastic/html_attributes.rb +32 -0
  47. data/lib/formtastic/i18n.rb +4 -2
  48. data/lib/formtastic/input_class_finder.rb +18 -0
  49. data/lib/formtastic/inputs.rb +39 -0
  50. data/lib/formtastic/inputs/base.rb +76 -0
  51. data/lib/formtastic/inputs/base/associations.rb +31 -0
  52. data/lib/formtastic/inputs/base/choices.rb +108 -0
  53. data/lib/formtastic/inputs/base/collections.rb +159 -0
  54. data/lib/formtastic/inputs/base/database.rb +22 -0
  55. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  56. data/lib/formtastic/inputs/base/errors.rb +58 -0
  57. data/lib/formtastic/inputs/base/fileish.rb +23 -0
  58. data/lib/formtastic/inputs/base/hints.rb +31 -0
  59. data/lib/formtastic/inputs/base/html.rb +53 -0
  60. data/lib/formtastic/inputs/base/labelling.rb +52 -0
  61. data/lib/formtastic/inputs/base/naming.rb +42 -0
  62. data/lib/formtastic/inputs/base/numeric.rb +50 -0
  63. data/lib/formtastic/inputs/base/options.rb +17 -0
  64. data/lib/formtastic/inputs/base/placeholder.rb +17 -0
  65. data/lib/formtastic/inputs/base/stringish.rb +38 -0
  66. data/lib/formtastic/inputs/base/timeish.rb +241 -0
  67. data/lib/formtastic/inputs/base/validations.rb +215 -0
  68. data/lib/formtastic/inputs/base/wrapping.rb +50 -0
  69. data/lib/formtastic/inputs/boolean_input.rb +118 -0
  70. data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
  71. data/lib/formtastic/inputs/color_input.rb +42 -0
  72. data/lib/formtastic/inputs/country_input.rb +86 -0
  73. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  74. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  75. data/lib/formtastic/inputs/date_select_input.rb +34 -0
  76. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  77. data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
  78. data/lib/formtastic/inputs/email_input.rb +41 -0
  79. data/lib/formtastic/inputs/file_input.rb +42 -0
  80. data/lib/formtastic/inputs/hidden_input.rb +62 -0
  81. data/lib/formtastic/inputs/number_input.rb +88 -0
  82. data/lib/formtastic/inputs/password_input.rb +41 -0
  83. data/lib/formtastic/inputs/phone_input.rb +42 -0
  84. data/lib/formtastic/inputs/radio_input.rb +163 -0
  85. data/lib/formtastic/inputs/range_input.rb +95 -0
  86. data/lib/formtastic/inputs/search_input.rb +41 -0
  87. data/lib/formtastic/inputs/select_input.rb +235 -0
  88. data/lib/formtastic/inputs/string_input.rb +36 -0
  89. data/lib/formtastic/inputs/text_input.rb +48 -0
  90. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  91. data/lib/formtastic/inputs/time_select_input.rb +38 -0
  92. data/lib/formtastic/inputs/time_zone_input.rb +58 -0
  93. data/lib/formtastic/inputs/url_input.rb +41 -0
  94. data/lib/formtastic/localized_string.rb +17 -0
  95. data/lib/formtastic/localizer.rb +152 -0
  96. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  97. data/lib/formtastic/util.rb +35 -16
  98. data/lib/formtastic/version.rb +3 -0
  99. data/lib/generators/formtastic/form/form_generator.rb +64 -37
  100. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  101. data/lib/generators/formtastic/install/install_generator.rb +13 -5
  102. data/lib/generators/templates/_form.html.erb +10 -4
  103. data/lib/generators/templates/_form.html.haml +8 -4
  104. data/lib/generators/templates/_form.html.slim +8 -0
  105. data/lib/generators/templates/formtastic.rb +77 -44
  106. data/lib/generators/templates/input.rb +19 -0
  107. data/lib/locale/en.yml +3 -0
  108. data/sample/basic_inputs.html +224 -0
  109. data/sample/config.ru +69 -0
  110. data/sample/index.html +14 -0
  111. data/spec/action_class_finder_spec.rb +12 -0
  112. data/spec/actions/button_action_spec.rb +63 -0
  113. data/spec/actions/generic_action_spec.rb +521 -0
  114. data/spec/actions/input_action_spec.rb +59 -0
  115. data/spec/actions/link_action_spec.rb +92 -0
  116. data/spec/builder/custom_builder_spec.rb +116 -0
  117. data/spec/builder/error_proc_spec.rb +27 -0
  118. data/spec/builder/semantic_fields_for_spec.rb +142 -0
  119. data/spec/fast_spec_helper.rb +12 -0
  120. data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
  121. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  122. data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
  123. data/spec/helpers/action_helper_spec.rb +19 -0
  124. data/spec/helpers/actions_helper_spec.rb +143 -0
  125. data/spec/helpers/form_helper_spec.rb +218 -0
  126. data/spec/helpers/input_helper_spec.rb +6 -0
  127. data/spec/helpers/inputs_helper_spec.rb +655 -0
  128. data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
  129. data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
  130. data/spec/helpers/reflection_helper_spec.rb +32 -0
  131. data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
  132. data/spec/i18n_spec.rb +210 -0
  133. data/spec/input_class_finder_spec.rb +10 -0
  134. data/spec/inputs/base/collections_spec.rb +76 -0
  135. data/spec/inputs/base/validations_spec.rb +342 -0
  136. data/spec/inputs/boolean_input_spec.rb +254 -0
  137. data/spec/inputs/check_boxes_input_spec.rb +546 -0
  138. data/spec/inputs/color_input_spec.rb +97 -0
  139. data/spec/inputs/country_input_spec.rb +133 -0
  140. data/spec/inputs/custom_input_spec.rb +55 -0
  141. data/spec/inputs/datalist_input_spec.rb +61 -0
  142. data/spec/inputs/date_picker_input_spec.rb +449 -0
  143. data/spec/inputs/date_select_input_spec.rb +235 -0
  144. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  145. data/spec/inputs/datetime_select_input_spec.rb +193 -0
  146. data/spec/inputs/email_input_spec.rb +85 -0
  147. data/spec/inputs/file_input_spec.rb +89 -0
  148. data/spec/inputs/hidden_input_spec.rb +135 -0
  149. data/spec/inputs/include_blank_spec.rb +78 -0
  150. data/spec/inputs/label_spec.rb +149 -0
  151. data/spec/inputs/number_input_spec.rb +815 -0
  152. data/spec/inputs/password_input_spec.rb +99 -0
  153. data/spec/inputs/phone_input_spec.rb +85 -0
  154. data/spec/inputs/placeholder_spec.rb +71 -0
  155. data/spec/inputs/radio_input_spec.rb +328 -0
  156. data/spec/inputs/range_input_spec.rb +505 -0
  157. data/spec/inputs/readonly_spec.rb +50 -0
  158. data/spec/inputs/search_input_spec.rb +84 -0
  159. data/spec/inputs/select_input_spec.rb +615 -0
  160. data/spec/inputs/string_input_spec.rb +260 -0
  161. data/spec/inputs/text_input_spec.rb +187 -0
  162. data/spec/inputs/time_picker_input_spec.rb +455 -0
  163. data/spec/inputs/time_select_input_spec.rb +248 -0
  164. data/spec/inputs/time_zone_input_spec.rb +143 -0
  165. data/spec/inputs/url_input_spec.rb +85 -0
  166. data/spec/inputs/with_options_spec.rb +43 -0
  167. data/spec/localizer_spec.rb +130 -0
  168. data/spec/namespaced_class_finder_spec.rb +79 -0
  169. data/spec/spec.opts +2 -0
  170. data/spec/spec_helper.rb +525 -0
  171. data/spec/support/custom_macros.rb +564 -0
  172. data/spec/support/deprecation.rb +6 -0
  173. data/spec/support/shared_examples.rb +1313 -0
  174. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  175. data/spec/support/test_environment.rb +31 -0
  176. data/spec/util_spec.rb +66 -0
  177. metadata +434 -161
  178. data/README.textile +0 -682
  179. data/generators/form/USAGE +0 -16
  180. data/generators/form/form_generator.rb +0 -111
  181. data/generators/formtastic/formtastic_generator.rb +0 -26
  182. data/init.rb +0 -5
  183. data/lib/formtastic/layout_helper.rb +0 -12
  184. data/lib/formtastic/railtie.rb +0 -14
  185. data/lib/generators/templates/formtastic.css +0 -145
  186. data/lib/generators/templates/formtastic_changes.css +0 -14
  187. data/lib/generators/templates/rails2/_form.html.erb +0 -5
  188. data/lib/generators/templates/rails2/_form.html.haml +0 -4
  189. data/rails/init.rb +0 -2
@@ -0,0 +1,99 @@
1
+ module Formtastic
2
+ # This class implements class resolution in a namespace chain. It
3
+ # is used both by Formtastic::Helpers::InputHelper and
4
+ # Formtastic::Helpers::ActionHelper to look up action and input classes.
5
+ #
6
+ # @example Implementing own class finder
7
+ # # You can implement own class finder that for example prefixes the class name or uses custom module.
8
+ # class MyInputClassFinder < Formtastic::NamespacedClassFinder
9
+ # def initialize(namespaces)
10
+ # super [MyNamespace] + namespaces # first lookup in MyNamespace then the defaults
11
+ # end
12
+ #
13
+ # private
14
+ #
15
+ # def class_name(as)
16
+ # "My#{super}Input" # for example MyStringInput
17
+ # end
18
+ # end
19
+ #
20
+ # # in config/initializers/formtastic.rb
21
+ # Formtastic::FormBuilder.input_class_finder = MyInputClassFinder
22
+ #
23
+
24
+ class NamespacedClassFinder
25
+ attr_reader :namespaces # @private
26
+
27
+ # @private
28
+ class NotFoundError < NameError
29
+ end
30
+
31
+ def self.use_const_defined?
32
+ defined?(Rails) && ::Rails.application && ::Rails.application.config.respond_to?(:eager_load) && ::Rails.application.config.eager_load
33
+ end
34
+
35
+ # @param namespaces [Array<Module>]
36
+ def initialize(namespaces)
37
+ @namespaces = namespaces.flatten
38
+ @cache = {}
39
+ end
40
+
41
+ # Looks up the given reference in the configured namespaces.
42
+ #
43
+ # Two finder methods are provided, one for development tries to
44
+ # reference the constant directly, triggering Rails' autoloading
45
+ # const_missing machinery; the second one instead for production
46
+ # checks with .const_defined before referencing the constant.
47
+ #
48
+ def find(as)
49
+ @cache[as] ||= resolve(as)
50
+ end
51
+
52
+ def resolve(as)
53
+ class_name = class_name(as)
54
+
55
+ finder(class_name) or raise NotFoundError, "class #{class_name}"
56
+ end
57
+
58
+ # Converts symbol to class name
59
+ # Overridden in subclasses to create `StringInput` and `ButtonAction`
60
+ # @example
61
+ # class_name(:string) == "String"
62
+
63
+ def class_name(as)
64
+ as.to_s.camelize
65
+ end
66
+
67
+ private
68
+
69
+ if use_const_defined?
70
+ def finder(class_name) # @private
71
+ find_with_const_defined(class_name)
72
+ end
73
+ else
74
+ def finder(class_name) # @private
75
+ find_by_trying(class_name)
76
+ end
77
+ end
78
+
79
+ # Looks up the given class name in the configured namespaces in order,
80
+ # returning the first one that has the class name constant defined.
81
+ def find_with_const_defined(class_name)
82
+ @namespaces.find do |namespace|
83
+ if namespace.const_defined?(class_name)
84
+ break namespace.const_get(class_name)
85
+ end
86
+ end
87
+ end
88
+
89
+ # Use auto-loading in development environment
90
+ def find_by_trying(class_name)
91
+ @namespaces.find do |namespace|
92
+ begin
93
+ break namespace.const_get(class_name)
94
+ rescue NameError
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Adapted from the rails3 compatibility shim in Haml 2.2
4
4
  module Formtastic
5
+ # @private
5
6
  module Util
6
7
  extend self
7
8
  ## Rails XSS Safety
@@ -13,26 +14,44 @@ module Formtastic
13
14
  # @param text [String]
14
15
  # @return [String] `text`, marked as HTML-safe
15
16
  def html_safe(text)
16
- return text if text.nil?
17
- return text.html_safe if defined?(ActiveSupport::SafeBuffer)
18
- return text.html_safe! if text.respond_to?(:html_safe!)
19
- text
17
+ if text.respond_to?(:html_safe)
18
+ text.html_safe
19
+ else
20
+ text
21
+ end
20
22
  end
21
23
 
22
- def rails_safe_buffer_class
23
- # It's important that we check ActiveSupport first,
24
- # because in Rails 2.3.6 ActionView::SafeBuffer exists
25
- # but is a deprecated proxy object.
26
- return ActiveSupport::SafeBuffer if defined?(ActiveSupport::SafeBuffer)
27
- return ActionView::SafeBuffer
24
+ def rails3?
25
+ match?(rails_version, "~> 3.0")
28
26
  end
29
27
 
30
- def rails3?
31
- version=
32
- if defined?(ActionPack::VERSION::MAJOR)
33
- ActionPack::VERSION::MAJOR
34
- end
35
- !version.blank? && version >= 3
28
+ def rails4?
29
+ match?(rails_version, "~> 4.0")
30
+ end
31
+
32
+ def rails4_0?
33
+ match?(rails_version, "~> 4.0.0")
34
+ end
35
+
36
+ def rails4_1?
37
+ match?(rails_version, "~> 4.1.0")
38
+ end
39
+
40
+ def deprecated_version_of_rails?
41
+ match?(rails_version, "< #{minimum_version_of_rails}")
36
42
  end
43
+
44
+ def minimum_version_of_rails
45
+ "4.1.0"
46
+ end
47
+
48
+ def rails_version
49
+ ::Rails::VERSION::STRING
50
+ end
51
+
52
+ def match?(version, dependency)
53
+ Gem::Dependency.new("formtastic", dependency).match?("formtastic", version)
54
+ end
55
+
37
56
  end
38
57
  end
@@ -0,0 +1,3 @@
1
+ module Formtastic
2
+ VERSION = "3.1.5"
3
+ end
@@ -1,54 +1,59 @@
1
1
  # encoding: utf-8
2
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
3
22
  class FormGenerator < Rails::Generators::NamedBase
4
- desc "Generates formtastic form code based on an existing model. By default the " <<
5
- "generated code will be printed out directly in the terminal, and also copied " <<
6
- "to clipboard. Can optionally be saved into partial directly."
23
+ desc "Generates a Formtastic form partial based on an existing model."
7
24
 
8
- argument :name, :type => :string, :required => true, :banner => 'ExistingModelName'
9
- argument :attributes, :type => :array, :default => [], :banner => 'field:type field:type'
25
+ argument :name, :type => :string, :required => true, :banner => 'MODEL_NAME'
26
+ argument :attributes, :type => :array, :default => [], :banner => 'attribute attribute'
10
27
 
11
- class_option :haml, :type => :boolean, :default => false, :group => :formtastic,
12
- :desc => "Generate HAML instead of ERB"
28
+ source_root File.expand_path('../../../templates', __FILE__)
13
29
 
14
- class_option :partial, :type => :boolean, :default => false, :group => :formtastic,
15
- :desc => 'Generate a form partial in the model views path, i.e. "_form.html.erb" or "_form.html.haml"'
30
+ class_option :template_engine
16
31
 
17
- class_option :controller, :type => :string, :default => false, :group => :formtastic,
18
- :desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
32
+ class_option :copy, :type => :boolean, :default => false, :group => :formtastic,
33
+ :desc => 'Copy the generated code the clipboard instead of generating a partial file."'
19
34
 
20
- source_root File.expand_path('../../../templates', __FILE__)
35
+ class_option :controller, :type => :string, :default => false, :group => :formtastic,
36
+ :desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
21
37
 
22
38
  def create_or_show
23
- @attributes = self.columns if @attributes.empty?
39
+ @attributes = reflected_attributes if @attributes.empty?
24
40
 
25
- if options[:partial]
26
- empty_directory "app/views/#{controller_path}"
27
- template "_form.html.#{template_type}", "app/views/#{controller_path}/_form.html.#{template_type}"
28
- else
29
- template = File.read("#{self.class.source_root}/_form.html.#{template_type}")
41
+ engine = options[:template_engine]
42
+
43
+ if options[:copy]
44
+ template = File.read("#{self.class.source_root}/_form.html.#{engine}")
30
45
  erb = ERB.new(template, nil, '-')
31
46
  generated_code = erb.result(binding).strip rescue nil
32
-
33
- puts "# ---------------------------------------------------------"
34
- puts "# GENERATED FORMTASTIC CODE"
35
- puts "# ---------------------------------------------------------"
36
- puts
37
- puts generated_code || "Nothing could be generated - model exists?"
38
- puts
39
- puts "# ---------------------------------------------------------"
40
- puts "Copied to clipboard - just paste it!" if save_to_clipboard(generated_code)
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}"
41
52
  end
42
53
  end
43
54
 
44
55
  protected
45
56
 
46
- IGNORED_COLUMNS = [:updated_at, :created_at].freeze
47
-
48
- def template_type
49
- @template_type ||= options[:haml] ? :haml : :erb
50
- end
51
-
52
57
  def controller_path
53
58
  @controller_path ||= if options[:controller]
54
59
  options[:controller].underscore
@@ -57,8 +62,29 @@ module Formtastic
57
62
  end
58
63
  end
59
64
 
60
- def columns
61
- @columns ||= self.name.camelize.constantize.content_columns.reject { |column| IGNORED_COLUMNS.include?(column.name.to_sym) }
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
62
88
  end
63
89
 
64
90
  def save_to_clipboard(data)
@@ -75,10 +101,11 @@ module Formtastic
75
101
  `echo "#{data}" | xsel --clipboard` || `echo "#{data}" | xclip`
76
102
  end
77
103
  rescue LoadError
78
- false
104
+ false
79
105
  else
80
- true
106
+ true
81
107
  end
82
108
  end
109
+
83
110
  end
84
111
  end
@@ -0,0 +1,46 @@
1
+ module Formtastic
2
+
3
+ # Modify existing inputs, subclass them, or create your own from scratch.
4
+ # @example
5
+ # !!!shell
6
+ # $ rails generate formtastic:input HatSize
7
+
8
+ # @example Define input name using underscore convention
9
+ # !!!shell
10
+ # $ rails generate formtastic:input hat_size
11
+
12
+ # @example Override an existing input behavior
13
+ # !!!shell
14
+ # $ rails generate formtastic:input string --extend
15
+
16
+ # @example Extend an existing input behavior
17
+ # !!!shell
18
+ # $ rails generate formtastic:input FlexibleText --extend string
19
+ class InputGenerator < Rails::Generators::NamedBase
20
+
21
+ argument :name, :type => :string, :required => true, :banner => 'FILE_NAME'
22
+
23
+ source_root File.expand_path('../../../templates', __FILE__)
24
+
25
+ class_option :extend
26
+
27
+ def create
28
+ normalize_file_name
29
+ define_extension_sentence
30
+ template "input.rb", "app/inputs/#{name.underscore}_input.rb"
31
+ end
32
+
33
+ protected
34
+
35
+ def normalize_file_name
36
+ name.chomp!("Input") if name.ends_with?("Input")
37
+ name.chomp!("_input") if name.ends_with?("_input")
38
+ name.chomp!("input") if name.ends_with?("input")
39
+ end
40
+
41
+ def define_extension_sentence
42
+ @extension_sentence = "< Formtastic::Inputs::#{name.camelize}Input" if options[:extend] == "extend"
43
+ @extension_sentence ||= "< Formtastic::Inputs::#{options[:extend].camelize}Input" if options[:extend]
44
+ end
45
+ end
46
+ end
@@ -1,15 +1,23 @@
1
1
  # encoding: utf-8
2
+
2
3
  module Formtastic
4
+ # Copies a config initializer to config/initializers/formtastic.rb
5
+ #
6
+ # @example
7
+ # !!!shell
8
+ # $ rails generate formtastic:install
3
9
  class InstallGenerator < Rails::Generators::Base
4
- desc "Copies formtastic.css and formtastic_changes.css to public/stylesheets/ and a config initializer to config/initializers/formtastic_config.rb"
5
-
6
10
  source_root File.expand_path('../../../templates', __FILE__)
11
+ class_option :template_engine
7
12
 
13
+ desc "Copies a config initializer to config/initializers/formtastic.rb"
8
14
  def copy_files
9
- template 'formtastic.rb', 'config/initializers/formtastic.rb'
15
+ copy_file 'formtastic.rb', 'config/initializers/formtastic.rb'
16
+ end
10
17
 
11
- template 'formtastic.css', 'public/stylesheets/formtastic.css'
12
- template 'formtastic_changes.css', 'public/stylesheets/formtastic_changes.css'
18
+ def copy_scaffold_template
19
+ engine = options[:template_engine]
20
+ copy_file "_form.html.#{engine}", "lib/templates/#{engine}/scaffold/_form.html.#{engine}"
13
21
  end
14
22
  end
15
23
  end
@@ -1,5 +1,11 @@
1
- <%%= f.inputs do %>
2
- <% attributes.each do |attribute| -%>
3
- <%%= f.input :<%= attribute.name %> %>
4
- <% end -%>
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 %>
5
11
  <%% end %>
@@ -1,4 +1,8 @@
1
- = f.inputs do
2
- <% attributes.each do |attribute| -%>
3
- = f.input :<%= attribute.name %>
4
- <% end -%>
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
+
7
+ = f.actions do
8
+ = f.action :submit, :as => :input
@@ -0,0 +1,8 @@
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
+
7
+ = f.actions do
8
+ = f.action :submit, as: :input
@@ -1,80 +1,113 @@
1
1
  # encoding: utf-8
2
2
 
3
- # --------------------------------------------------------------------------------------------------
4
- # Please note: If you're subclassing Formtastic::SemanticFormBuilder in a Rails 3 project,
5
- # Formtastic uses class_attribute for these configuration attributes instead of the deprecated
6
- # class_inheritable_attribute. The behaviour is slightly different with subclasses (especially
7
- # around attributes with Hash or Array) values, so make sure you understand what's happening.
8
- # See the documentation for class_attribute in ActiveSupport for more information.
9
- # --------------------------------------------------------------------------------------------------
10
-
11
3
  # Set the default text field size when input is a string. Default is nil.
12
- # Formtastic::SemanticFormBuilder.default_text_field_size = 50
4
+ # Formtastic::FormBuilder.default_text_field_size = 50
13
5
 
14
6
  # Set the default text area height when input is a text. Default is 20.
15
- # Formtastic::SemanticFormBuilder.default_text_area_height = 5
7
+ # Formtastic::FormBuilder.default_text_area_height = 5
16
8
 
17
9
  # Set the default text area width when input is a text. Default is nil.
18
- # Formtastic::SemanticFormBuilder.default_text_area_width = 50
10
+ # Formtastic::FormBuilder.default_text_area_width = 50
19
11
 
20
12
  # Should all fields be considered "required" by default?
21
- # Rails 2 only, ignored by Rails 3 because it will never fall back to this default.
22
13
  # Defaults to true.
23
- # Formtastic::SemanticFormBuilder.all_fields_required_by_default = true
14
+ # Formtastic::FormBuilder.all_fields_required_by_default = true
24
15
 
25
16
  # Should select fields have a blank option/prompt by default?
26
17
  # Defaults to true.
27
- # Formtastic::SemanticFormBuilder.include_blank_for_select_by_default = true
18
+ # Formtastic::FormBuilder.include_blank_for_select_by_default = true
28
19
 
29
- # Set the string that will be appended to the labels/fieldsets which are required
20
+ # Set the string that will be appended to the labels/fieldsets which are required.
30
21
  # It accepts string or procs and the default is a localized version of
31
22
  # '<abbr title="required">*</abbr>'. In other words, if you configure formtastic.required
32
23
  # in your locale, it will replace the abbr title properly. But if you don't want to use
33
- # abbr tag, you can simply give a string as below
34
- # Formtastic::SemanticFormBuilder.required_string = "(required)"
24
+ # abbr tag, you can simply give a string as below.
25
+ # Formtastic::FormBuilder.required_string = "(required)"
35
26
 
36
- # Set the string that will be appended to the labels/fieldsets which are optional
37
- # Defaults to an empty string ("") and also accepts procs (see required_string above)
38
- # Formtastic::SemanticFormBuilder.optional_string = "(optional)"
27
+ # Set the string that will be appended to the labels/fieldsets which are optional.
28
+ # Defaults to an empty string ("") and also accepts procs (see required_string above).
29
+ # Formtastic::FormBuilder.optional_string = "(optional)"
39
30
 
40
31
  # Set the way inline errors will be displayed.
41
32
  # Defaults to :sentence, valid options are :sentence, :list, :first and :none
42
- # Formtastic::SemanticFormBuilder.inline_errors = :sentence
33
+ # Formtastic::FormBuilder.inline_errors = :sentence
43
34
  # Formtastic uses the following classes as default for hints, inline_errors and error list
44
35
 
45
- # If you override the class here, please ensure to override it in your formtastic_changes.css stylesheet as well
46
- # Formtastic::SemanticFormBuilder.default_hint_class = "inline-hints"
47
- # Formtastic::SemanticFormBuilder.default_inline_error_class = "inline-errors"
48
- # Formtastic::SemanticFormBuilder.default_error_list_class = "errors"
36
+ # If you override the class here, please ensure to override it in your stylesheets as well.
37
+ # Formtastic::FormBuilder.default_hint_class = "inline-hints"
38
+ # Formtastic::FormBuilder.default_inline_error_class = "inline-errors"
39
+ # Formtastic::FormBuilder.default_error_list_class = "errors"
49
40
 
50
41
  # Set the method to call on label text to transform or format it for human-friendly
51
42
  # reading when formtastic is used without object. Defaults to :humanize.
52
- # Formtastic::SemanticFormBuilder.label_str_method = :humanize
43
+ # Formtastic::FormBuilder.label_str_method = :humanize
53
44
 
54
45
  # Set the array of methods to try calling on parent objects in :select and :radio inputs
55
46
  # for the text inside each @<option>@ tag or alongside each radio @<input>@. The first method
56
47
  # that is found on the object will be used.
57
48
  # Defaults to ["to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
58
- # Formtastic::SemanticFormBuilder.collection_label_methods = [
49
+ # Formtastic::FormBuilder.collection_label_methods = [
59
50
  # "to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"]
60
51
 
61
- # Formtastic by default renders inside li tags the input, hints and then
62
- # errors messages. Sometimes you want the hints to be rendered first than
63
- # the input, in the following order: hints, input and errors. You can
64
- # customize it doing just as below:
65
- # Formtastic::SemanticFormBuilder.inline_order = [:input, :hints, :errors]
66
-
67
- # Additionally, you can customize the order for specific types of inputs.
68
- # This is configured on a type basis and if a type is not found it will
69
- # fall back to the default order as defined by #inline_order
70
- # Formtastic::SemanticFormBuilder.custom_inline_order[:checkbox] = [:errors, :hints, :input]
71
- # Formtastic::SemanticFormBuilder.custom_inline_order[:select] = [:hints, :input, :errors]
72
-
73
52
  # Specifies if labels/hints for input fields automatically be looked up using I18n.
74
- # Default value: false. Overridden for specific fields by setting value to true,
53
+ # Default value: true. Overridden for specific fields by setting value to true,
75
54
  # i.e. :label => true, or :hint => true (or opposite depending on initialized value)
76
- # Formtastic::SemanticFormBuilder.i18n_lookups_by_default = false
55
+ # Formtastic::FormBuilder.i18n_lookups_by_default = false
77
56
 
78
- # You can add custom inputs or override parts of Formtastic by subclassing SemanticFormBuilder and
79
- # specifying that class here. Defaults to SemanticFormBuilder.
80
- # Formtastic::SemanticFormHelper.builder = MyCustomBuilder
57
+ # Specifies if I18n lookups of the default I18n Localizer should be cached to improve performance.
58
+ # Defaults to true.
59
+ # Formtastic::FormBuilder.i18n_cache_lookups = false
60
+
61
+ # Specifies the class to use for localization lookups. You can create your own
62
+ # class and use it instead by subclassing Formtastic::Localizer (which is the default).
63
+ # Formtastic::FormBuilder.i18n_localizer = MyOwnLocalizer
64
+
65
+ # You can add custom inputs or override parts of Formtastic by subclassing Formtastic::FormBuilder and
66
+ # specifying that class here. Defaults to Formtastic::FormBuilder.
67
+ # Formtastic::Helpers::FormHelper.builder = MyCustomBuilder
68
+
69
+ # All formtastic forms have a class that indicates that they are just that. You
70
+ # can change it to any class you want.
71
+ # Formtastic::Helpers::FormHelper.default_form_class = 'formtastic'
72
+
73
+ # Formtastic will infer a class name from the model, array, string or symbol you pass to the
74
+ # form builder. You can customize the way that class is presented by overriding
75
+ # this proc.
76
+ # Formtastic::Helpers::FormHelper.default_form_model_class_proc = proc { |model_class_name| model_class_name }
77
+
78
+ # Allows to set a custom field_error_proc wrapper. By default this wrapper
79
+ # is disabled since `formtastic` already adds an error class to the LI tag
80
+ # containing the input.
81
+ # Formtastic::Helpers::FormHelper.formtastic_field_error_proc = proc { |html_tag, instance_tag| html_tag }
82
+
83
+ # You can opt-in to Formtastic's use of the HTML5 `required` attribute on `<input>`, `<select>`
84
+ # and `<textarea>` tags by setting this to true (defaults to false).
85
+ # Formtastic::FormBuilder.use_required_attribute = false
86
+
87
+ # You can opt-in to new HTML5 browser validations (for things like email and url inputs) by setting
88
+ # this to true. Doing so will omit the `novalidate` attribute from the `<form>` tag.
89
+ # See http://diveintohtml5.org/forms.html#validation for more info.
90
+ # Formtastic::FormBuilder.perform_browser_validations = true
91
+
92
+ # By creating custom input class finder, you can change how input classes are looked up.
93
+ # For example you can make it to search for TextInputFilter instead of TextInput.
94
+ # See # TODO: add link # for more information
95
+ # NOTE: this behavior will be default from Formtastic 4.0
96
+ Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
97
+
98
+ # Define custom namespaces in which to look up your Input classes. Default is
99
+ # to look up in the global scope and in Formtastic::Inputs.
100
+ # Formtastic::FormBuilder.input_namespaces = [ ::Object, ::MyInputsModule, ::Formtastic::Inputs ]
101
+
102
+ # By creating custom action class finder, you can change how action classes are looked up.
103
+ # For example you can make it to search for MyButtonAction instead of ButtonAction.
104
+ # See # TODO: add link # for more information
105
+ # NOTE: this behavior will be default from Formtastic 4.0
106
+ Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder
107
+
108
+ # Define custom namespaces in which to look up your Action classes. Default is
109
+ # to look up in the global scope and in Formtastic::Actions.
110
+ # Formtastic::FormBuilder.action_namespaces = [ ::Object, ::MyActionsModule, ::Formtastic::Actions ]
111
+
112
+ # Which columns to skip when automatically rendering a form without any fields specified.
113
+ # Formtastic::FormBuilder.skipped_columns = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]