formtastic 2.1.0 → 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 (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +4 -2
  5. data/CHANGELOG.md +52 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +105 -0
  8. data/MIT-LICENSE +1 -1
  9. data/{README.textile → README.md} +204 -219
  10. data/RELEASE_PROCESS +3 -1
  11. data/Rakefile +27 -29
  12. data/app/assets/stylesheets/formtastic.css +3 -2
  13. data/bin/appraisal +8 -0
  14. data/formtastic.gemspec +11 -14
  15. data/gemfiles/rails_5.2/Gemfile +5 -0
  16. data/gemfiles/rails_6.0/Gemfile +5 -0
  17. data/gemfiles/rails_6.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +18 -0
  20. data/lib/formtastic/actions/button_action.rb +55 -60
  21. data/lib/formtastic/actions/input_action.rb +59 -57
  22. data/lib/formtastic/actions/link_action.rb +68 -67
  23. data/lib/formtastic/actions.rb +6 -3
  24. data/lib/formtastic/deprecation.rb +5 -0
  25. data/lib/formtastic/engine.rb +3 -1
  26. data/lib/formtastic/form_builder.rb +35 -16
  27. data/lib/formtastic/helpers/action_helper.rb +34 -28
  28. data/lib/formtastic/helpers/enum.rb +13 -0
  29. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  30. data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
  31. data/lib/formtastic/helpers/form_helper.rb +19 -16
  32. data/lib/formtastic/helpers/input_helper.rb +69 -97
  33. data/lib/formtastic/helpers/inputs_helper.rb +35 -25
  34. data/lib/formtastic/helpers/reflection.rb +4 -4
  35. data/lib/formtastic/helpers.rb +1 -2
  36. data/lib/formtastic/html_attributes.rb +12 -1
  37. data/lib/formtastic/i18n.rb +1 -1
  38. data/lib/formtastic/input_class_finder.rb +18 -0
  39. data/lib/formtastic/inputs/base/choices.rb +2 -2
  40. data/lib/formtastic/inputs/base/collections.rb +46 -14
  41. data/lib/formtastic/inputs/base/database.rb +7 -2
  42. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  43. data/lib/formtastic/inputs/base/errors.rb +7 -7
  44. data/lib/formtastic/inputs/base/hints.rb +2 -2
  45. data/lib/formtastic/inputs/base/html.rb +10 -9
  46. data/lib/formtastic/inputs/base/labelling.rb +5 -8
  47. data/lib/formtastic/inputs/base/naming.rb +4 -4
  48. data/lib/formtastic/inputs/base/numeric.rb +1 -1
  49. data/lib/formtastic/inputs/base/options.rb +3 -4
  50. data/lib/formtastic/inputs/base/stringish.rb +10 -2
  51. data/lib/formtastic/inputs/base/timeish.rb +34 -22
  52. data/lib/formtastic/inputs/base/validations.rb +41 -13
  53. data/lib/formtastic/inputs/base/wrapping.rb +29 -26
  54. data/lib/formtastic/inputs/base.rb +22 -15
  55. data/lib/formtastic/inputs/boolean_input.rb +26 -12
  56. data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
  57. data/lib/formtastic/inputs/color_input.rb +41 -0
  58. data/lib/formtastic/inputs/country_input.rb +24 -5
  59. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  60. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  61. data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
  62. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  63. data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
  64. data/lib/formtastic/inputs/file_input.rb +2 -2
  65. data/lib/formtastic/inputs/hidden_input.rb +2 -6
  66. data/lib/formtastic/inputs/radio_input.rb +28 -22
  67. data/lib/formtastic/inputs/select_input.rb +36 -39
  68. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  69. data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
  70. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  71. data/lib/formtastic/inputs.rb +32 -21
  72. data/lib/formtastic/localized_string.rb +1 -1
  73. data/lib/formtastic/localizer.rb +24 -24
  74. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  75. data/lib/formtastic/version.rb +1 -1
  76. data/lib/formtastic.rb +20 -10
  77. data/lib/generators/formtastic/form/form_generator.rb +10 -4
  78. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  79. data/lib/generators/formtastic/install/install_generator.rb +5 -19
  80. data/lib/generators/templates/_form.html.slim +2 -2
  81. data/lib/generators/templates/formtastic.rb +46 -25
  82. data/lib/generators/templates/input.rb +19 -0
  83. data/sample/basic_inputs.html +23 -3
  84. data/script/integration-template.rb +74 -0
  85. data/script/integration.sh +19 -0
  86. data/spec/action_class_finder_spec.rb +12 -0
  87. data/spec/actions/button_action_spec.rb +8 -8
  88. data/spec/actions/generic_action_spec.rb +92 -56
  89. data/spec/actions/input_action_spec.rb +7 -7
  90. data/spec/actions/link_action_spec.rb +10 -10
  91. data/spec/builder/custom_builder_spec.rb +36 -20
  92. data/spec/builder/error_proc_spec.rb +4 -4
  93. data/spec/builder/semantic_fields_for_spec.rb +28 -29
  94. data/spec/fast_spec_helper.rb +12 -0
  95. data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
  96. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  97. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  98. data/spec/helpers/action_helper_spec.rb +75 -103
  99. data/spec/helpers/actions_helper_spec.rb +17 -17
  100. data/spec/helpers/form_helper_spec.rb +84 -33
  101. data/spec/helpers/input_helper_spec.rb +333 -285
  102. data/spec/helpers/inputs_helper_spec.rb +167 -121
  103. data/spec/helpers/reflection_helper_spec.rb +3 -3
  104. data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
  105. data/spec/i18n_spec.rb +26 -26
  106. data/spec/input_class_finder_spec.rb +10 -0
  107. data/spec/inputs/base/collections_spec.rb +76 -0
  108. data/spec/inputs/base/validations_spec.rb +480 -0
  109. data/spec/inputs/boolean_input_spec.rb +100 -65
  110. data/spec/inputs/check_boxes_input_spec.rb +200 -101
  111. data/spec/inputs/color_input_spec.rb +85 -0
  112. data/spec/inputs/country_input_spec.rb +20 -20
  113. data/spec/inputs/custom_input_spec.rb +3 -4
  114. data/spec/inputs/datalist_input_spec.rb +61 -0
  115. data/spec/inputs/date_picker_input_spec.rb +449 -0
  116. data/spec/inputs/date_select_input_spec.rb +249 -0
  117. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  118. data/spec/inputs/datetime_select_input_spec.rb +209 -0
  119. data/spec/inputs/email_input_spec.rb +5 -5
  120. data/spec/inputs/file_input_spec.rb +6 -6
  121. data/spec/inputs/hidden_input_spec.rb +22 -35
  122. data/spec/inputs/include_blank_spec.rb +11 -11
  123. data/spec/inputs/label_spec.rb +62 -25
  124. data/spec/inputs/number_input_spec.rb +112 -112
  125. data/spec/inputs/password_input_spec.rb +5 -5
  126. data/spec/inputs/phone_input_spec.rb +5 -5
  127. data/spec/inputs/placeholder_spec.rb +6 -6
  128. data/spec/inputs/radio_input_spec.rb +99 -55
  129. data/spec/inputs/range_input_spec.rb +66 -66
  130. data/spec/inputs/readonly_spec.rb +50 -0
  131. data/spec/inputs/search_input_spec.rb +5 -5
  132. data/spec/inputs/select_input_spec.rb +170 -170
  133. data/spec/inputs/string_input_spec.rb +68 -16
  134. data/spec/inputs/text_input_spec.rb +16 -16
  135. data/spec/inputs/time_picker_input_spec.rb +455 -0
  136. data/spec/inputs/time_select_input_spec.rb +261 -0
  137. data/spec/inputs/time_zone_input_spec.rb +54 -28
  138. data/spec/inputs/url_input_spec.rb +5 -5
  139. data/spec/inputs/with_options_spec.rb +7 -7
  140. data/spec/localizer_spec.rb +39 -17
  141. data/spec/namespaced_class_finder_spec.rb +79 -0
  142. data/spec/schema.rb +21 -0
  143. data/spec/spec_helper.rb +254 -221
  144. data/spec/support/custom_macros.rb +128 -95
  145. data/spec/support/shared_examples.rb +12 -0
  146. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  147. data/spec/support/test_environment.rb +26 -10
  148. metadata +177 -238
  149. data/.travis.yml +0 -8
  150. data/Appraisals +0 -11
  151. data/CHANGELOG +0 -371
  152. data/gemfiles/rails-3.0.gemfile +0 -7
  153. data/gemfiles/rails-3.1.gemfile +0 -7
  154. data/gemfiles/rails-3.2.gemfile +0 -7
  155. data/lib/formtastic/helpers/buttons_helper.rb +0 -310
  156. data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
  157. data/lib/formtastic/util.rb +0 -25
  158. data/lib/tasks/verify_rcov.rb +0 -44
  159. data/spec/helpers/buttons_helper_spec.rb +0 -166
  160. data/spec/helpers/commit_button_helper_spec.rb +0 -530
  161. data/spec/inputs/date_input_spec.rb +0 -227
  162. data/spec/inputs/datetime_input_spec.rb +0 -185
  163. data/spec/inputs/time_input_spec.rb +0 -267
  164. data/spec/support/deferred_garbage_collection.rb +0 -21
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,8 +6,11 @@ require 'action_pack'
6
6
  require 'action_view'
7
7
  require 'action_controller'
8
8
  require 'action_dispatch'
9
+ require 'active_record'
10
+
11
+ ActiveRecord::Base.establish_connection('url' => 'sqlite3::memory:', 'pool' => 1)
12
+ load 'spec/schema.rb'
9
13
 
10
- require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/util'))
11
14
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
12
15
 
13
16
  require 'ammeter/init'
@@ -16,13 +19,15 @@ require 'ammeter/init'
16
19
  # in ./support/ and its subdirectories in alphabetic order.
17
20
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each {|f| require f}
18
21
 
22
+ I18n.enforce_available_locales = false if I18n.respond_to?(:enforce_available_locales)
23
+
19
24
  module FakeHelpersModule
20
25
  end
21
26
 
22
27
  module FormtasticSpecHelper
23
28
  include ActionPack
24
29
  include ActionView::Context if defined?(ActionView::Context)
25
- include ActionController::RecordIdentifier
30
+ include ActionController::RecordIdentifier if defined?(ActionController::RecordIdentifier)
26
31
  include ActionView::Helpers::FormHelper
27
32
  include ActionView::Helpers::FormTagHelper
28
33
  include ActionView::Helpers::FormOptionsHelper
@@ -36,12 +41,15 @@ module FormtasticSpecHelper
36
41
  include ActionView::Helpers::AssetTagHelper
37
42
  include ActiveSupport
38
43
  include ActionController::PolymorphicRoutes if defined?(ActionController::PolymorphicRoutes)
39
-
44
+ include ActionDispatch::Routing::PolymorphicRoutes
45
+ include AbstractController::UrlFor if defined?(AbstractController::UrlFor)
46
+ include ActionView::RecordIdentifier if defined?(ActionView::RecordIdentifier)
47
+
40
48
  include Formtastic::Helpers::FormHelper
41
49
 
42
50
  def default_input_type(column_type, column_name = :generic_column_name)
43
- @new_post.stub!(column_name)
44
- @new_post.stub!(:column_for_attribute).and_return(mock('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?
45
53
 
46
54
  semantic_form_for(@new_post) do |builder|
47
55
  @default_type = builder.send(:default_input_type, column_name)
@@ -51,8 +59,8 @@ module FormtasticSpecHelper
51
59
  end
52
60
 
53
61
  def active_model_validator(kind, attributes, options = {})
54
- validator = mock("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
55
- validator.stub!(:kind).and_return(kind)
62
+ validator = double("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
63
+ allow(validator).to receive(:kind).and_return(kind)
56
64
  validator
57
65
  end
58
66
 
@@ -95,26 +103,17 @@ module FormtasticSpecHelper
95
103
  end
96
104
 
97
105
  module ::Namespaced
98
- class Post
99
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
100
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
101
-
102
- def id
103
- end
104
-
105
- def persisted?
106
- end
106
+ class Post < ActiveRecord::Base
107
107
  end
108
108
  end
109
109
 
110
- class ::Author
111
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
112
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
113
-
114
- def to_label
110
+ class ::Author < ActiveRecord::Base
111
+ def new_record?
112
+ !id
115
113
  end
116
114
 
117
- def persisted?
115
+ def to_label
116
+ [name, surname].compact.join(' ')
118
117
  end
119
118
  end
120
119
 
@@ -127,6 +126,10 @@ module FormtasticSpecHelper
127
126
  end
128
127
  end
129
128
 
129
+ class ::LegacyPost < ActiveRecord::Base
130
+ belongs_to :author, foreign_key: :post_author
131
+ end
132
+
130
133
  class ::Continent
131
134
  extend ActiveModel::Naming if defined?(ActiveModel::Naming)
132
135
  include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
@@ -139,7 +142,7 @@ module FormtasticSpecHelper
139
142
 
140
143
  ##
141
144
  # We can't mock :respond_to?, so we need a concrete class override
142
- class ::MongoidReflectionMock < RSpec::Mocks::Mock
145
+ class ::MongoidReflectionMock < RSpec::Mocks::Double
143
146
  def initialize(name=nil, stubs_and_options={})
144
147
  super name, stubs_and_options
145
148
  end
@@ -148,24 +151,72 @@ module FormtasticSpecHelper
148
151
  sym == :options ? false : super
149
152
  end
150
153
  end
154
+
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.
157
+ #
158
+ # TODO try delegate?
159
+ # delegate :map, :size, :length, :first, :to_ary, :each, :include?, :to => :array
160
+ class MockScope
161
+ attr_reader :array
162
+
163
+ def initialize(the_array)
164
+ @array = the_array
165
+ end
166
+
167
+ def map(&block)
168
+ array.map(&block)
169
+ end
170
+
171
+ def where(*args)
172
+ # array
173
+ self
174
+ end
175
+
176
+ def includes(*args)
177
+ self
178
+ end
179
+
180
+ def size
181
+ array.size
182
+ end
183
+ alias_method :length, :size
184
+
185
+ def first
186
+ array.first
187
+ end
188
+
189
+ def to_ary
190
+ array
191
+ end
192
+
193
+ def each(&block)
194
+ array.each(&block)
195
+ end
196
+
197
+ def include?(*args)
198
+ array.include?(*args)
199
+ end
200
+ end
151
201
 
152
202
  def _routes
153
- url_helpers = mock('url_helpers')
154
- url_helpers.stub!(:hash_for_posts_path).and_return({})
155
- url_helpers.stub!(:hash_for_post_path).and_return({})
156
- url_helpers.stub!(:hash_for_post_models_path).and_return({})
157
- url_helpers.stub!(:hash_for_authors_path).and_return({})
203
+ url_helpers = double('url_helpers')
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({})
158
208
 
159
- mock('_routes',
209
+ double('_routes',
160
210
  :url_helpers => url_helpers,
161
- :url_for => "/mock/path"
211
+ :url_for => "/mock/path",
212
+ :polymorphic_mappings => {}
162
213
  )
163
214
  end
164
215
 
165
216
  def controller
166
- env = mock('env', :[] => nil)
167
- request = mock('request', :env => env)
168
- mock('controller', :controller_path= => '', :params => {}, :request => request)
217
+ env = double('env', :[] => nil)
218
+ request = double('request', :env => env)
219
+ double('controller', :controller_path= => '', :params => {}, :request => request)
169
220
  end
170
221
 
171
222
  def default_url_options
@@ -185,209 +236,185 @@ module FormtasticSpecHelper
185
236
  def author_path(*args); "/authors/1"; end
186
237
  def authors_path(*args); "/authors"; end
187
238
  def new_author_path(*args); "/authors/new"; end
239
+
240
+ def author_array_or_scope(the_array = [@fred, @bob])
241
+ MockScope.new(the_array)
242
+ end
188
243
 
189
- @fred = ::Author.new
190
- @fred.stub!(:class).and_return(::Author)
191
- @fred.stub!(:to_label).and_return('Fred Smith')
192
- @fred.stub!(:login).and_return('fred_smith')
193
- @fred.stub!(:age).and_return(27)
194
- @fred.stub!(:id).and_return(37)
195
- @fred.stub!(:new_record?).and_return(false)
196
- @fred.stub!(:errors).and_return(mock('errors', :[] => nil))
197
- @fred.stub!(:to_key).and_return(nil)
198
- @fred.stub!(:persisted?).and_return(nil)
199
- @fred.stub!(:name).and_return('Fred')
200
-
201
- @bob = ::Author.new
202
- @bob.stub!(:to_label).and_return('Bob Rock')
203
- @bob.stub!(:login).and_return('bob')
204
- @bob.stub!(:age).and_return(43)
205
- @bob.stub!(:created_at)
206
- @bob.stub!(:id).and_return(42)
207
- @bob.stub!(:posts).and_return([])
208
- @bob.stub!(:post_ids).and_return([])
209
- @bob.stub!(:new_record?).and_return(false)
210
- @bob.stub!(:errors).and_return(mock('errors', :[] => nil))
211
- @bob.stub!(:to_key).and_return(nil)
212
- @bob.stub!(:persisted?).and_return(nil)
213
- @bob.stub!(:name).and_return('Bob')
214
-
215
- @james = ::Author.new
216
- @james.stub!(:to_label).and_return('James Shock')
217
- @james.stub!(:login).and_return('james')
218
- @james.stub!(:age).and_return(38)
219
- @james.stub!(:id).and_return(75)
220
- @james.stub!(:posts).and_return([])
221
- @james.stub!(:post_ids).and_return([])
222
- @james.stub!(:new_record?).and_return(false)
223
- @james.stub!(:errors).and_return(mock('errors', :[] => nil))
224
- @james.stub!(:to_key).and_return(nil)
225
- @james.stub!(:persisted?).and_return(nil)
226
- @james.stub!(:name).and_return('James')
227
-
228
-
229
- ::Author.stub!(:scoped).and_return(::Author)
230
- ::Author.stub!(:find).and_return([@fred, @bob])
231
- ::Author.stub!(:all).and_return([@fred, @bob])
232
- ::Author.stub!(:where).and_return([@fred, @bob])
233
- ::Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
234
- ::Author.stub!(:human_name).and_return('::Author')
235
- ::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
236
- ::Author.stub!(:content_columns).and_return([mock('column', :name => 'login'), mock('column', :name => 'created_at')])
237
- ::Author.stub!(:to_key).and_return(nil)
238
- ::Author.stub!(:persisted?).and_return(nil)
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)
239
258
 
240
259
  @hash_backed_author = HashBackedAuthor.new
241
260
 
242
261
  # Sometimes we need a mock @post object and some Authors for belongs_to
243
- @new_post = mock('post')
244
- @new_post.stub!(:class).and_return(::Post)
245
- @new_post.stub!(:id).and_return(nil)
246
- @new_post.stub!(:new_record?).and_return(true)
247
- @new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
248
- @new_post.stub!(:author).and_return(nil)
249
- @new_post.stub!(:author_attributes=).and_return(nil)
250
- @new_post.stub!(:authors).and_return([@fred])
251
- @new_post.stub!(:authors_attributes=)
252
- @new_post.stub!(:reviewer).and_return(nil)
253
- @new_post.stub!(:main_post).and_return(nil)
254
- @new_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
255
- @new_post.stub!(:to_key).and_return(nil)
256
- @new_post.stub!(:to_model).and_return(@new_post)
257
- @new_post.stub!(:persisted?).and_return(nil)
258
-
259
- @freds_post = mock('post')
260
- @freds_post.stub!(:to_ary)
261
- @freds_post.stub!(:class).and_return(::Post)
262
- @freds_post.stub!(:to_label).and_return('Fred Smith')
263
- @freds_post.stub!(:id).and_return(19)
264
- @freds_post.stub!(:title).and_return("Hello World")
265
- @freds_post.stub!(:author).and_return(@fred)
266
- @freds_post.stub!(:author_id).and_return(@fred.id)
267
- @freds_post.stub!(:authors).and_return([@fred])
268
- @freds_post.stub!(:author_ids).and_return([@fred.id])
269
- @freds_post.stub!(:new_record?).and_return(false)
270
- @freds_post.stub!(:errors).and_return(mock('errors', :[] => nil))
271
- @freds_post.stub!(:to_key).and_return(nil)
272
- @freds_post.stub!(:persisted?).and_return(nil)
273
- @fred.stub!(:posts).and_return([@freds_post])
274
- @fred.stub!(:post_ids).and_return([@freds_post.id])
275
-
276
- ::Post.stub!(:scoped).and_return(::Post)
277
- ::Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
278
- ::Post.stub!(:human_name).and_return('Post')
279
- ::Post.stub!(:reflect_on_all_validations).and_return([])
280
- ::Post.stub!(:reflect_on_validations_for).and_return([])
281
- ::Post.stub!(:reflections).and_return({})
282
- ::Post.stub!(:reflect_on_association).and_return do |column_name|
262
+ @new_post = double('post')
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}
278
+
279
+ @freds_post = double('post')
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|
283
305
  case column_name
284
306
  when :author, :author_status
285
- mock = mock('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
286
- mock.stub!(:[]).with(:class_name).and_return("Author")
307
+ mock = double('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
308
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
287
309
  mock
288
310
  when :reviewer
289
- mock = mock('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
290
- mock.stub!(:[]).with(:class_name).and_return("Author")
311
+ mock = double('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
312
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
291
313
  mock
292
314
  when :authors
293
- mock('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
315
+ double('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
294
316
  when :sub_posts
295
- mock('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
317
+ double('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
296
318
  when :main_post
297
- mock('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
319
+ double('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
298
320
  when :mongoid_reviewer
299
321
  ::MongoidReflectionMock.new('reflection',
300
322
  :options => Proc.new { raise NoMethodError, "Mongoid has no reflection.options" },
301
323
  :klass => ::Author, :macro => :referenced_in, :foreign_key => "reviewer_id") # custom id
302
324
  end
303
- end
304
- ::Post.stub!(:find).and_return([@freds_post])
305
- ::Post.stub!(:all).and_return([@freds_post])
306
- ::Post.stub!(:where).and_return([@freds_post])
307
- ::Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
308
- ::Post.stub!(:to_key).and_return(nil)
309
- ::Post.stub!(:persisted?).and_return(nil)
310
- ::Post.stub!(:to_ary)
311
-
312
- ::MongoPost.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
313
- ::MongoPost.stub!(:human_name).and_return('MongoPost')
314
- ::MongoPost.stub!(:associations).and_return({
315
- :sub_posts => mock('reflection', :options => {:polymorphic => true}, :klass => ::MongoPost, :macro => :has_many),
325
+ }
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({
337
+ :sub_posts => double('reflection', :options => {:polymorphic => true}, :klass => ::MongoPost, :macro => :has_many),
316
338
  :options => []
317
339
  })
318
- ::MongoPost.stub!(:find).and_return([@freds_post])
319
- ::MongoPost.stub!(:all).and_return([@freds_post])
320
- ::MongoPost.stub!(:where).and_return([@freds_post])
321
- ::MongoPost.stub!(:to_key).and_return(nil)
322
- ::MongoPost.stub!(:persisted?).and_return(nil)
323
- ::MongoPost.stub!(:to_ary)
324
- ::MongoPost.stub!(:model_name).and_return( mock(:model_name_mock, :singular => "post", :plural => "posts", :param_key => "post", :route_key => "posts") )
325
-
326
- @new_mm_post = mock('mm_post')
327
- @new_mm_post.stub!(:class).and_return(::MongoPost)
328
- @new_mm_post.stub!(:id).and_return(nil)
329
- @new_mm_post.stub!(:new_record?).and_return(true)
330
- @new_mm_post.stub!(:errors).and_return(mock('errors', :[] => nil))
331
- @new_mm_post.stub!(:title).and_return("Hello World")
332
- @new_mm_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
333
- @new_mm_post.stub!(:to_key).and_return(nil)
334
- @new_mm_post.stub!(:to_model).and_return(@new_mm_post)
335
- @new_mm_post.stub!(:persisted?).and_return(nil)
336
-
337
- @mock_file = mock('file')
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") )
347
+
348
+ @new_mm_post = double('mm_post')
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)
359
+
360
+ @mock_file = double('file')
338
361
  Formtastic::FormBuilder.file_methods.each do |method|
339
- @mock_file.stub!(method).and_return(true)
362
+ allow(@mock_file).to receive(method).and_return(true)
340
363
  end
341
364
 
342
- @new_post.stub!(:title)
343
- @new_post.stub!(:email)
344
- @new_post.stub!(:url)
345
- @new_post.stub!(:phone)
346
- @new_post.stub!(:search)
347
- @new_post.stub!(:to_ary)
348
- @new_post.stub!(:body)
349
- @new_post.stub!(:published)
350
- @new_post.stub!(:publish_at)
351
- @new_post.stub!(:created_at)
352
- @new_post.stub!(:secret).and_return(1)
353
- @new_post.stub!(:url)
354
- @new_post.stub!(:email)
355
- @new_post.stub!(:search)
356
- @new_post.stub!(:phone)
357
- @new_post.stub!(:time_zone)
358
- @new_post.stub!(:category_name)
359
- @new_post.stub!(:allow_comments).and_return(true)
360
- @new_post.stub!(:answer_comments)
361
- @new_post.stub!(:country)
362
- @new_post.stub!(:country_subdivision)
363
- @new_post.stub!(:country_code)
364
- @new_post.stub!(:document).and_return(@mock_file)
365
- @new_post.stub!(:column_for_attribute).with(:meta_description).and_return(mock('column', :type => :string, :limit => 255))
366
- @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 50))
367
- @new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
368
- @new_post.stub!(:column_for_attribute).with(:published).and_return(mock('column', :type => :boolean))
369
- @new_post.stub!(:column_for_attribute).with(:publish_at).and_return(mock('column', :type => :date))
370
- @new_post.stub!(:column_for_attribute).with(:time_zone).and_return(mock('column', :type => :string))
371
- @new_post.stub!(:column_for_attribute).with(:allow_comments).and_return(mock('column', :type => :boolean))
372
- @new_post.stub!(:column_for_attribute).with(:author).and_return(mock('column', :type => :integer))
373
- @new_post.stub!(:column_for_attribute).with(:country).and_return(mock('column', :type => :string, :limit => 255))
374
- @new_post.stub!(:column_for_attribute).with(:country_subdivision).and_return(mock('column', :type => :string, :limit => 255))
375
- @new_post.stub!(:column_for_attribute).with(:country_code).and_return(mock('column', :type => :string, :limit => 255))
376
- @new_post.stub!(:column_for_attribute).with(:email).and_return(mock('column', :type => :string, :limit => 255))
377
- @new_post.stub!(:column_for_attribute).with(:url).and_return(mock('column', :type => :string, :limit => 255))
378
- @new_post.stub!(:column_for_attribute).with(:phone).and_return(mock('column', :type => :string, :limit => 255))
379
- @new_post.stub!(:column_for_attribute).with(:search).and_return(mock('column', :type => :string, :limit => 255))
380
- @new_post.stub!(:column_for_attribute).with(:document).and_return(nil)
381
-
382
- @new_post.stub!(:author).and_return(@bob)
383
- @new_post.stub!(:author_id).and_return(@bob.id)
384
-
385
- @new_post.stub!(:reviewer).and_return(@fred)
386
- @new_post.stub!(:reviewer_id).and_return(@fred.id)
387
-
388
- @new_post.should_receive(:publish_at=).any_number_of_times
389
- @new_post.should_receive(:title=).any_number_of_times
390
- @new_post.stub!(:main_post_id).and_return(nil)
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)
412
+
413
+ # @new_post.should_receive(:publish_at=).at_least(:once)
414
+ allow(@new_post).to receive(:publish_at=)
415
+ # @new_post.should_receive(:title=).at_least(:once)
416
+ allow(@new_post).to receive(:title=)
417
+ allow(@new_post).to receive(:main_post_id).and_return(nil)
391
418
 
392
419
  end
393
420
 
@@ -413,20 +440,26 @@ module FormtasticSpecHelper
413
440
  yield
414
441
  Formtastic::FormBuilder.send(:"#{config_method_name}=", old_value)
415
442
  end
443
+
444
+ RSpec::Matchers.define :errors_matcher do |expected|
445
+ match { |actual| actual.to_s == expected.to_s }
446
+ end
447
+ end
416
448
 
449
+ class ::ActionView::Base
450
+ include Formtastic::Helpers::FormHelper
417
451
  end
418
452
 
419
453
  ::ActiveSupport::Deprecation.silenced = false
420
454
 
421
455
  RSpec.configure do |config|
422
- config.before(:each) do
456
+ config.infer_spec_type_from_file_location!
457
+
458
+ config.filter_run focus: true
459
+ config.filter_run_excluding skip: true
460
+ config.run_all_when_everything_filtered = true
461
+
462
+ config.before(:example) do
423
463
  Formtastic::Localizer.cache.clear!
424
464
  end
425
-
426
- config.before(:all) do
427
- DeferredGarbageCollection.start unless ENV["DEFER_GC"] == "false"
428
- end
429
- config.after(:all) do
430
- DeferredGarbageCollection.reconsider unless ENV["DEFER_GC"] == "false"
431
- end
432
465
  end