formtastic 3.1.6 → 4.0.0.rc1

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.gitignore +3 -2
  4. data/.travis.yml +28 -40
  5. data/CHANGELOG.md +49 -0
  6. data/DEPRECATIONS +1 -1
  7. data/Gemfile.lock +104 -0
  8. data/README.md +628 -629
  9. data/Rakefile +20 -1
  10. data/app/assets/stylesheets/formtastic.css +1 -1
  11. data/bin/appraisal +8 -0
  12. data/formtastic.gemspec +9 -14
  13. data/gemfiles/rails_5.2/Gemfile +5 -0
  14. data/gemfiles/rails_6.0/Gemfile +5 -0
  15. data/gemfiles/rails_edge/Gemfile +13 -0
  16. data/lib/formtastic/actions.rb +6 -3
  17. data/lib/formtastic/deprecation.rb +1 -38
  18. data/lib/formtastic/engine.rb +3 -1
  19. data/lib/formtastic/form_builder.rb +8 -24
  20. data/lib/formtastic/helpers/action_helper.rb +1 -48
  21. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  22. data/lib/formtastic/helpers/fieldset_wrapper.rb +7 -3
  23. data/lib/formtastic/helpers/input_helper.rb +18 -76
  24. data/lib/formtastic/helpers/inputs_helper.rb +12 -3
  25. data/lib/formtastic/i18n.rb +1 -1
  26. data/lib/formtastic/inputs/base/collections.rb +1 -5
  27. data/lib/formtastic/inputs/base/errors.rb +4 -4
  28. data/lib/formtastic/inputs/base/hints.rb +1 -1
  29. data/lib/formtastic/inputs/base/timeish.rb +5 -1
  30. data/lib/formtastic/inputs/base/validations.rb +19 -9
  31. data/lib/formtastic/inputs/check_boxes_input.rb +3 -3
  32. data/lib/formtastic/inputs/color_input.rb +0 -1
  33. data/lib/formtastic/inputs/select_input.rb +1 -1
  34. data/lib/formtastic/inputs.rb +32 -29
  35. data/lib/formtastic/localizer.rb +4 -3
  36. data/lib/formtastic/version.rb +1 -1
  37. data/lib/formtastic.rb +5 -11
  38. data/lib/generators/templates/formtastic.rb +4 -6
  39. data/script/integration-template.rb +71 -0
  40. data/script/integration.sh +19 -0
  41. data/spec/action_class_finder_spec.rb +1 -1
  42. data/spec/actions/button_action_spec.rb +8 -8
  43. data/spec/actions/generic_action_spec.rb +60 -60
  44. data/spec/actions/input_action_spec.rb +7 -7
  45. data/spec/actions/link_action_spec.rb +10 -10
  46. data/spec/builder/custom_builder_spec.rb +36 -20
  47. data/spec/builder/error_proc_spec.rb +4 -4
  48. data/spec/builder/semantic_fields_for_spec.rb +27 -27
  49. data/spec/generators/formtastic/form/form_generator_spec.rb +25 -25
  50. data/spec/generators/formtastic/input/input_generator_spec.rb +31 -31
  51. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  52. data/spec/helpers/action_helper_spec.rb +328 -10
  53. data/spec/helpers/actions_helper_spec.rb +17 -17
  54. data/spec/helpers/form_helper_spec.rb +33 -33
  55. data/spec/helpers/input_helper_spec.rb +975 -2
  56. data/spec/helpers/inputs_helper_spec.rb +120 -105
  57. data/spec/helpers/reflection_helper_spec.rb +3 -3
  58. data/spec/helpers/semantic_errors_helper_spec.rb +22 -22
  59. data/spec/i18n_spec.rb +26 -26
  60. data/spec/input_class_finder_spec.rb +1 -1
  61. data/spec/inputs/base/collections_spec.rb +6 -6
  62. data/spec/inputs/base/validations_spec.rb +157 -19
  63. data/spec/inputs/boolean_input_spec.rb +55 -55
  64. data/spec/inputs/check_boxes_input_spec.rb +96 -95
  65. data/spec/inputs/color_input_spec.rb +51 -63
  66. data/spec/inputs/country_input_spec.rb +20 -20
  67. data/spec/inputs/custom_input_spec.rb +2 -6
  68. data/spec/inputs/datalist_input_spec.rb +1 -1
  69. data/spec/inputs/date_picker_input_spec.rb +42 -42
  70. data/spec/inputs/date_select_input_spec.rb +51 -37
  71. data/spec/inputs/datetime_picker_input_spec.rb +46 -46
  72. data/spec/inputs/datetime_select_input_spec.rb +53 -37
  73. data/spec/inputs/email_input_spec.rb +5 -5
  74. data/spec/inputs/file_input_spec.rb +6 -6
  75. data/spec/inputs/hidden_input_spec.rb +18 -18
  76. data/spec/inputs/include_blank_spec.rb +8 -8
  77. data/spec/inputs/label_spec.rb +20 -20
  78. data/spec/inputs/number_input_spec.rb +112 -112
  79. data/spec/inputs/password_input_spec.rb +5 -5
  80. data/spec/inputs/phone_input_spec.rb +5 -5
  81. data/spec/inputs/placeholder_spec.rb +5 -5
  82. data/spec/inputs/radio_input_spec.rb +63 -65
  83. data/spec/inputs/range_input_spec.rb +66 -66
  84. data/spec/inputs/readonly_spec.rb +4 -4
  85. data/spec/inputs/search_input_spec.rb +5 -5
  86. data/spec/inputs/select_input_spec.rb +92 -96
  87. data/spec/inputs/string_input_spec.rb +23 -23
  88. data/spec/inputs/text_input_spec.rb +16 -16
  89. data/spec/inputs/time_picker_input_spec.rb +43 -43
  90. data/spec/inputs/time_select_input_spec.rb +67 -54
  91. data/spec/inputs/time_zone_input_spec.rb +19 -19
  92. data/spec/inputs/url_input_spec.rb +5 -5
  93. data/spec/inputs/with_options_spec.rb +7 -7
  94. data/spec/localizer_spec.rb +17 -17
  95. data/spec/namespaced_class_finder_spec.rb +2 -2
  96. data/spec/schema.rb +21 -0
  97. data/spec/spec_helper.rb +163 -223
  98. data/spec/support/custom_macros.rb +72 -75
  99. data/spec/support/shared_examples.rb +0 -1301
  100. data/spec/support/test_environment.rb +23 -9
  101. metadata +36 -122
  102. data/Appraisals +0 -43
  103. data/CHANGELOG +0 -54
  104. data/gemfiles/rails_3.2.gemfile +0 -9
  105. data/gemfiles/rails_4.0.4.gemfile +0 -8
  106. data/gemfiles/rails_4.1.gemfile +0 -8
  107. data/gemfiles/rails_4.2.gemfile +0 -8
  108. data/gemfiles/rails_4.gemfile +0 -8
  109. data/gemfiles/rails_5.0.gemfile +0 -8
  110. data/gemfiles/rails_edge.gemfile +0 -15
  111. data/lib/formtastic/util.rb +0 -57
  112. data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
  113. data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
  114. data/spec/util_spec.rb +0 -66
@@ -73,13 +73,11 @@ module Formtastic
73
73
  raise IndeterminableMinimumAttributeError if validation.options[:greater_than] && column? && [:float, :decimal].include?(column.type)
74
74
 
75
75
  if validation.options[:greater_than_or_equal_to]
76
- return (validation.options[:greater_than_or_equal_to].call(object)) if validation.options[:greater_than_or_equal_to].kind_of?(Proc)
77
- return (validation.options[:greater_than_or_equal_to])
76
+ return option_value(validation.options[:greater_than_or_equal_to], object)
78
77
  end
79
78
 
80
79
  if validation.options[:greater_than]
81
- return (validation.options[:greater_than].call(object) + 1) if validation.options[:greater_than].kind_of?(Proc)
82
- return (validation.options[:greater_than] + 1)
80
+ return option_value(validation.options[:greater_than], object) + 1
83
81
  end
84
82
  end
85
83
  end
@@ -94,13 +92,11 @@ module Formtastic
94
92
  raise IndeterminableMaximumAttributeError if validation.options[:less_than] && column? && [:float, :decimal].include?(column.type)
95
93
 
96
94
  if validation.options[:less_than_or_equal_to]
97
- return (validation.options[:less_than_or_equal_to].call(object)) if validation.options[:less_than_or_equal_to].kind_of?(Proc)
98
- return (validation.options[:less_than_or_equal_to])
95
+ return option_value(validation.options[:less_than_or_equal_to], object)
99
96
  end
100
97
 
101
98
  if validation.options[:less_than]
102
- return ((validation.options[:less_than].call(object)) - 1) if validation.options[:less_than].kind_of?(Proc)
103
- return (validation.options[:less_than] - 1)
99
+ return option_value(validation.options[:less_than], object) - 1
104
100
  end
105
101
  end
106
102
  end
@@ -208,8 +204,22 @@ module Formtastic
208
204
  def readonly_from_options?
209
205
  options[:input_html] && options[:input_html][:readonly]
210
206
  end
207
+
208
+ private
209
+
210
+ # Loosely based on
211
+ # https://github.com/rails/rails/blob/5-2-stable/activemodel/lib/active_model/validations/numericality.rb#L54-L59
212
+ def option_value(option, object)
213
+ case option
214
+ when Symbol
215
+ object.send(option)
216
+ when Proc
217
+ option.call(object)
218
+ else
219
+ option
220
+ end
221
+ end
211
222
  end
212
223
  end
213
224
  end
214
225
  end
215
-
@@ -99,7 +99,7 @@ module Formtastic
99
99
  end
100
100
 
101
101
  def hidden_field_for_all
102
- if hidden_fields?
102
+ if hidden_fields_for_every?
103
103
  ''
104
104
  else
105
105
  options = {}
@@ -109,7 +109,7 @@ module Formtastic
109
109
  end
110
110
  end
111
111
 
112
- def hidden_fields?
112
+ def hidden_fields_for_every?
113
113
  options[:hidden_fields]
114
114
  end
115
115
 
@@ -170,7 +170,7 @@ module Formtastic
170
170
  protected
171
171
 
172
172
  def checkbox_input(choice)
173
- if hidden_fields?
173
+ if hidden_fields_for_every?
174
174
  check_box_with_hidden_input(choice)
175
175
  else
176
176
  check_box_without_hidden_input(choice)
@@ -31,7 +31,6 @@ module Formtastic
31
31
  include Base::Placeholder
32
32
 
33
33
  def to_html
34
- raise "The :color input requires the color_field form helper, which is only available in Rails 4+" unless builder.respond_to?(:color_field)
35
34
  input_wrapping do
36
35
  label_html <<
37
36
  builder.color_field(method, input_html_options)
@@ -196,7 +196,7 @@ module Formtastic
196
196
  def extra_input_html_options
197
197
  {
198
198
  :multiple => multiple?,
199
- :name => (multiple? && Rails::VERSION::MAJOR >= 3) ? input_html_options_name_multiple : input_html_options_name
199
+ :name => multiple? ? input_html_options_name_multiple : input_html_options_name
200
200
  }
201
201
 
202
202
 
@@ -4,36 +4,39 @@ module Formtastic
4
4
 
5
5
  autoload :Base
6
6
  autoload :Basic
7
- autoload :BooleanInput
8
- autoload :CheckBoxesInput
9
- autoload :ColorInput
10
- autoload :CountryInput
11
- autoload :DatalistInput
12
- autoload :DateInput
13
- autoload :DatePickerInput
14
- autoload :DatetimePickerInput
15
- autoload :DateSelectInput
16
- autoload :DatetimeInput
17
- autoload :DatetimeSelectInput
18
- autoload :EmailInput
19
- autoload :FileInput
20
- autoload :HiddenInput
21
- autoload :NumberInput
22
- autoload :NumericInput
23
- autoload :PasswordInput
24
- autoload :PhoneInput
25
- autoload :RadioInput
26
- autoload :RangeInput
27
- autoload :SearchInput
28
- autoload :SelectInput
29
- autoload :StringInput
30
- autoload :TextInput
31
- autoload :TimeInput
32
- autoload :TimePickerInput
33
- autoload :TimeSelectInput
34
- autoload :TimeZoneInput
35
7
  autoload :Timeish
36
- autoload :UrlInput
8
+
9
+ eager_autoload do
10
+ autoload :BooleanInput
11
+ autoload :CheckBoxesInput
12
+ autoload :ColorInput
13
+ autoload :CountryInput
14
+ autoload :DatalistInput
15
+ autoload :DateInput
16
+ autoload :DatePickerInput
17
+ autoload :DatetimePickerInput
18
+ autoload :DateSelectInput
19
+ autoload :DatetimeInput
20
+ autoload :DatetimeSelectInput
21
+ autoload :EmailInput
22
+ autoload :FileInput
23
+ autoload :HiddenInput
24
+ autoload :NumberInput
25
+ autoload :NumericInput
26
+ autoload :PasswordInput
27
+ autoload :PhoneInput
28
+ autoload :RadioInput
29
+ autoload :RangeInput
30
+ autoload :SearchInput
31
+ autoload :SelectInput
32
+ autoload :StringInput
33
+ autoload :TextInput
34
+ autoload :TimeInput
35
+ autoload :TimePickerInput
36
+ autoload :TimeSelectInput
37
+ autoload :TimeZoneInput
38
+ autoload :UrlInput
39
+ end
37
40
  end
38
41
  end
39
42
 
@@ -101,7 +101,7 @@ module Formtastic
101
101
  # This is effectively what Rails label helper does for i18n lookup
102
102
  options[:scope] = [:helpers, type]
103
103
  options[:default] = defaults
104
- i18n_value = ::I18n.t(default_key, options)
104
+ i18n_value = ::I18n.t(default_key, **options)
105
105
  end
106
106
 
107
107
  # save the result to the cache
@@ -116,12 +116,13 @@ module Formtastic
116
116
 
117
117
  def normalize_model_name(name)
118
118
  if name =~ /(.+)\[(.+)\]/
119
- # Rails 3 (and 3.1?) nested builder case with :post rather than @post
119
+ # Nested builder case with :post rather than @post
120
+ # TODO: check if this is no longer required with a minimum of Rails 4.1
120
121
  [$1, $2]
121
122
  elsif builder.respond_to?(:options) && builder.options.key?(:as)
122
123
  [builder.options[:as].to_s]
123
124
  elsif builder.respond_to?(:options) && builder.options.key?(:parent_builder)
124
- # Rails 3.0 nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
125
+ # Rails 3.0+ nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
125
126
  [builder.options[:parent_builder].object_name.to_s, name]
126
127
  else
127
128
  # Non-nested case
@@ -1,3 +1,3 @@
1
1
  module Formtastic
2
- VERSION = "3.1.6"
2
+ VERSION = "4.0.0.rc1"
3
3
  end
data/lib/formtastic.rb CHANGED
@@ -4,26 +4,20 @@ require 'formtastic/engine' if defined?(::Rails)
4
4
  module Formtastic
5
5
  extend ActiveSupport::Autoload
6
6
 
7
- autoload :FormBuilder
8
7
  autoload :Helpers
9
8
  autoload :HtmlAttributes
10
- autoload :I18n
11
- autoload :Inputs
12
- autoload :Actions
13
9
  autoload :LocalizedString
14
10
  autoload :Localizer
15
- autoload :Util
16
11
  autoload :NamespacedClassFinder
17
12
  autoload :InputClassFinder
18
13
  autoload :ActionClassFinder
19
14
  autoload :Deprecation
20
15
 
21
- # @private
22
- mattr_accessor :deprecation
23
- self.deprecation = Formtastic::Deprecation.new('4.0', 'Formtastic')
24
-
25
- if defined?(::Rails) && Util.deprecated_version_of_rails?
26
- deprecation.warn("Support for Rails < #{Util.minimum_version_of_rails} will be dropped")
16
+ eager_autoload do
17
+ autoload :I18n
18
+ autoload :FormBuilder
19
+ autoload :Inputs
20
+ autoload :Actions
27
21
  end
28
22
 
29
23
  # @public
@@ -91,9 +91,8 @@
91
91
 
92
92
  # By creating custom input class finder, you can change how input classes are looked up.
93
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
94
+ # See https://github.com/justinfrench/formtastic/wiki/Custom-Class-Finders
95
+ # Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
97
96
 
98
97
  # Define custom namespaces in which to look up your Input classes. Default is
99
98
  # to look up in the global scope and in Formtastic::Inputs.
@@ -101,9 +100,8 @@ Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
101
100
 
102
101
  # By creating custom action class finder, you can change how action classes are looked up.
103
102
  # 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
103
+ # See https://github.com/justinfrench/formtastic/wiki/Custom-Class-Finders
104
+ # Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder
107
105
 
108
106
  # Define custom namespaces in which to look up your Action classes. Default is
109
107
  # to look up in the global scope and in Formtastic::Actions.
@@ -0,0 +1,71 @@
1
+ gem 'formtastic', path: '..'
2
+ gem 'bcrypt', '~> 3.1.7'
3
+ gem 'rails-dom-testing', group: :test
4
+
5
+ # to speed up travis install, reuse the bundle path
6
+ def bundle_path
7
+ File.expand_path ENV.fetch('BUNDLE_PATH', 'vendor/bundle'), ENV['TRAVIS_BUILD_DIR']
8
+ end
9
+
10
+ if Rails.version >= '6.1'
11
+ gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails'"
12
+ elsif Rails.version >= '6.0'
13
+ gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '6-0-stable'"
14
+ elsif Rails.version >= '5.2'
15
+ gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '5-2-stable'"
16
+ end
17
+
18
+ ### Ensure Dummy App's Ruby version matches the current environments Ruby Version
19
+ ruby_version = "ruby '#{RUBY_VERSION}'"
20
+ gsub_file 'Gemfile', /ruby '\d+.\d+.\d+'/, ruby_version
21
+
22
+ if File.directory?(bundle_path) && bundle_install?
23
+ def run_bundle
24
+ previous_bundle_path = bundle_path
25
+
26
+ require "bundler"
27
+ Bundler.with_clean_env do
28
+ system("bundle install --jobs=3 --retry=3 --path=#{previous_bundle_path}")
29
+ end
30
+ end
31
+ end
32
+
33
+ in_root do
34
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile')
35
+ end
36
+
37
+ formtastic = -> do
38
+ generate(:scaffold, 'user name:string password:digest')
39
+ generate('formtastic:install')
40
+ generate('formtastic:form', 'user name password:password --force')
41
+
42
+ rails_command('db:migrate')
43
+
44
+ in_root do
45
+ inject_into_class 'app/models/user.rb', 'User', " has_secure_password\n"
46
+ inject_into_file 'app/assets/stylesheets/application.css', " *= require formtastic\n", before: ' *= require_self'
47
+ inject_into_class 'test/controllers/users_controller_test.rb', 'UsersControllerTest', <<-RUBY
48
+
49
+ test "should show form" do
50
+ get edit_user_path(@user)
51
+
52
+ assert_select 'form' do
53
+ assert_select 'li.input.string' do
54
+ assert_select 'input#user_name[type=text]'
55
+ end
56
+ assert_select 'li.input.password' do
57
+ assert_select 'input#user_password[type=password]'
58
+ end
59
+
60
+ assert_select 'fieldset.actions' do
61
+ assert_select 'li.action.input_action' do
62
+ assert_select 'input[type=submit]'
63
+ end
64
+ end
65
+ end
66
+ end # test "should show form"
67
+ RUBY
68
+ end
69
+ end
70
+
71
+ after_bundle(&formtastic)
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -e
4
+ set -o verbose
5
+
6
+ test_app=dummy
7
+
8
+ rm -rf ${test_app}
9
+
10
+ bundle exec rails new ${test_app} \
11
+ --template=$(dirname "$0")/integration-template.rb \
12
+ --skip-bootsnap \
13
+ --skip-javascript \
14
+ --skip-spring \
15
+ --skip-turbolinks
16
+
17
+ cd ${test_app} && export BUNDLE_GEMFILE=Gemfile
18
+
19
+ bundle exec rake test
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
  require 'formtastic/action_class_finder'
4
4
 
5
- describe Formtastic::ActionClassFinder do
5
+ RSpec.describe Formtastic::ActionClassFinder do
6
6
  include FormtasticSpecHelper
7
7
 
8
8
  it_behaves_like 'Specialized Class Finder' do
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe 'ButtonAction', 'when submitting' do
4
+ RSpec.describe 'ButtonAction', 'when submitting' do
5
5
 
6
6
  include FormtasticSpecHelper
7
7
 
@@ -15,12 +15,12 @@ describe 'ButtonAction', 'when submitting' do
15
15
  end
16
16
 
17
17
  it 'should render a submit type of button' do
18
- output_buffer.should have_tag('li.action.button_action button[@type="submit"]')
18
+ expect(output_buffer).to have_tag('li.action.button_action button[@type="submit"]')
19
19
  end
20
20
 
21
21
  end
22
22
 
23
- describe 'ButtonAction', 'when resetting' do
23
+ RSpec.describe 'ButtonAction', 'when resetting' do
24
24
 
25
25
  include FormtasticSpecHelper
26
26
 
@@ -34,16 +34,16 @@ describe 'ButtonAction', 'when resetting' do
34
34
  end
35
35
 
36
36
  it 'should render a reset type of button' do
37
- output_buffer.should have_tag('li.action.button_action button[@type="reset"]', :text => "Reset Post")
37
+ expect(output_buffer).to have_tag('li.action.button_action button[@type="reset"]', :text => "Reset Post")
38
38
  end
39
39
 
40
40
  it 'should not render a value attribute' do
41
- output_buffer.should_not have_tag('li.action.button_action button[@value]')
41
+ expect(output_buffer).not_to have_tag('li.action.button_action button[@value]')
42
42
  end
43
43
 
44
44
  end
45
45
 
46
- describe 'InputAction', 'when cancelling' do
46
+ RSpec.describe 'InputAction', 'when cancelling' do
47
47
 
48
48
  include FormtasticSpecHelper
49
49
 
@@ -53,11 +53,11 @@ describe 'InputAction', 'when cancelling' do
53
53
  end
54
54
 
55
55
  it 'should raise an error' do
56
- lambda {
56
+ expect {
57
57
  concat(semantic_form_for(@new_post) do |builder|
58
58
  concat(builder.action(:cancel, :as => :button))
59
59
  end)
60
- }.should raise_error(Formtastic::UnsupportedMethodForAction)
60
+ }.to raise_error(Formtastic::UnsupportedMethodForAction)
61
61
  end
62
62
 
63
63
  end