with_model 2.1.7 → 2.2.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.
data/spec/readme_spec.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ require "spec_helper"
4
4
 
5
- describe 'A blog post' do
5
+ describe "A blog post" do
6
6
  before do
7
- stub_const('MyModule', Module.new)
7
+ stub_const("MyModule", Module.new)
8
8
  end
9
9
 
10
10
  with_model :BlogPost do
@@ -21,11 +21,11 @@ describe 'A blog post' do
21
21
  validates_presence_of :title
22
22
 
23
23
  def self.some_class_method
24
- 'chunky'
24
+ "chunky"
25
25
  end
26
26
 
27
27
  def some_instance_method
28
- 'bacon'
28
+ "bacon"
29
29
  end
30
30
  end
31
31
  end
@@ -43,46 +43,46 @@ describe 'A blog post' do
43
43
  end
44
44
  end
45
45
 
46
- it 'can be accessed as a constant' do
46
+ it "can be accessed as a constant" do
47
47
  expect(BlogPost).to be
48
48
  end
49
49
 
50
- it 'has the module' do
50
+ it "has the module" do
51
51
  expect(BlogPost.include?(MyModule)).to be true
52
52
  end
53
53
 
54
- it 'has the class method' do
55
- expect(BlogPost.some_class_method).to eq 'chunky'
54
+ it "has the class method" do
55
+ expect(BlogPost.some_class_method).to eq "chunky"
56
56
  end
57
57
 
58
- it 'has the instance method' do
59
- expect(BlogPost.new.some_instance_method).to eq 'bacon'
58
+ it "has the instance method" do
59
+ expect(BlogPost.new.some_instance_method).to eq "bacon"
60
60
  end
61
61
 
62
- it 'can do all the things a regular model can' do
62
+ it "can do all the things a regular model can" do
63
63
  record = BlogPost.new
64
64
  expect(record).not_to be_valid
65
- record.title = 'foo'
65
+ record.title = "foo"
66
66
  expect(record).to be_valid
67
67
  expect(record.save).to be true
68
68
  expect(record.reload).to eq record
69
- record.comments.create!(text: 'Lorem ipsum')
69
+ record.comments.create!(text: "Lorem ipsum")
70
70
  expect(record.comments.count).to eq 1
71
71
  end
72
72
 
73
73
  # with_model classes can have inheritance.
74
- class Car < ActiveRecord::Base
74
+ class Car < ActiveRecord::Base # standard:disable Lint/ConstantDefinitionInBlock
75
75
  self.abstract_class = true
76
76
  end
77
77
 
78
78
  with_model :Ford, superclass: Car
79
79
 
80
- it 'has a specified superclass' do
80
+ it "has a specified superclass" do
81
81
  expect(Ford < Car).to be true
82
82
  end
83
83
  end
84
84
 
85
- describe 'with_model can be run within RSpec :all hook' do
85
+ describe "with_model can be run within RSpec :all hook" do
86
86
  with_model :BlogPost, scope: :all do
87
87
  table do |t|
88
88
  t.string :title
@@ -93,26 +93,26 @@ describe 'with_model can be run within RSpec :all hook' do
93
93
  BlogPost.create # without scope: :all these will fail
94
94
  end
95
95
 
96
- it 'has been initialized within before(:all)' do
96
+ it "has been initialized within before(:all)" do
97
97
  expect(BlogPost.count).to eq 1
98
98
  end
99
99
  end
100
100
 
101
- describe 'another example group' do
102
- it 'does not have the constant anymore' do
101
+ describe "another example group" do
102
+ it "does not have the constant anymore" do
103
103
  expect(defined?(BlogPost)).to be_falsy
104
104
  end
105
105
  end
106
106
 
107
- describe 'with table options' do
107
+ describe "with table options" do
108
108
  with_model :WithOptions do
109
109
  table id: false do |t|
110
- t.string 'foo'
110
+ t.string "foo"
111
111
  t.timestamps null: false
112
112
  end
113
113
  end
114
114
 
115
- it 'respects the additional options' do
116
- expect(WithOptions.columns.map(&:name)).not_to include('id')
115
+ it "respects the additional options" do
116
+ expect(WithOptions.columns.map(&:name)).not_to include("id")
117
117
  end
118
118
  end
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Workaround for JRuby CI failure https://github.com/jruby/jruby/issues/6547#issuecomment-774104996
4
- if RUBY_ENGINE == 'jruby'
5
- require 'i18n/backend'
6
- require 'i18n/backend/simple'
7
- end
8
-
9
- require 'simplecov'
10
- SimpleCov.start
11
-
12
- require 'bundler/setup'
13
- require 'with_model'
3
+ require "bundler/setup"
4
+ require "with_model"
14
5
 
15
6
  RSpec.configure do |config|
16
7
  config.extend WithModel
@@ -26,24 +17,21 @@ RSpec.configure do |config|
26
17
  end
27
18
  end
28
19
 
29
- is_jruby = RUBY_PLATFORM == 'java'
30
- adapter = is_jruby ? 'jdbcsqlite3' : 'sqlite3'
31
-
32
20
  # WithModel requires ActiveRecord::Base.connection to be established.
33
21
  # If ActiveRecord already has a connection, as in a Rails app, this is unnecessary.
34
- require 'active_record'
35
- ActiveRecord::Base.establish_connection(adapter: adapter, database: ':memory:')
22
+ require "active_record"
23
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
36
24
 
37
25
  I18n.enforce_available_locales = true if defined?(I18n) && I18n.respond_to?(:enforce_available_locales=)
38
26
 
39
- if ENV['LOGGER']
40
- require 'logger'
27
+ if ENV["LOGGER"]
28
+ require "logger"
41
29
  ActiveRecord::Base.logger = Logger.new($stdout)
42
30
  end
43
31
 
44
32
  module SpecHelper
45
33
  module RailsTestCompatibility
46
- require 'minitest'
34
+ require "minitest"
47
35
  include Minitest::Assertions
48
36
 
49
37
  def assertions
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_model'
4
- require 'spec_helper'
3
+ require "active_model"
4
+ require "spec_helper"
5
5
 
6
- shared_examples_for 'ActiveModel' do
7
- require 'active_model/lint'
6
+ shared_examples_for "ActiveModel" do
7
+ require "active_model/lint"
8
8
  include SpecHelper::RailsTestCompatibility
9
9
  include ActiveModel::Lint::Tests
10
10
 
@@ -12,26 +12,24 @@ shared_examples_for 'ActiveModel' do
12
12
  active_model_lint_tests = active_model_methods.map(&:to_s).grep(/^test/)
13
13
 
14
14
  active_model_lint_tests.each do |method_name|
15
- friendly_name = method_name.tr('_', ' ')
15
+ friendly_name = method_name.tr("_", " ")
16
16
 
17
- # rubocop:disable RSpec/NoExpectationExample
18
17
  example friendly_name do
19
18
  public_send method_name.to_sym
20
19
  end
21
- # rubocop:enable RSpec/NoExpectationExample
22
20
  end
23
21
 
24
22
  before { @model = subject }
25
23
  end
26
24
 
27
- describe 'a temporary ActiveRecord model created with with_model' do
25
+ describe "a temporary ActiveRecord model created with with_model" do
28
26
  non_shadowing_example_ran = false
29
27
 
30
28
  describe "which doesn't shadow an existing class" do
31
29
  with_model :BlogPost do
32
30
  table do |t|
33
- t.string 'title'
34
- t.text 'content'
31
+ t.string "title"
32
+ t.text "content"
35
33
  t.timestamps null: false
36
34
  end
37
35
 
@@ -46,13 +44,13 @@ describe 'a temporary ActiveRecord model created with with_model' do
46
44
  non_shadowing_example_ran = true
47
45
  end
48
46
 
49
- it 'acts like a normal ActiveRecord model' do
50
- record = BlogPost.create!(title: 'New blog post', content: 'Hello, world!')
47
+ it "acts like a normal ActiveRecord model" do
48
+ record = BlogPost.create!(title: "New blog post", content: "Hello, world!")
51
49
 
52
50
  record.reload
53
51
 
54
- expect(record.title).to eq 'New blog post'
55
- expect(record.content).to eq 'Hello, world!'
52
+ expect(record.title).to eq "New blog post"
53
+ expect(record.content).to eq "Hello, world!"
56
54
  expect(record.updated_at).to be_present
57
55
 
58
56
  record.destroy
@@ -60,123 +58,126 @@ describe 'a temporary ActiveRecord model created with with_model' do
60
58
  expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
61
59
  end
62
60
 
63
- describe 'the class' do
61
+ describe "the class" do
64
62
  subject { BlogPost.new }
65
63
 
66
- it_behaves_like 'ActiveModel'
64
+ it_behaves_like "ActiveModel"
67
65
  end
68
66
 
69
- it 'has the methods defined in its model block' do
70
- expect(BlogPost.new(title: 'New blog post').fancy_title).to eq 'Title: New blog post'
67
+ it "has the methods defined in its model block" do
68
+ expect(BlogPost.new(title: "New blog post").fancy_title).to eq "Title: New blog post"
71
69
  end
72
70
 
73
- it 'defines a constant' do
71
+ it "defines a constant" do
74
72
  expect(BlogPost).to be_a(Class)
75
73
  end
76
74
 
77
- describe '.with_model?' do
78
- it 'returns true' do
75
+ describe ".with_model?" do
76
+ it "returns true" do
79
77
  expect(BlogPost.with_model?).to be true
80
78
  end
81
79
  end
82
80
 
83
- it 'is its own base_class' do
81
+ it "is its own base_class" do
84
82
  expect(BlogPost.base_class).to eq BlogPost
85
83
  end
86
84
  end
87
85
 
88
- context 'after an example which uses with_model without shadowing an existing constant' do
89
- it 'returns the constant to its undefined state' do
86
+ context "after an example which uses with_model without shadowing an existing constant" do
87
+ it "returns the constant to its undefined state" do
90
88
  expect(non_shadowing_example_ran).to be true
91
89
  expect(defined?(BlogPost)).to be_falsy
92
90
  end
93
91
  end
94
92
 
95
- describe 'constant restoration' do
96
- before { stub_const('MyConst', 1) }
93
+ describe "constant restoration" do
94
+ before { stub_const("MyConst", 1) }
97
95
 
98
96
  shadowing_example_ran = false
99
97
 
100
- context 'with the with_model block' do
98
+ context "with the with_model block" do
101
99
  with_model :MyConst
102
100
 
103
101
  after do
104
102
  shadowing_example_ran = true
105
103
  end
106
104
 
107
- it 'shadows that constant' do
105
+ it "shadows that constant" do
108
106
  expect(MyConst).to be_a(Class)
109
107
  end
110
108
  end
111
109
 
112
- context 'without the with_model block' do
113
- it 'returns the constant to its original value' do
110
+ context "without the with_model block" do
111
+ it "returns the constant to its original value" do
114
112
  expect(shadowing_example_ran).to be true
115
113
  expect(MyConst).to eq 1
116
114
  end
117
115
  end
118
116
  end
119
117
 
120
- describe 'with a plural name' do
118
+ describe "with a plural name" do
121
119
  with_model :BlogPosts
122
120
 
123
- it 'does not singularize the constant name' do
121
+ it "does not singularize the constant name" do
124
122
  expect(BlogPosts).to be
125
123
  expect(-> { BlogPost }).to raise_error(NameError)
126
124
  end
127
125
  end
128
126
 
129
- describe 'with a name containing capital letters' do
127
+ describe "with a name containing capital letters" do
130
128
  with_model :BlogPost
131
129
 
132
- it 'tableizes the table name' do
130
+ it "tableizes the table name" do
133
131
  expect(BlogPost.table_name).to match(/_blog_posts_/)
134
132
  expect(BlogPost.table_name).to eq BlogPost.table_name.downcase
135
133
  end
136
134
  end
137
135
 
138
- describe 'with a name with underscores' do
136
+ describe "with a name with underscores" do
139
137
  with_model :blog_post
140
138
 
141
- it 'constantizes the name' do
139
+ it "constantizes the name" do
142
140
  expect(BlogPost).to be
143
141
  end
144
142
 
145
- it 'tableizes the table name' do
143
+ it "tableizes the table name" do
146
144
  expect(BlogPost.table_name).to match(/_blog_posts_/)
147
145
  expect(BlogPost.table_name).to eq BlogPost.table_name.downcase
148
146
  end
149
147
  end
150
148
 
151
- describe 'with a name which is namespaced' do
152
- before { stub_const('Stuff', Module.new) }
149
+ describe "with a name which is namespaced" do
150
+ before { stub_const("Stuff", Module.new) }
153
151
 
154
- with_model :'Stuff::BlogPost'
152
+ with_model :"Stuff::BlogPost"
155
153
 
156
- it 'creates the model in the namespace' do
154
+ it "creates the model in the namespace" do
157
155
  expect(defined?(BlogPost)).to be_falsey
158
156
  expect(defined?(Stuff::BlogPost)).to be_truthy
159
157
  end
160
158
  end
161
159
 
162
- describe 'using the constant in the model block' do
160
+ describe "using the constant in the model block" do
163
161
  with_model :BlogPost do
164
162
  model do
165
- raise 'I am not myself!' unless self == BlogPost
163
+ raise "I am not myself!" unless self == BlogPost
166
164
  end
167
165
  end
168
166
 
169
- it 'is available' do
167
+ it "is available" do
170
168
  expect(BlogPost).to be
171
169
  end
172
170
  end
173
171
 
174
- context 'with a mixin' do
172
+ context "with a mixin" do
175
173
  let(:mixin) do
176
- Module.new { def foo; end }
174
+ Module.new {
175
+ def foo
176
+ end
177
+ }
177
178
  end
178
179
 
179
- before { stub_const('AMixin', mixin) }
180
+ before { stub_const("AMixin", mixin) }
180
181
 
181
182
  with_model :WithAMixin do
182
183
  model do
@@ -184,108 +185,109 @@ describe 'a temporary ActiveRecord model created with with_model' do
184
185
  end
185
186
  end
186
187
 
187
- it 'has the mixin' do
188
+ it "has the mixin" do
188
189
  expect(-> { WithAMixin.new.foo }).not_to raise_error
189
190
  expect(WithAMixin.include?(AMixin)).to be true
190
191
  end
191
192
  end
192
193
 
193
- context 'with a mixin that has a class_eval' do
194
+ context "with a mixin that has a class_eval" do
194
195
  subject { WithAClassEval.new }
195
196
 
196
197
  let(:mixin) do
197
198
  Module.new do
198
199
  def self.included(klass)
199
200
  klass.class_eval do
200
- after_save { |object| object.my_method } # rubocop:disable Style/SymbolProc
201
+ after_save { |object| object.my_method }
201
202
  end
202
203
  end
203
204
  end
204
205
  end
205
206
 
206
- before { stub_const('AMixin', mixin) }
207
+ before { stub_const("AMixin", mixin) }
207
208
 
208
209
  with_model :WithAClassEval do
209
210
  model do
210
211
  include AMixin
211
- def my_method; end
212
+ def my_method
213
+ end
212
214
  end
213
215
  end
214
216
 
215
- it 'only has one after_save callback' do
217
+ it "only has one after_save callback" do
216
218
  expect(subject).to receive(:my_method).once
217
219
  subject.save
218
220
  end
219
221
 
220
- it 'still only has one after_save callback in future tests' do
222
+ it "still only has one after_save callback in future tests" do
221
223
  expect(subject).to receive(:my_method).once
222
224
  subject.save
223
225
  end
224
226
  end
225
227
 
226
- context 'with table options' do
228
+ context "with table options" do
227
229
  with_model :WithOptions do
228
230
  table id: false do |t|
229
- t.string 'foo'
231
+ t.string "foo"
230
232
  t.timestamps null: false
231
233
  end
232
234
  end
233
235
 
234
- it 'respects the additional options' do
235
- expect(WithOptions.columns.map(&:name)).not_to include('id')
236
+ it "respects the additional options" do
237
+ expect(WithOptions.columns.map(&:name)).not_to include("id")
236
238
  end
237
239
  end
238
240
 
239
- context 'without a block' do
241
+ context "without a block" do
240
242
  with_model :BlogPost
241
243
 
242
- it 'acts like a normal ActiveRecord model' do
244
+ it "acts like a normal ActiveRecord model" do
243
245
  record = BlogPost.create!
244
246
  record.reload
245
247
  record.destroy
246
248
  expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
247
249
  end
248
250
 
249
- describe 'the class' do
251
+ describe "the class" do
250
252
  subject { BlogPost.new }
251
253
 
252
- it_behaves_like 'ActiveModel'
254
+ it_behaves_like "ActiveModel"
253
255
  end
254
256
  end
255
257
 
256
- context 'with an empty block' do
257
- with_model(:BlogPost) {} # rubocop:disable Lint/EmptyBlock
258
+ context "with an empty block" do
259
+ with_model(:BlogPost) {}
258
260
 
259
- it 'acts like a normal ActiveRecord model' do
261
+ it "acts like a normal ActiveRecord model" do
260
262
  record = BlogPost.create!
261
263
  record.reload
262
264
  record.destroy
263
265
  expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
264
266
  end
265
267
 
266
- describe 'the class' do
268
+ describe "the class" do
267
269
  subject { BlogPost.new }
268
270
 
269
- it_behaves_like 'ActiveModel'
271
+ it_behaves_like "ActiveModel"
270
272
  end
271
273
  end
272
274
 
273
- context 'without a model block' do
275
+ context "without a model block" do
274
276
  with_model :BlogPost do
275
277
  table do |t|
276
- t.string 'title'
277
- t.text 'content'
278
+ t.string "title"
279
+ t.text "content"
278
280
  t.timestamps null: false
279
281
  end
280
282
  end
281
283
 
282
- it 'acts like a normal ActiveRecord model' do
283
- record = BlogPost.create!(title: 'New blog post', content: 'Hello, world!')
284
+ it "acts like a normal ActiveRecord model" do
285
+ record = BlogPost.create!(title: "New blog post", content: "Hello, world!")
284
286
 
285
287
  record.reload
286
288
 
287
- expect(record.title).to eq 'New blog post'
288
- expect(record.content).to eq 'Hello, world!'
289
+ expect(record.title).to eq "New blog post"
290
+ expect(record.content).to eq "Hello, world!"
289
291
  expect(record.updated_at).to be_present
290
292
 
291
293
  record.destroy
@@ -293,56 +295,32 @@ describe 'a temporary ActiveRecord model created with with_model' do
293
295
  expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
294
296
  end
295
297
 
296
- describe 'the class' do
298
+ describe "the class" do
297
299
  subject { BlogPost.new }
298
300
 
299
- it_behaves_like 'ActiveModel'
301
+ it_behaves_like "ActiveModel"
300
302
  end
301
303
  end
302
304
 
303
- context 'without a table or model block' do
305
+ context "without a table or model block" do
304
306
  with_model :BlogPost
305
307
 
306
- it 'acts like a normal ActiveRecord model' do
307
- expect(BlogPost.columns.map(&:name)).to eq ['id']
308
+ it "acts like a normal ActiveRecord model" do
309
+ expect(BlogPost.columns.map(&:name)).to eq ["id"]
308
310
  record = BlogPost.create!
309
311
  record.reload
310
312
  record.destroy
311
313
  expect { record.reload }.to raise_error(ActiveRecord::RecordNotFound)
312
314
  end
313
315
 
314
- describe 'the class' do
316
+ describe "the class" do
315
317
  subject { BlogPost.new }
316
318
 
317
- it_behaves_like 'ActiveModel'
318
- end
319
- end
320
-
321
- context 'with ActiveSupport::DescendantsTracker' do
322
- with_model :BlogPost do
323
- model do
324
- def self.inspect
325
- "BlogPost class #{object_id}"
326
- end
327
- end
328
- end
329
-
330
- def blog_post_classes
331
- ActiveRecord::Base.descendants.select do |c|
332
- c.table_name == BlogPost.table_name
333
- end
334
- end
335
-
336
- it 'includes the correct model class in descendants on the first test run' do
337
- expect(blog_post_classes).to eq [BlogPost]
338
- end
339
-
340
- it 'includes the correct model class in descendants on the second test run' do
341
- expect(blog_post_classes).to eq [BlogPost]
319
+ it_behaves_like "ActiveModel"
342
320
  end
343
321
  end
344
322
 
345
- context 'with_model can be run within RSpec :all hook' do
323
+ context "with_model can be run within RSpec :all hook" do
346
324
  with_model :BlogPost, scope: :all do
347
325
  table do |t|
348
326
  t.string :title
@@ -353,42 +331,55 @@ describe 'a temporary ActiveRecord model created with with_model' do
353
331
  BlogPost.create # without scope: :all these will fail
354
332
  end
355
333
 
356
- it 'has been initialized within before(:all)' do
334
+ it "has been initialized within before(:all)" do
357
335
  expect(BlogPost.count).to eq 1
358
336
  end
359
337
  end
360
338
 
361
339
  context "with 'superclass' option" do
362
- class BlogPostParent < ActiveRecord::Base
340
+ class BlogPostParent < ActiveRecord::Base # standard:disable Lint/ConstantDefinitionInBlock
363
341
  self.abstract_class = true
364
342
  end
365
343
 
366
- after(:all) do
367
- Object.__send__(:remove_const, 'BlogPostParent')
368
- end
369
-
370
344
  with_model :BlogPost, superclass: BlogPostParent do
371
345
  table do |t|
372
- t.string 'title'
346
+ t.string "title"
373
347
  end
374
348
  end
375
349
 
376
- describe 'the class' do
350
+ describe "the class" do
377
351
  subject { BlogPost.new }
378
352
 
379
- it_behaves_like 'ActiveModel'
353
+ it_behaves_like "ActiveModel"
380
354
  end
381
355
 
382
- it 'is a subclass of the supplied superclass' do
356
+ it "is a subclass of the supplied superclass" do
383
357
  expect(BlogPost < BlogPostParent).to be true
384
358
  end
385
359
 
386
- it 'is its own base_class' do
360
+ it "is its own base_class" do
387
361
  expect(BlogPost.base_class).to eq BlogPost
388
362
  end
389
363
 
390
- it 'responds to .with_model? with true' do
364
+ it "responds to .with_model? with true" do
391
365
  expect(BlogPost.with_model?).to be true
392
366
  end
393
367
  end
368
+
369
+ context "with 'superclass' that connects to a different database" do
370
+ class ApplicationRecordInDifferentDatabase < ActiveRecord::Base # standard:disable Lint/ConstantDefinitionInBlock
371
+ self.abstract_class = true
372
+ establish_connection(ActiveRecord::Base.connection_pool.db_config.configuration_hash)
373
+ end
374
+
375
+ with_model :BlogPost, superclass: ApplicationRecordInDifferentDatabase do
376
+ table do |t|
377
+ t.string "title"
378
+ end
379
+ end
380
+
381
+ it "uses the superclass connection" do
382
+ expect(BlogPost.connection.tables).to include(BlogPost.table_name)
383
+ end
384
+ end
394
385
  end