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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +46 -0
- data/.yardopts +1 -0
- data/Appraisals +43 -0
- data/CHANGELOG +54 -0
- data/DEPRECATIONS +52 -0
- data/Gemfile +3 -0
- data/README.md +629 -0
- data/RELEASE_PROCESS +6 -0
- data/Rakefile +35 -0
- data/app/assets/stylesheets/formtastic.css +289 -0
- data/app/assets/stylesheets/formtastic_ie6.css +33 -0
- data/app/assets/stylesheets/formtastic_ie7.css +23 -0
- data/formtastic.gemspec +42 -0
- data/gemfiles/rails_3.2.gemfile +9 -0
- data/gemfiles/rails_4.0.4.gemfile +8 -0
- data/gemfiles/rails_4.1.gemfile +8 -0
- data/gemfiles/rails_4.2.gemfile +8 -0
- data/gemfiles/rails_4.gemfile +8 -0
- data/gemfiles/rails_5.0.gemfile +8 -0
- data/gemfiles/rails_edge.gemfile +15 -0
- data/lib/formtastic.rb +40 -1945
- data/lib/formtastic/action_class_finder.rb +18 -0
- data/lib/formtastic/actions.rb +11 -0
- data/lib/formtastic/actions/base.rb +156 -0
- data/lib/formtastic/actions/button_action.rb +67 -0
- data/lib/formtastic/actions/buttonish.rb +17 -0
- data/lib/formtastic/actions/input_action.rb +70 -0
- data/lib/formtastic/actions/link_action.rb +88 -0
- data/lib/formtastic/deprecation.rb +42 -0
- data/lib/formtastic/engine.rb +11 -0
- data/lib/formtastic/form_builder.rb +124 -0
- data/lib/formtastic/helpers.rb +16 -0
- data/lib/formtastic/helpers/action_helper.rb +162 -0
- data/lib/formtastic/helpers/actions_helper.rb +168 -0
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/errors_helper.rb +81 -0
- data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
- data/lib/formtastic/helpers/file_column_detection.rb +16 -0
- data/lib/formtastic/helpers/form_helper.rb +203 -0
- data/lib/formtastic/helpers/input_helper.rb +407 -0
- data/lib/formtastic/helpers/inputs_helper.rb +411 -0
- data/lib/formtastic/helpers/reflection.rb +37 -0
- data/lib/formtastic/html_attributes.rb +32 -0
- data/lib/formtastic/i18n.rb +4 -2
- data/lib/formtastic/input_class_finder.rb +18 -0
- data/lib/formtastic/inputs.rb +39 -0
- data/lib/formtastic/inputs/base.rb +76 -0
- data/lib/formtastic/inputs/base/associations.rb +31 -0
- data/lib/formtastic/inputs/base/choices.rb +108 -0
- data/lib/formtastic/inputs/base/collections.rb +159 -0
- data/lib/formtastic/inputs/base/database.rb +22 -0
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
- data/lib/formtastic/inputs/base/errors.rb +58 -0
- data/lib/formtastic/inputs/base/fileish.rb +23 -0
- data/lib/formtastic/inputs/base/hints.rb +31 -0
- data/lib/formtastic/inputs/base/html.rb +53 -0
- data/lib/formtastic/inputs/base/labelling.rb +52 -0
- data/lib/formtastic/inputs/base/naming.rb +42 -0
- data/lib/formtastic/inputs/base/numeric.rb +50 -0
- data/lib/formtastic/inputs/base/options.rb +17 -0
- data/lib/formtastic/inputs/base/placeholder.rb +17 -0
- data/lib/formtastic/inputs/base/stringish.rb +38 -0
- data/lib/formtastic/inputs/base/timeish.rb +241 -0
- data/lib/formtastic/inputs/base/validations.rb +215 -0
- data/lib/formtastic/inputs/base/wrapping.rb +50 -0
- data/lib/formtastic/inputs/boolean_input.rb +118 -0
- data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
- data/lib/formtastic/inputs/color_input.rb +42 -0
- data/lib/formtastic/inputs/country_input.rb +86 -0
- data/lib/formtastic/inputs/datalist_input.rb +41 -0
- data/lib/formtastic/inputs/date_picker_input.rb +93 -0
- data/lib/formtastic/inputs/date_select_input.rb +34 -0
- data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
- data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
- data/lib/formtastic/inputs/email_input.rb +41 -0
- data/lib/formtastic/inputs/file_input.rb +42 -0
- data/lib/formtastic/inputs/hidden_input.rb +62 -0
- data/lib/formtastic/inputs/number_input.rb +88 -0
- data/lib/formtastic/inputs/password_input.rb +41 -0
- data/lib/formtastic/inputs/phone_input.rb +42 -0
- data/lib/formtastic/inputs/radio_input.rb +163 -0
- data/lib/formtastic/inputs/range_input.rb +95 -0
- data/lib/formtastic/inputs/search_input.rb +41 -0
- data/lib/formtastic/inputs/select_input.rb +235 -0
- data/lib/formtastic/inputs/string_input.rb +36 -0
- data/lib/formtastic/inputs/text_input.rb +48 -0
- data/lib/formtastic/inputs/time_picker_input.rb +99 -0
- data/lib/formtastic/inputs/time_select_input.rb +38 -0
- data/lib/formtastic/inputs/time_zone_input.rb +58 -0
- data/lib/formtastic/inputs/url_input.rb +41 -0
- data/lib/formtastic/localized_string.rb +17 -0
- data/lib/formtastic/localizer.rb +152 -0
- data/lib/formtastic/namespaced_class_finder.rb +99 -0
- data/lib/formtastic/util.rb +35 -16
- data/lib/formtastic/version.rb +3 -0
- data/lib/generators/formtastic/form/form_generator.rb +64 -37
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/formtastic/install/install_generator.rb +13 -5
- data/lib/generators/templates/_form.html.erb +10 -4
- data/lib/generators/templates/_form.html.haml +8 -4
- data/lib/generators/templates/_form.html.slim +8 -0
- data/lib/generators/templates/formtastic.rb +77 -44
- data/lib/generators/templates/input.rb +19 -0
- data/lib/locale/en.yml +3 -0
- data/sample/basic_inputs.html +224 -0
- data/sample/config.ru +69 -0
- data/sample/index.html +14 -0
- data/spec/action_class_finder_spec.rb +12 -0
- data/spec/actions/button_action_spec.rb +63 -0
- data/spec/actions/generic_action_spec.rb +521 -0
- data/spec/actions/input_action_spec.rb +59 -0
- data/spec/actions/link_action_spec.rb +92 -0
- data/spec/builder/custom_builder_spec.rb +116 -0
- data/spec/builder/error_proc_spec.rb +27 -0
- data/spec/builder/semantic_fields_for_spec.rb +142 -0
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
- data/spec/helpers/action_helper_spec.rb +19 -0
- data/spec/helpers/actions_helper_spec.rb +143 -0
- data/spec/helpers/form_helper_spec.rb +218 -0
- data/spec/helpers/input_helper_spec.rb +6 -0
- data/spec/helpers/inputs_helper_spec.rb +655 -0
- data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
- data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
- data/spec/helpers/reflection_helper_spec.rb +32 -0
- data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
- data/spec/i18n_spec.rb +210 -0
- data/spec/input_class_finder_spec.rb +10 -0
- data/spec/inputs/base/collections_spec.rb +76 -0
- data/spec/inputs/base/validations_spec.rb +342 -0
- data/spec/inputs/boolean_input_spec.rb +254 -0
- data/spec/inputs/check_boxes_input_spec.rb +546 -0
- data/spec/inputs/color_input_spec.rb +97 -0
- data/spec/inputs/country_input_spec.rb +133 -0
- data/spec/inputs/custom_input_spec.rb +55 -0
- data/spec/inputs/datalist_input_spec.rb +61 -0
- data/spec/inputs/date_picker_input_spec.rb +449 -0
- data/spec/inputs/date_select_input_spec.rb +235 -0
- data/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/spec/inputs/datetime_select_input_spec.rb +193 -0
- data/spec/inputs/email_input_spec.rb +85 -0
- data/spec/inputs/file_input_spec.rb +89 -0
- data/spec/inputs/hidden_input_spec.rb +135 -0
- data/spec/inputs/include_blank_spec.rb +78 -0
- data/spec/inputs/label_spec.rb +149 -0
- data/spec/inputs/number_input_spec.rb +815 -0
- data/spec/inputs/password_input_spec.rb +99 -0
- data/spec/inputs/phone_input_spec.rb +85 -0
- data/spec/inputs/placeholder_spec.rb +71 -0
- data/spec/inputs/radio_input_spec.rb +328 -0
- data/spec/inputs/range_input_spec.rb +505 -0
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/search_input_spec.rb +84 -0
- data/spec/inputs/select_input_spec.rb +615 -0
- data/spec/inputs/string_input_spec.rb +260 -0
- data/spec/inputs/text_input_spec.rb +187 -0
- data/spec/inputs/time_picker_input_spec.rb +455 -0
- data/spec/inputs/time_select_input_spec.rb +248 -0
- data/spec/inputs/time_zone_input_spec.rb +143 -0
- data/spec/inputs/url_input_spec.rb +85 -0
- data/spec/inputs/with_options_spec.rb +43 -0
- data/spec/localizer_spec.rb +130 -0
- data/spec/namespaced_class_finder_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +525 -0
- data/spec/support/custom_macros.rb +564 -0
- data/spec/support/deprecation.rb +6 -0
- data/spec/support/shared_examples.rb +1313 -0
- data/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/spec/support/test_environment.rb +31 -0
- data/spec/util_spec.rb +66 -0
- metadata +434 -161
- data/README.textile +0 -682
- data/generators/form/USAGE +0 -16
- data/generators/form/form_generator.rb +0 -111
- data/generators/formtastic/formtastic_generator.rb +0 -26
- data/init.rb +0 -5
- data/lib/formtastic/layout_helper.rb +0 -12
- data/lib/formtastic/railtie.rb +0 -14
- data/lib/generators/templates/formtastic.css +0 -145
- data/lib/generators/templates/formtastic_changes.css +0 -14
- data/lib/generators/templates/rails2/_form.html.erb +0 -5
- data/lib/generators/templates/rails2/_form.html.haml +0 -4
- 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
|
data/lib/formtastic/util.rb
CHANGED
|
@@ -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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if text.respond_to?(:html_safe)
|
|
18
|
+
text.html_safe
|
|
19
|
+
else
|
|
20
|
+
text
|
|
21
|
+
end
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
def
|
|
23
|
-
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
@@ -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
|
|
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 => '
|
|
9
|
-
argument :attributes, :type => :array, :default => [], :banner => '
|
|
25
|
+
argument :name, :type => :string, :required => true, :banner => 'MODEL_NAME'
|
|
26
|
+
argument :attributes, :type => :array, :default => [], :banner => 'attribute attribute'
|
|
10
27
|
|
|
11
|
-
|
|
12
|
-
:desc => "Generate HAML instead of ERB"
|
|
28
|
+
source_root File.expand_path('../../../templates', __FILE__)
|
|
13
29
|
|
|
14
|
-
class_option :
|
|
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 :
|
|
18
|
-
|
|
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
|
-
|
|
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 =
|
|
39
|
+
@attributes = reflected_attributes if @attributes.empty?
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
61
|
-
|
|
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
|
-
|
|
104
|
+
false
|
|
79
105
|
else
|
|
80
|
-
|
|
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
|
-
|
|
15
|
+
copy_file 'formtastic.rb', 'config/initializers/formtastic.rb'
|
|
16
|
+
end
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
<%%=
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
=
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
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
|
|
46
|
-
# Formtastic::
|
|
47
|
-
# Formtastic::
|
|
48
|
-
# Formtastic::
|
|
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::
|
|
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::
|
|
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:
|
|
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::
|
|
55
|
+
# Formtastic::FormBuilder.i18n_lookups_by_default = false
|
|
77
56
|
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
# Formtastic::
|
|
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]
|