formtastic 3.1.2 → 4.0.0

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 (135) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +3 -2
  5. data/CHANGELOG.md +52 -0
  6. data/Gemfile.lock +105 -0
  7. data/MIT-LICENSE +1 -1
  8. data/{README.textile → README.md} +178 -167
  9. data/RELEASE_PROCESS +3 -1
  10. data/Rakefile +20 -1
  11. data/app/assets/stylesheets/formtastic.css +1 -1
  12. data/bin/appraisal +8 -0
  13. data/formtastic.gemspec +10 -16
  14. data/gemfiles/rails_5.2/Gemfile +5 -0
  15. data/gemfiles/rails_6.0/Gemfile +5 -0
  16. data/gemfiles/rails_6.1/Gemfile +5 -0
  17. data/gemfiles/rails_edge/Gemfile +13 -0
  18. data/lib/formtastic.rb +9 -11
  19. data/lib/formtastic/actions.rb +6 -3
  20. data/lib/formtastic/deprecation.rb +1 -38
  21. data/lib/formtastic/engine.rb +3 -1
  22. data/lib/formtastic/form_builder.rb +11 -24
  23. data/lib/formtastic/helpers.rb +1 -1
  24. data/lib/formtastic/helpers/action_helper.rb +1 -48
  25. data/lib/formtastic/helpers/enum.rb +13 -0
  26. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  27. data/lib/formtastic/helpers/fieldset_wrapper.rb +13 -9
  28. data/lib/formtastic/helpers/form_helper.rb +1 -1
  29. data/lib/formtastic/helpers/input_helper.rb +23 -77
  30. data/lib/formtastic/helpers/inputs_helper.rb +27 -22
  31. data/lib/formtastic/i18n.rb +1 -1
  32. data/lib/formtastic/inputs.rb +32 -29
  33. data/lib/formtastic/inputs/base/choices.rb +1 -1
  34. data/lib/formtastic/inputs/base/collections.rb +43 -10
  35. data/lib/formtastic/inputs/base/database.rb +7 -2
  36. data/lib/formtastic/inputs/base/errors.rb +4 -4
  37. data/lib/formtastic/inputs/base/hints.rb +1 -1
  38. data/lib/formtastic/inputs/base/html.rb +7 -6
  39. data/lib/formtastic/inputs/base/naming.rb +4 -4
  40. data/lib/formtastic/inputs/base/options.rb +2 -3
  41. data/lib/formtastic/inputs/base/timeish.rb +5 -1
  42. data/lib/formtastic/inputs/base/validations.rb +38 -12
  43. data/lib/formtastic/inputs/check_boxes_input.rb +13 -5
  44. data/lib/formtastic/inputs/color_input.rb +0 -1
  45. data/lib/formtastic/inputs/country_input.rb +3 -1
  46. data/lib/formtastic/inputs/radio_input.rb +20 -0
  47. data/lib/formtastic/inputs/select_input.rb +29 -1
  48. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  49. data/lib/formtastic/localizer.rb +20 -22
  50. data/lib/formtastic/namespaced_class_finder.rb +1 -1
  51. data/lib/formtastic/version.rb +1 -1
  52. data/lib/generators/formtastic/form/form_generator.rb +1 -1
  53. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  54. data/lib/generators/templates/formtastic.rb +14 -13
  55. data/lib/generators/templates/input.rb +19 -0
  56. data/sample/basic_inputs.html +1 -1
  57. data/script/integration-template.rb +74 -0
  58. data/script/integration.sh +19 -0
  59. data/spec/action_class_finder_spec.rb +1 -1
  60. data/spec/actions/button_action_spec.rb +8 -8
  61. data/spec/actions/generic_action_spec.rb +60 -60
  62. data/spec/actions/input_action_spec.rb +7 -7
  63. data/spec/actions/link_action_spec.rb +10 -10
  64. data/spec/builder/custom_builder_spec.rb +37 -21
  65. data/spec/builder/error_proc_spec.rb +4 -4
  66. data/spec/builder/semantic_fields_for_spec.rb +27 -27
  67. data/spec/fast_spec_helper.rb +12 -0
  68. data/spec/generators/formtastic/form/form_generator_spec.rb +25 -25
  69. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  70. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  71. data/spec/helpers/action_helper_spec.rb +328 -10
  72. data/spec/helpers/actions_helper_spec.rb +17 -17
  73. data/spec/helpers/form_helper_spec.rb +37 -37
  74. data/spec/helpers/input_helper_spec.rb +975 -2
  75. data/spec/helpers/inputs_helper_spec.rb +120 -105
  76. data/spec/helpers/reflection_helper_spec.rb +3 -3
  77. data/spec/helpers/semantic_errors_helper_spec.rb +22 -22
  78. data/spec/i18n_spec.rb +26 -26
  79. data/spec/input_class_finder_spec.rb +1 -1
  80. data/spec/inputs/base/collections_spec.rb +76 -0
  81. data/spec/inputs/base/validations_spec.rb +480 -0
  82. data/spec/inputs/boolean_input_spec.rb +55 -55
  83. data/spec/inputs/check_boxes_input_spec.rb +155 -108
  84. data/spec/inputs/color_input_spec.rb +51 -63
  85. data/spec/inputs/country_input_spec.rb +20 -20
  86. data/spec/inputs/custom_input_spec.rb +2 -6
  87. data/spec/inputs/datalist_input_spec.rb +1 -1
  88. data/spec/inputs/date_picker_input_spec.rb +42 -42
  89. data/spec/inputs/date_select_input_spec.rb +51 -37
  90. data/spec/inputs/datetime_picker_input_spec.rb +46 -46
  91. data/spec/inputs/datetime_select_input_spec.rb +53 -37
  92. data/spec/inputs/email_input_spec.rb +5 -5
  93. data/spec/inputs/file_input_spec.rb +6 -6
  94. data/spec/inputs/hidden_input_spec.rb +18 -18
  95. data/spec/inputs/include_blank_spec.rb +8 -8
  96. data/spec/inputs/label_spec.rb +20 -20
  97. data/spec/inputs/number_input_spec.rb +112 -112
  98. data/spec/inputs/password_input_spec.rb +5 -5
  99. data/spec/inputs/phone_input_spec.rb +5 -5
  100. data/spec/inputs/placeholder_spec.rb +5 -5
  101. data/spec/inputs/radio_input_spec.rb +84 -58
  102. data/spec/inputs/range_input_spec.rb +66 -66
  103. data/spec/inputs/readonly_spec.rb +50 -0
  104. data/spec/inputs/search_input_spec.rb +5 -5
  105. data/spec/inputs/select_input_spec.rb +149 -93
  106. data/spec/inputs/string_input_spec.rb +23 -23
  107. data/spec/inputs/text_input_spec.rb +16 -16
  108. data/spec/inputs/time_picker_input_spec.rb +43 -43
  109. data/spec/inputs/time_select_input_spec.rb +67 -54
  110. data/spec/inputs/time_zone_input_spec.rb +54 -28
  111. data/spec/inputs/url_input_spec.rb +5 -5
  112. data/spec/inputs/with_options_spec.rb +7 -7
  113. data/spec/localizer_spec.rb +17 -17
  114. data/spec/namespaced_class_finder_spec.rb +2 -2
  115. data/spec/schema.rb +21 -0
  116. data/spec/spec_helper.rb +165 -253
  117. data/spec/support/custom_macros.rb +72 -75
  118. data/spec/support/shared_examples.rb +0 -1232
  119. data/spec/support/test_environment.rb +23 -9
  120. metadata +69 -176
  121. data/.travis.yml +0 -29
  122. data/Appraisals +0 -29
  123. data/CHANGELOG +0 -31
  124. data/DEPRECATIONS +0 -49
  125. data/gemfiles/rails_3.2.gemfile +0 -7
  126. data/gemfiles/rails_4.0.4.gemfile +0 -7
  127. data/gemfiles/rails_4.1.gemfile +0 -7
  128. data/gemfiles/rails_4.2.gemfile +0 -7
  129. data/gemfiles/rails_4.gemfile +0 -7
  130. data/gemfiles/rails_edge.gemfile +0 -10
  131. data/lib/formtastic/util.rb +0 -57
  132. data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
  133. data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
  134. data/spec/support/deferred_garbage_collection.rb +0 -21
  135. data/spec/util_spec.rb +0 -66
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe 'Formtastic::Localizer' do
4
+ RSpec.describe 'Formtastic::Localizer' do
5
5
  describe "Cache" do
6
6
  before do
7
7
  @cache = Formtastic::Localizer::Cache.new
@@ -11,27 +11,27 @@ describe 'Formtastic::Localizer' do
11
11
  end
12
12
 
13
13
  it "should get value" do
14
- @cache.get(@key).should == 'value'
15
- @cache.get(@undefined_key).should be_nil
14
+ expect(@cache.get(@key)).to eq('value')
15
+ expect(@cache.get(@undefined_key)).to be_nil
16
16
  end
17
17
 
18
18
  it "should check if key exists?" do
19
- @cache.has_key?(@key).should be_truthy
20
- @cache.has_key?(@undefined_key).should be_falsey
19
+ expect(@cache.has_key?(@key)).to be_truthy
20
+ expect(@cache.has_key?(@undefined_key)).to be_falsey
21
21
  end
22
22
 
23
23
  it "should set a key" do
24
24
  @cache.set(['model', 'name2'], 'value2')
25
- @cache.get(['model', 'name2']).should == 'value2'
25
+ expect(@cache.get(['model', 'name2'])).to eq('value2')
26
26
  end
27
27
 
28
28
  it "should return hash" do
29
- @cache.cache.should be_an_instance_of(Hash)
29
+ expect(@cache.cache).to be_an_instance_of(Hash)
30
30
  end
31
31
 
32
32
  it "should clear the cache" do
33
33
  @cache.clear!
34
- @cache.get(@key).should be_nil
34
+ expect(@cache.get(@key)).to be_nil
35
35
  end
36
36
  end
37
37
 
@@ -53,11 +53,11 @@ describe 'Formtastic::Localizer' do
53
53
  end
54
54
 
55
55
  it "should be defined" do
56
- lambda { Formtastic::Localizer }.should_not raise_error
56
+ expect { Formtastic::Localizer }.not_to raise_error
57
57
  end
58
58
 
59
59
  it "should have a cache" do
60
- Formtastic::Localizer.cache.should be_an_instance_of(Formtastic::Localizer::Cache)
60
+ expect(Formtastic::Localizer.cache).to be_an_instance_of(Formtastic::Localizer::Cache)
61
61
  end
62
62
 
63
63
  describe "localize" do
@@ -75,19 +75,19 @@ describe 'Formtastic::Localizer' do
75
75
  end
76
76
 
77
77
  it "should translate key with i18n" do
78
- @localizer.localize(:name, :name, :label).should == 'POST.NAME'
78
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NAME')
79
79
  end
80
80
 
81
81
  describe "with caching" do
82
82
  it "should not update translation when stored translations change" do
83
83
  with_config :i18n_cache_lookups, true do
84
- @localizer.localize(:name, :name, :label).should == 'POST.NAME'
84
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NAME')
85
85
  store_post_translations('POST.NEW_NAME')
86
86
 
87
- @localizer.localize(:name, :name, :label).should == 'POST.NAME'
87
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NAME')
88
88
 
89
89
  Formtastic::Localizer.cache.clear!
90
- @localizer.localize(:name, :name, :label).should == 'POST.NEW_NAME'
90
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NEW_NAME')
91
91
  end
92
92
  end
93
93
  end
@@ -95,9 +95,9 @@ describe 'Formtastic::Localizer' do
95
95
  describe "without caching" do
96
96
  it "should update translation when stored translations change" do
97
97
  with_config :i18n_cache_lookups, false do
98
- @localizer.localize(:name, :name, :label).should == 'POST.NAME'
98
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NAME')
99
99
  store_post_translations('POST.NEW_NAME')
100
- @localizer.localize(:name, :name, :label).should == 'POST.NEW_NAME'
100
+ expect(@localizer.localize(:name, :name, :label)).to eq('POST.NEW_NAME')
101
101
  end
102
102
  end
103
103
  end
@@ -120,7 +120,7 @@ describe 'Formtastic::Localizer' do
120
120
  end
121
121
 
122
122
  it "should translate custom key with i18n" do
123
- @localizer.localize(:name, :name, :label).should == 'MESSAGE.NAME'
123
+ expect(@localizer.localize(:name, :name, :label)).to eq('MESSAGE.NAME')
124
124
  end
125
125
  end
126
126
  end
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
  require 'formtastic/namespaced_class_finder'
4
4
 
5
- describe Formtastic::NamespacedClassFinder do
5
+ RSpec.describe Formtastic::NamespacedClassFinder do
6
6
  include FormtasticSpecHelper
7
7
 
8
8
  before do
@@ -54,7 +54,7 @@ describe Formtastic::NamespacedClassFinder do
54
54
 
55
55
  context '#finder' do
56
56
  before do
57
- Rails.application.config.stub(:cache_classes).and_return(cache_classes)
57
+ allow(Rails.application.config).to receive(:cache_classes).and_return(cache_classes)
58
58
  end
59
59
 
60
60
  context 'when cache_classes is on' do
data/spec/schema.rb ADDED
@@ -0,0 +1,21 @@
1
+ ActiveRecord::Schema.define(version: 20170208011723) do
2
+
3
+ create_table "posts", force: :cascade do |t|
4
+ t.integer "author_id", limit: 4, null: false
5
+ end
6
+
7
+ create_table "authors", force: :cascade do |t|
8
+ t.integer "age", limit: 4, null: false
9
+ t.string "name", limit: 255, null: false
10
+ t.string "surname", limit: 255, null: false
11
+ t.string "login", limit: 255
12
+ t.datetime "created_at"
13
+ t.datetime "updated_at"
14
+ end
15
+
16
+ #non-rails foreign id convention
17
+ create_table "legacy_posts", force: :cascade do |t|
18
+ t.integer "post_author", limit: 4, null: false
19
+ end
20
+
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,16 +6,12 @@ require 'action_pack'
6
6
  require 'action_view'
7
7
  require 'action_controller'
8
8
  require 'action_dispatch'
9
+ require 'active_record'
9
10
 
10
- require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/util'))
11
- require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
11
+ ActiveRecord::Base.establish_connection('url' => 'sqlite3::memory:', 'pool' => 1)
12
+ load 'spec/schema.rb'
12
13
 
13
- #rspec-rails 2-14 assumes a full rails install
14
- module Rails
15
- module VERSION
16
- include ActionPack::VERSION
17
- end
18
- end
14
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
19
15
 
20
16
  require 'ammeter/init'
21
17
 
@@ -52,8 +48,8 @@ module FormtasticSpecHelper
52
48
  include Formtastic::Helpers::FormHelper
53
49
 
54
50
  def default_input_type(column_type, column_name = :generic_column_name)
55
- @new_post.stub(column_name)
56
- @new_post.stub(:column_for_attribute).and_return(double('column', :type => column_type)) unless column_type.nil?
51
+ allow(@new_post).to receive(column_name)
52
+ allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => column_type)) unless column_type.nil?
57
53
 
58
54
  semantic_form_for(@new_post) do |builder|
59
55
  @default_type = builder.send(:default_input_type, column_name)
@@ -64,7 +60,7 @@ module FormtasticSpecHelper
64
60
 
65
61
  def active_model_validator(kind, attributes, options = {})
66
62
  validator = double("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
67
- validator.stub(:kind).and_return(kind)
63
+ allow(validator).to receive(:kind).and_return(kind)
68
64
  validator
69
65
  end
70
66
 
@@ -107,26 +103,17 @@ module FormtasticSpecHelper
107
103
  end
108
104
 
109
105
  module ::Namespaced
110
- class Post
111
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
112
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
113
-
114
- def id
115
- end
116
-
117
- def persisted?
118
- end
106
+ class Post < ActiveRecord::Base
119
107
  end
120
108
  end
121
109
 
122
- class ::Author
123
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
124
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
125
-
126
- def to_label
110
+ class ::Author < ActiveRecord::Base
111
+ def new_record?
112
+ !id
127
113
  end
128
114
 
129
- def persisted?
115
+ def to_label
116
+ [name, surname].compact.join(' ')
130
117
  end
131
118
  end
132
119
 
@@ -139,6 +126,10 @@ module FormtasticSpecHelper
139
126
  end
140
127
  end
141
128
 
129
+ class ::LegacyPost < ActiveRecord::Base
130
+ belongs_to :author, foreign_key: :post_author
131
+ end
132
+
142
133
  class ::Continent
143
134
  extend ActiveModel::Naming if defined?(ActiveModel::Naming)
144
135
  include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
@@ -161,9 +152,8 @@ module FormtasticSpecHelper
161
152
  end
162
153
  end
163
154
 
164
- # In Rails 3 Model.all returns an array. In Rails 4, it returns an
165
- # association proxy, which quacks a lot like an array. We use this in stubs
166
- # or mocks where we need to return the later.
155
+ # Model.all returns an association proxy, which quacks a lot like an array.
156
+ # We use this in stubs or mocks where we need to return the later.
167
157
  #
168
158
  # TODO try delegate?
169
159
  # delegate :map, :size, :length, :first, :to_ary, :each, :include?, :to => :array
@@ -211,14 +201,15 @@ module FormtasticSpecHelper
211
201
 
212
202
  def _routes
213
203
  url_helpers = double('url_helpers')
214
- url_helpers.stub(:hash_for_posts_path).and_return({})
215
- url_helpers.stub(:hash_for_post_path).and_return({})
216
- url_helpers.stub(:hash_for_post_models_path).and_return({})
217
- url_helpers.stub(:hash_for_authors_path).and_return({})
204
+ allow(url_helpers).to receive(:hash_for_posts_path).and_return({})
205
+ allow(url_helpers).to receive(:hash_for_post_path).and_return({})
206
+ allow(url_helpers).to receive(:hash_for_post_models_path).and_return({})
207
+ allow(url_helpers).to receive(:hash_for_authors_path).and_return({})
218
208
 
219
209
  double('_routes',
220
210
  :url_helpers => url_helpers,
221
- :url_for => "/mock/path"
211
+ :url_for => "/mock/path",
212
+ :polymorphic_mappings => {}
222
213
  )
223
214
  end
224
215
 
@@ -246,121 +237,79 @@ module FormtasticSpecHelper
246
237
  def authors_path(*args); "/authors"; end
247
238
  def new_author_path(*args); "/authors/new"; end
248
239
 
249
- # Returns the array for Rails 3 and a thing that looks looks like an
250
- # association proxy for Rails 4+
251
240
  def author_array_or_scope(the_array = [@fred, @bob])
252
- if ::Formtastic::Util.rails3?
253
- the_array
254
- else
255
- MockScope.new(the_array)
256
- end
241
+ MockScope.new(the_array)
257
242
  end
258
-
259
- @fred = ::Author.new
260
- @fred.stub(:class).and_return(::Author)
261
- @fred.stub(:to_label).and_return('Fred Smith')
262
- @fred.stub(:login).and_return('fred_smith')
263
- @fred.stub(:age).and_return(27)
264
- @fred.stub(:id).and_return(37)
265
- @fred.stub(:new_record?).and_return(false)
266
- @fred.stub(:errors).and_return(double('errors', :[] => nil))
267
- @fred.stub(:to_key).and_return(nil)
268
- @fred.stub(:persisted?).and_return(nil)
269
- @fred.stub(:name).and_return('Fred')
270
-
271
- @bob = ::Author.new
272
- @bob.stub(:to_label).and_return('Bob Rock')
273
- @bob.stub(:login).and_return('bob')
274
- @bob.stub(:age).and_return(43)
275
- @bob.stub(:created_at)
276
- @bob.stub(:id).and_return(42)
277
- @bob.stub(:posts).and_return([])
278
- @bob.stub(:post_ids).and_return([])
279
- @bob.stub(:new_record?).and_return(false)
280
- @bob.stub(:errors).and_return(double('errors', :[] => nil))
281
- @bob.stub(:to_key).and_return(nil)
282
- @bob.stub(:persisted?).and_return(nil)
283
- @bob.stub(:name).and_return('Bob')
284
-
285
- @james = ::Author.new
286
- @james.stub(:to_label).and_return('James Shock')
287
- @james.stub(:login).and_return('james')
288
- @james.stub(:age).and_return(38)
289
- @james.stub(:id).and_return(75)
290
- @james.stub(:posts).and_return([])
291
- @james.stub(:post_ids).and_return([])
292
- @james.stub(:new_record?).and_return(false)
293
- @james.stub(:errors).and_return(double('errors', :[] => nil))
294
- @james.stub(:to_key).and_return(nil)
295
- @james.stub(:persisted?).and_return(nil)
296
- @james.stub(:name).and_return('James')
297
-
298
-
299
- ::Author.stub(:scoped).and_return(::Author)
300
- ::Author.stub(:find).and_return(author_array_or_scope)
301
- ::Author.stub(:all).and_return(author_array_or_scope)
302
- ::Author.stub(:where).and_return(author_array_or_scope)
303
- ::Author.stub(:human_attribute_name) { |column_name| column_name.humanize }
304
- ::Author.stub(:human_name).and_return('::Author')
305
- ::Author.stub(:reflect_on_association) { |column_name| double('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
306
- ::Author.stub(:content_columns).and_return([double('column', :name => 'login'), double('column', :name => 'created_at')])
307
- ::Author.stub(:to_key).and_return(nil)
308
- ::Author.stub(:persisted?).and_return(nil)
243
+
244
+ @fred = ::Author.new(login: 'fred_smith', age: 27, name: 'Fred', id: 37)
245
+ @bob = ::Author.new(login: 'bob', age: 43, name: 'Bob', id: 42)
246
+ @james = ::Author.new(age: 38, id: 75)
247
+
248
+ allow(::Author).to receive(:scoped).and_return(::Author)
249
+ allow(::Author).to receive(:find).and_return(author_array_or_scope)
250
+ allow(::Author).to receive(:all).and_return(author_array_or_scope)
251
+ allow(::Author).to receive(:where).and_return(author_array_or_scope)
252
+ allow(::Author).to receive(:human_attribute_name) { |column_name| column_name.humanize }
253
+ allow(::Author).to receive(:human_name).and_return('::Author')
254
+ allow(::Author).to receive(:reflect_on_association) { |column_name| double('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
255
+ allow(::Author).to receive(:content_columns).and_return([double('column', :name => 'login'), double('column', :name => 'created_at')])
256
+ allow(::Author).to receive(:to_key).and_return(nil)
257
+ allow(::Author).to receive(:persisted?).and_return(nil)
309
258
 
310
259
  @hash_backed_author = HashBackedAuthor.new
311
260
 
312
261
  # Sometimes we need a mock @post object and some Authors for belongs_to
313
262
  @new_post = double('post')
314
- @new_post.stub(:class).and_return(::Post)
315
- @new_post.stub(:id).and_return(nil)
316
- @new_post.stub(:new_record?).and_return(true)
317
- @new_post.stub(:errors).and_return(double('errors', :[] => nil))
318
- @new_post.stub(:author).and_return(nil)
319
- @new_post.stub(:author_attributes=).and_return(nil)
320
- @new_post.stub(:authors).and_return(author_array_or_scope([@fred]))
321
- @new_post.stub(:authors_attributes=)
322
- @new_post.stub(:reviewer).and_return(nil)
323
- @new_post.stub(:main_post).and_return(nil)
324
- @new_post.stub(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
325
- @new_post.stub(:to_key).and_return(nil)
326
- @new_post.stub(:to_model).and_return(@new_post)
327
- @new_post.stub(:persisted?).and_return(nil)
328
- @new_post.stub(:model_name){ @new_post.class.model_name}
263
+ allow(@new_post).to receive(:class).and_return(::Post)
264
+ allow(@new_post).to receive(:id).and_return(nil)
265
+ allow(@new_post).to receive(:new_record?).and_return(true)
266
+ allow(@new_post).to receive(:errors).and_return(double('errors', :[] => nil))
267
+ allow(@new_post).to receive(:author).and_return(nil)
268
+ allow(@new_post).to receive(:author_attributes=).and_return(nil)
269
+ allow(@new_post).to receive(:authors).and_return(author_array_or_scope([@fred]))
270
+ allow(@new_post).to receive(:authors_attributes=)
271
+ allow(@new_post).to receive(:reviewer).and_return(nil)
272
+ allow(@new_post).to receive(:main_post).and_return(nil)
273
+ allow(@new_post).to receive(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
274
+ allow(@new_post).to receive(:to_key).and_return(nil)
275
+ allow(@new_post).to receive(:to_model).and_return(@new_post)
276
+ allow(@new_post).to receive(:persisted?).and_return(nil)
277
+ allow(@new_post).to receive(:model_name){ @new_post.class.model_name}
329
278
 
330
279
  @freds_post = double('post')
331
- @freds_post.stub(:to_ary)
332
- @freds_post.stub(:class).and_return(::Post)
333
- @freds_post.stub(:to_label).and_return('Fred Smith')
334
- @freds_post.stub(:id).and_return(19)
335
- @freds_post.stub(:title).and_return("Hello World")
336
- @freds_post.stub(:author).and_return(@fred)
337
- @freds_post.stub(:author_id).and_return(@fred.id)
338
- @freds_post.stub(:authors).and_return([@fred])
339
- @freds_post.stub(:author_ids).and_return([@fred.id])
340
- @freds_post.stub(:new_record?).and_return(false)
341
- @freds_post.stub(:errors).and_return(double('errors', :[] => nil))
342
- @freds_post.stub(:to_key).and_return(nil)
343
- @freds_post.stub(:persisted?).and_return(nil)
344
- @freds_post.stub(:model_name){ @freds_post.class.model_name}
345
- @freds_post.stub(:to_model).and_return(@freds_post)
346
- @fred.stub(:posts).and_return(author_array_or_scope([@freds_post]))
347
- @fred.stub(:post_ids).and_return([@freds_post.id])
348
-
349
- ::Post.stub(:scoped).and_return(::Post)
350
- ::Post.stub(:human_attribute_name) { |column_name| column_name.humanize }
351
- ::Post.stub(:human_name).and_return('Post')
352
- ::Post.stub(:reflect_on_all_validations).and_return([])
353
- ::Post.stub(:reflect_on_validations_for).and_return([])
354
- ::Post.stub(:reflections).and_return({})
355
- ::Post.stub(:reflect_on_association) { |column_name|
280
+ allow(@freds_post).to receive(:to_ary)
281
+ allow(@freds_post).to receive(:class).and_return(::Post)
282
+ allow(@freds_post).to receive(:to_label).and_return('Fred Smith')
283
+ allow(@freds_post).to receive(:id).and_return(19)
284
+ allow(@freds_post).to receive(:title).and_return("Hello World")
285
+ allow(@freds_post).to receive(:author).and_return(@fred)
286
+ allow(@freds_post).to receive(:author_id).and_return(@fred.id)
287
+ allow(@freds_post).to receive(:authors).and_return([@fred])
288
+ allow(@freds_post).to receive(:author_ids).and_return([@fred.id])
289
+ allow(@freds_post).to receive(:new_record?).and_return(false)
290
+ allow(@freds_post).to receive(:errors).and_return(double('errors', :[] => nil))
291
+ allow(@freds_post).to receive(:to_key).and_return(nil)
292
+ allow(@freds_post).to receive(:persisted?).and_return(nil)
293
+ allow(@freds_post).to receive(:model_name){ @freds_post.class.model_name}
294
+ allow(@freds_post).to receive(:to_model).and_return(@freds_post)
295
+ allow(@fred).to receive(:posts).and_return(author_array_or_scope([@freds_post]))
296
+ allow(@fred).to receive(:post_ids).and_return([@freds_post.id])
297
+
298
+ allow(::Post).to receive(:scoped).and_return(::Post)
299
+ allow(::Post).to receive(:human_attribute_name) { |column_name| column_name.humanize }
300
+ allow(::Post).to receive(:human_name).and_return('Post')
301
+ allow(::Post).to receive(:reflect_on_all_validations).and_return([])
302
+ allow(::Post).to receive(:reflect_on_validations_for).and_return([])
303
+ allow(::Post).to receive(:reflections).and_return({})
304
+ allow(::Post).to receive(:reflect_on_association) { |column_name|
356
305
  case column_name
357
306
  when :author, :author_status
358
307
  mock = double('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
359
- mock.stub(:[]).with(:class_name).and_return("Author")
308
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
360
309
  mock
361
310
  when :reviewer
362
311
  mock = double('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
363
- mock.stub(:[]).with(:class_name).and_return("Author")
312
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
364
313
  mock
365
314
  when :authors
366
315
  double('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
@@ -374,98 +323,98 @@ module FormtasticSpecHelper
374
323
  :klass => ::Author, :macro => :referenced_in, :foreign_key => "reviewer_id") # custom id
375
324
  end
376
325
  }
377
- ::Post.stub(:find).and_return(author_array_or_scope([@freds_post]))
378
- ::Post.stub(:all).and_return(author_array_or_scope([@freds_post]))
379
- ::Post.stub(:where).and_return(author_array_or_scope([@freds_post]))
380
- ::Post.stub(:content_columns).and_return([double('column', :name => 'title'), double('column', :name => 'body'), double('column', :name => 'created_at')])
381
- ::Post.stub(:to_key).and_return(nil)
382
- ::Post.stub(:persisted?).and_return(nil)
383
- ::Post.stub(:to_ary)
384
-
385
- ::MongoPost.stub(:human_attribute_name) { |column_name| column_name.humanize }
386
- ::MongoPost.stub(:human_name).and_return('MongoPost')
387
- ::MongoPost.stub(:associations).and_return({
326
+ allow(::Post).to receive(:find).and_return(author_array_or_scope([@freds_post]))
327
+ allow(::Post).to receive(:all).and_return(author_array_or_scope([@freds_post]))
328
+ allow(::Post).to receive(:where).and_return(author_array_or_scope([@freds_post]))
329
+ allow(::Post).to receive(:content_columns).and_return([double('column', :name => 'title'), double('column', :name => 'body'), double('column', :name => 'created_at')])
330
+ allow(::Post).to receive(:to_key).and_return(nil)
331
+ allow(::Post).to receive(:persisted?).and_return(nil)
332
+ allow(::Post).to receive(:to_ary)
333
+
334
+ allow(::MongoPost).to receive(:human_attribute_name) { |column_name| column_name.humanize }
335
+ allow(::MongoPost).to receive(:human_name).and_return('MongoPost')
336
+ allow(::MongoPost).to receive(:associations).and_return({
388
337
  :sub_posts => double('reflection', :options => {:polymorphic => true}, :klass => ::MongoPost, :macro => :has_many),
389
338
  :options => []
390
339
  })
391
- ::MongoPost.stub(:find).and_return(author_array_or_scope([@freds_post]))
392
- ::MongoPost.stub(:all).and_return(author_array_or_scope([@freds_post]))
393
- ::MongoPost.stub(:where).and_return(author_array_or_scope([@freds_post]))
394
- ::MongoPost.stub(:to_key).and_return(nil)
395
- ::MongoPost.stub(:persisted?).and_return(nil)
396
- ::MongoPost.stub(:to_ary)
397
- ::MongoPost.stub(:model_name).and_return( double(:model_name_mock, :singular => "post", :plural => "posts", :param_key => "post", :route_key => "posts") )
340
+ allow(::MongoPost).to receive(:find).and_return(author_array_or_scope([@freds_post]))
341
+ allow(::MongoPost).to receive(:all).and_return(author_array_or_scope([@freds_post]))
342
+ allow(::MongoPost).to receive(:where).and_return(author_array_or_scope([@freds_post]))
343
+ allow(::MongoPost).to receive(:to_key).and_return(nil)
344
+ allow(::MongoPost).to receive(:persisted?).and_return(nil)
345
+ allow(::MongoPost).to receive(:to_ary)
346
+ allow(::MongoPost).to receive(:model_name).and_return( double(:model_name_mock, :singular => "post", :plural => "posts", :param_key => "post", :route_key => "posts", :name => "post") )
398
347
 
399
348
  @new_mm_post = double('mm_post')
400
- @new_mm_post.stub(:class).and_return(::MongoPost)
401
- @new_mm_post.stub(:id).and_return(nil)
402
- @new_mm_post.stub(:new_record?).and_return(true)
403
- @new_mm_post.stub(:errors).and_return(double('errors', :[] => nil))
404
- @new_mm_post.stub(:title).and_return("Hello World")
405
- @new_mm_post.stub(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
406
- @new_mm_post.stub(:to_key).and_return(nil)
407
- @new_mm_post.stub(:to_model).and_return(@new_mm_post)
408
- @new_mm_post.stub(:persisted?).and_return(nil)
409
- @new_mm_post.stub(:model_name).and_return(::MongoPost.model_name)
349
+ allow(@new_mm_post).to receive(:class).and_return(::MongoPost)
350
+ allow(@new_mm_post).to receive(:id).and_return(nil)
351
+ allow(@new_mm_post).to receive(:new_record?).and_return(true)
352
+ allow(@new_mm_post).to receive(:errors).and_return(double('errors', :[] => nil))
353
+ allow(@new_mm_post).to receive(:title).and_return("Hello World")
354
+ allow(@new_mm_post).to receive(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
355
+ allow(@new_mm_post).to receive(:to_key).and_return(nil)
356
+ allow(@new_mm_post).to receive(:to_model).and_return(@new_mm_post)
357
+ allow(@new_mm_post).to receive(:persisted?).and_return(nil)
358
+ allow(@new_mm_post).to receive(:model_name).and_return(::MongoPost.model_name)
410
359
 
411
360
  @mock_file = double('file')
412
361
  Formtastic::FormBuilder.file_methods.each do |method|
413
- @mock_file.stub(method).and_return(true)
362
+ allow(@mock_file).to receive(method).and_return(true)
414
363
  end
415
364
 
416
- @new_post.stub(:title)
417
- @new_post.stub(:email)
418
- @new_post.stub(:url)
419
- @new_post.stub(:phone)
420
- @new_post.stub(:search)
421
- @new_post.stub(:to_ary)
422
- @new_post.stub(:body)
423
- @new_post.stub(:published)
424
- @new_post.stub(:publish_at)
425
- @new_post.stub(:created_at)
426
- @new_post.stub(:secret).and_return(1)
427
- @new_post.stub(:url)
428
- @new_post.stub(:email)
429
- @new_post.stub(:color)
430
- @new_post.stub(:search)
431
- @new_post.stub(:phone)
432
- @new_post.stub(:time_zone)
433
- @new_post.stub(:category_name)
434
- @new_post.stub(:allow_comments).and_return(true)
435
- @new_post.stub(:answer_comments)
436
- @new_post.stub(:country)
437
- @new_post.stub(:country_subdivision)
438
- @new_post.stub(:country_code)
439
- @new_post.stub(:document).and_return(@mock_file)
440
- @new_post.stub(:column_for_attribute).with(:meta_description).and_return(double('column', :type => :string, :limit => 255))
441
- @new_post.stub(:column_for_attribute).with(:title).and_return(double('column', :type => :string, :limit => 50))
442
- @new_post.stub(:column_for_attribute).with(:body).and_return(double('column', :type => :text))
443
- @new_post.stub(:column_for_attribute).with(:published).and_return(double('column', :type => :boolean))
444
- @new_post.stub(:column_for_attribute).with(:publish_at).and_return(double('column', :type => :date))
445
- @new_post.stub(:column_for_attribute).with(:time_zone).and_return(double('column', :type => :string))
446
- @new_post.stub(:column_for_attribute).with(:allow_comments).and_return(double('column', :type => :boolean))
447
- @new_post.stub(:column_for_attribute).with(:author).and_return(double('column', :type => :integer))
448
- @new_post.stub(:column_for_attribute).with(:country).and_return(double('column', :type => :string, :limit => 255))
449
- @new_post.stub(:column_for_attribute).with(:country_subdivision).and_return(double('column', :type => :string, :limit => 255))
450
- @new_post.stub(:column_for_attribute).with(:country_code).and_return(double('column', :type => :string, :limit => 255))
451
- @new_post.stub(:column_for_attribute).with(:email).and_return(double('column', :type => :string, :limit => 255))
452
- @new_post.stub(:column_for_attribute).with(:color).and_return(double('column', :type => :string, :limit => 255))
453
- @new_post.stub(:column_for_attribute).with(:url).and_return(double('column', :type => :string, :limit => 255))
454
- @new_post.stub(:column_for_attribute).with(:phone).and_return(double('column', :type => :string, :limit => 255))
455
- @new_post.stub(:column_for_attribute).with(:search).and_return(double('column', :type => :string, :limit => 255))
456
- @new_post.stub(:column_for_attribute).with(:document).and_return(nil)
457
-
458
- @new_post.stub(:author).and_return(@bob)
459
- @new_post.stub(:author_id).and_return(@bob.id)
460
-
461
- @new_post.stub(:reviewer).and_return(@fred)
462
- @new_post.stub(:reviewer_id).and_return(@fred.id)
365
+ allow(@new_post).to receive(:title)
366
+ allow(@new_post).to receive(:email)
367
+ allow(@new_post).to receive(:url)
368
+ allow(@new_post).to receive(:phone)
369
+ allow(@new_post).to receive(:search)
370
+ allow(@new_post).to receive(:to_ary)
371
+ allow(@new_post).to receive(:body)
372
+ allow(@new_post).to receive(:published)
373
+ allow(@new_post).to receive(:publish_at)
374
+ allow(@new_post).to receive(:created_at)
375
+ allow(@new_post).to receive(:secret).and_return(1)
376
+ allow(@new_post).to receive(:url)
377
+ allow(@new_post).to receive(:email)
378
+ allow(@new_post).to receive(:color)
379
+ allow(@new_post).to receive(:search)
380
+ allow(@new_post).to receive(:phone)
381
+ allow(@new_post).to receive(:time_zone)
382
+ allow(@new_post).to receive(:category_name)
383
+ allow(@new_post).to receive(:allow_comments).and_return(true)
384
+ allow(@new_post).to receive(:answer_comments)
385
+ allow(@new_post).to receive(:country)
386
+ allow(@new_post).to receive(:country_subdivision)
387
+ allow(@new_post).to receive(:country_code)
388
+ allow(@new_post).to receive(:document).and_return(@mock_file)
389
+ allow(@new_post).to receive(:column_for_attribute).with(:meta_description).and_return(double('column', :type => :string, :limit => 255))
390
+ allow(@new_post).to receive(:column_for_attribute).with(:title).and_return(double('column', :type => :string, :limit => 50))
391
+ allow(@new_post).to receive(:column_for_attribute).with(:body).and_return(double('column', :type => :text))
392
+ allow(@new_post).to receive(:column_for_attribute).with(:published).and_return(double('column', :type => :boolean))
393
+ allow(@new_post).to receive(:column_for_attribute).with(:publish_at).and_return(double('column', :type => :date))
394
+ allow(@new_post).to receive(:column_for_attribute).with(:time_zone).and_return(double('column', :type => :string))
395
+ allow(@new_post).to receive(:column_for_attribute).with(:allow_comments).and_return(double('column', :type => :boolean))
396
+ allow(@new_post).to receive(:column_for_attribute).with(:author).and_return(double('column', :type => :integer))
397
+ allow(@new_post).to receive(:column_for_attribute).with(:country).and_return(double('column', :type => :string, :limit => 255))
398
+ allow(@new_post).to receive(:column_for_attribute).with(:country_subdivision).and_return(double('column', :type => :string, :limit => 255))
399
+ allow(@new_post).to receive(:column_for_attribute).with(:country_code).and_return(double('column', :type => :string, :limit => 255))
400
+ allow(@new_post).to receive(:column_for_attribute).with(:email).and_return(double('column', :type => :string, :limit => 255))
401
+ allow(@new_post).to receive(:column_for_attribute).with(:color).and_return(double('column', :type => :string, :limit => 255))
402
+ allow(@new_post).to receive(:column_for_attribute).with(:url).and_return(double('column', :type => :string, :limit => 255))
403
+ allow(@new_post).to receive(:column_for_attribute).with(:phone).and_return(double('column', :type => :string, :limit => 255))
404
+ allow(@new_post).to receive(:column_for_attribute).with(:search).and_return(double('column', :type => :string, :limit => 255))
405
+ allow(@new_post).to receive(:column_for_attribute).with(:document).and_return(nil)
406
+
407
+ allow(@new_post).to receive(:author).and_return(@bob)
408
+ allow(@new_post).to receive(:author_id).and_return(@bob.id)
409
+
410
+ allow(@new_post).to receive(:reviewer).and_return(@fred)
411
+ allow(@new_post).to receive(:reviewer_id).and_return(@fred.id)
463
412
 
464
413
  # @new_post.should_receive(:publish_at=).at_least(:once)
465
- @new_post.stub(:publish_at=)
414
+ allow(@new_post).to receive(:publish_at=)
466
415
  # @new_post.should_receive(:title=).at_least(:once)
467
- @new_post.stub(:title=)
468
- @new_post.stub(:main_post_id).and_return(nil)
416
+ allow(@new_post).to receive(:title=)
417
+ allow(@new_post).to receive(:main_post_id).and_return(nil)
469
418
 
470
419
  end
471
420
 
@@ -492,29 +441,8 @@ module FormtasticSpecHelper
492
441
  Formtastic::FormBuilder.send(:"#{config_method_name}=", old_value)
493
442
  end
494
443
 
495
- class ToSMatcher
496
- def initialize(str)
497
- @str=str.to_s
498
- end
499
-
500
- def matches?(value)
501
- value.to_s==@str
502
- end
503
-
504
- def failure_message_for_should
505
- "Expected argument that converted to #{@str}"
506
- end
507
- end
508
-
509
- def errors_matcher(method)
510
- # In edge rails (Rails 4) tags store method_name as a string and index the errors object using a string
511
- # therefore allow stubs to match on either string or symbol. The errors object calls to_sym on all index
512
- # accesses so @object.errors[:abc] is equivalent to @object.errors["abc"]
513
- if Rails::VERSION::MAJOR == 4
514
- ToSMatcher.new(method)
515
- else
516
- method
517
- end
444
+ RSpec::Matchers.define :errors_matcher do |expected|
445
+ match { |actual| actual.to_s == expected.to_s }
518
446
  end
519
447
  end
520
448
 
@@ -531,23 +459,7 @@ RSpec.configure do |config|
531
459
  config.filter_run_excluding skip: true
532
460
  config.run_all_when_everything_filtered = true
533
461
 
534
- config.before(:each) do
462
+ config.before(:example) do
535
463
  Formtastic::Localizer.cache.clear!
536
464
  end
537
-
538
- config.before(:each) do
539
- allow(Formtastic.deprecation).to receive(:deprecation_warning).and_call_original
540
- # TODO: Remove this in Formtastic 4
541
- [ :action_class, :standard_action_class_name, :custom_action_class_name,
542
- :input_class, :standard_input_class_name, :custom_input_class_name ].each do |method|
543
- allow(Formtastic.deprecation).to receive(:deprecation_warning).with(method, instance_of(String), instance_of(Array))
544
- end
545
- end
546
-
547
- config.before(:all) do
548
- DeferredGarbageCollection.start unless ENV["DEFER_GC"] == "false"
549
- end
550
- config.after(:all) do
551
- DeferredGarbageCollection.reconsider unless ENV["DEFER_GC"] == "false"
552
- end
553
465
  end