with_model 2.3.1 → 2.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e161c7fe750e7eb3b78e178a14b2e23ef88b0fa4612abfb22e3920be9eda614e
4
- data.tar.gz: fb6d9310626f6a006463782d179406e1a2af10b6672899fb57c2bf26f6df61a0
3
+ metadata.gz: 82365b7ef365626c49c238c05258d85603f6d9cf18c080c5ef39329c1ecf3346
4
+ data.tar.gz: d1cf7a5a2f060ab68b1daf20a0495de5a09b706b272387810c3c4acce6e42470
5
5
  SHA512:
6
- metadata.gz: 7d80585ba48b4b87593f9b7f18b8c4674391e51458b5e273ee121e4962bf4b479000a178a83db14cfa38a1eb185c8f09ac01d727ce6f79afe39ce5e45686ca70
7
- data.tar.gz: 3e241e4d17f7b5d889e665e5cb17e5d66de1ca7fdd3b3cbd4e73615421561f735aa3d3f40176b27c1be32cfc9e1db7059d642662ad35fc786fc45620b8a8146f
6
+ metadata.gz: 6c4d55dda6fe90872b8a31799207acfe4a910734f20e26cd870103d4ddee2dac6f7f756474f2982e944337ec06502b507622a95c89d400df64aae763554b04c7
7
+ data.tar.gz: f3fc56af09b5da30a0bde842ff0cc66d448089a638bce6203485ce9f48fe35014b21c05cb1d1f06fc179f49077c58f365837e2f5ab15534d0781a0f4f297c4d8
@@ -29,8 +29,6 @@ jobs:
29
29
  matrix:
30
30
  ruby-version: ["3.3", "3.4", "4.0"]
31
31
  active-record:
32
- - label: AR 7.2
33
- env: ACTIVE_RECORD_VERSION=~> 7.2.0
34
32
  - label: AR 8.0
35
33
  env: ACTIVE_RECORD_VERSION=~> 8.0.0
36
34
  - label: AR 8.1
@@ -52,11 +50,6 @@ jobs:
52
50
  label: AR 8-0-stable
53
51
  env: ACTIVE_RECORD_BRANCH=8-0-stable
54
52
  allow-failure: true
55
- - ruby-version: "4.0"
56
- active-record:
57
- label: AR 7-2-stable
58
- env: ACTIVE_RECORD_BRANCH=7-2-stable
59
- allow-failure: true
60
53
  # A canary for the next Ruby, which cannot fail the build.
61
54
  - ruby-version: ruby-head
62
55
  active-record:
@@ -78,11 +71,6 @@ jobs:
78
71
  ruby-version: ${{ matrix.ruby-version }}
79
72
  bundler-cache: true
80
73
  cache-version: ${{ matrix.active-record.env }}
81
- # Gemfile.lock is not checked in, so this resolves the newest gems that
82
- # satisfy the Gemfile on each run rather than a recorded set. `--all` is
83
- # what Bundler 4, shipped with Ruby 4.0, wants for that.
84
- - name: Update bundle
85
- run: bundle update --all
86
74
  # Not bin/rake: bin/ holds generated binstubs and is not checked in, and
87
75
  # whether bundling writes them there varies by Bundler version - Bundler 4
88
76
  # does not, which left Ruby 4.0 with no binstub to run.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  ### Unreleased
2
2
 
3
+ ### 2.5.0
4
+
5
+ - Allow `table(false)` for an abstract model, and for a model whose superclass
6
+ is `ActiveRecord::Base` or abstract when the model has an existing table: the
7
+ one its model block names with `self.table_name`, or else the one Active
8
+ Record names after the model. Its rows are left for the suite to clean up.
9
+
10
+ ### 2.4.0
11
+
12
+ - Add Test::Unit support, including lifecycle integration for dynamic models and
13
+ tables.
14
+ - Add `with_model/rspec`, `with_model/minitest`, and `with_model/test_unit`
15
+ convenience entrypoints.
16
+ - Add runner integration guides for RSpec, Minitest, and Test::Unit.
17
+ - Skip temporary-table teardown when the table has already disappeared.
18
+ - Require Active Record 8.0 or later.
19
+
3
20
  ### 2.3.1
4
21
 
5
22
  - Honor Active Record destruction callbacks and dependent associations when
data/CONTRIBUTING.md CHANGED
@@ -24,12 +24,22 @@ avoid anything that only works on the newest of either.
24
24
 
25
25
  ## Running the tests
26
26
 
27
- The suite runs against both supported test harnesses, so `with_model` has to work
28
- under each:
27
+ The suite runs against all three supported test harnesses, so `with_model` has
28
+ to work under each:
29
29
 
30
30
  - `spec/` covers behavior under RSpec.
31
- - `test/` covers the minitest life cycle — the setup and teardown hooks, and
31
+ - `test/` covers the Minitest life cycle — the setup and teardown hooks, and
32
32
  their ordering — rather than repeating the specs.
33
+ - `test_unit/` covers Test::Unit integration in a dedicated process, including
34
+ native fixture callback ordering.
35
+
36
+ Run one harness with its scoped Rake task:
37
+
38
+ ```sh
39
+ bundle exec rake spec
40
+ bundle exec rake test
41
+ bundle exec rake test_unit
42
+ ```
33
43
 
34
44
  Run everything, including the linter, with:
35
45
 
@@ -37,6 +47,13 @@ Run everything, including the linter, with:
37
47
  bundle exec rake
38
48
  ```
39
49
 
50
+ Validate the README and runner guides with RDoc before submitting documentation
51
+ changes:
52
+
53
+ ```sh
54
+ rm -rf tmp/rdoc && bundle exec rdoc --markup markdown --op tmp/rdoc README.md docs/rspec.md docs/minitest.md docs/test-unit.md lib/**/*.rb
55
+ ```
56
+
40
57
  `bin/` holds generated binstubs and is not checked in. Whether bundling writes
41
58
  them for you depends on your Bundler version, so create them once if you would
42
59
  rather type `bin/rake`:
@@ -75,9 +92,27 @@ bundle exec standardrb --fix
75
92
 
76
93
  ## Changes and releases
77
94
 
78
- Please add a line to `CHANGELOG.md` under `### Unreleased` describing your change
79
- from the point of view of someone using the gem. Leave `lib/with_model/version.rb`
80
- alone: version bumps and releases are cut separately by a maintainer, so a bump
81
- in a pull request only creates a conflict.
95
+ Please add an entry to `CHANGELOG.md` under `### Unreleased` for each change
96
+ someone using the gem would notice. Leave `lib/with_model/version.rb` alone:
97
+ version bumps and releases are cut separately by a maintainer, so a bump in a
98
+ pull request only creates a conflict.
99
+
100
+ ### Changelog format
101
+
102
+ - Each release has a `### X.Y.Z` heading, newest first, with unreleased changes
103
+ under `### Unreleased` at the top. Leave a blank line after each heading.
104
+ - Write one bullet per change, from the point of view of someone using the gem:
105
+ what they can now do or what behaves differently, not how the code changed.
106
+ - Start with a verb in the imperative mood (Add, Allow, Fix, Deprecate, Remove,
107
+ Require), and write a full sentence ending in a period.
108
+ - Put code, such as method names, options, and constants, in backticks.
109
+ - Wrap lines at 80 columns, indenting continuation lines by two spaces.
110
+ - List dependency changes last, Active Record before Ruby, with added support
111
+ before a raised minimum: "Add support for Ruby 4.0." then "Require Ruby 3.3
112
+ or later."
113
+ - Don't cite issue or pull request numbers. The pull request links the issue.
114
+ - Credit contributors from outside the maintainers by name, in parentheses at
115
+ the end of the entry, as in "Create table in same database as `superclass`
116
+ (John Doe)."
82
117
 
83
118
  Last, but not least, have fun.
data/Gemfile CHANGED
@@ -24,3 +24,4 @@ gem "rspec"
24
24
  gem "ruby-lsp"
25
25
  gem "sqlite3"
26
26
  gem "standard"
27
+ gem "test-unit"
data/README.md CHANGED
@@ -14,32 +14,63 @@
14
14
 
15
15
  Install as usual: `gem install with_model` or add `gem 'with_model'` to your Gemfile. See [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) for supported (tested) Ruby versions.
16
16
 
17
+ ## Test runner setup
18
+
19
+ Choose the entrypoint for the test runner that owns the declarations. Each
20
+ performs complete global setup for one runner; see its guide for lifecycle and
21
+ manual-setup details.
22
+
17
23
  ### RSpec
18
24
 
19
- Extend `WithModel` into RSpec:
25
+ ```ruby
26
+ require "with_model/rspec"
27
+ ```
28
+
29
+ See the [RSpec guide](docs/rspec.md).
30
+
31
+ ### Minitest
20
32
 
21
33
  ```ruby
22
- require "with_model"
34
+ require "with_model/minitest"
35
+ ```
23
36
 
24
- RSpec.configure do |config|
25
- config.extend WithModel
26
- end
37
+ See the [Minitest guide](docs/minitest.md).
38
+
39
+ ### Test::Unit
40
+
41
+ ```ruby
42
+ require "with_model/test_unit"
27
43
  ```
28
44
 
29
- ### minitest/spec
45
+ See the [Test::Unit guide](docs/test-unit.md).
30
46
 
31
- Extend `WithModel` into minitest/spec and set the test runner explicitly:
47
+ ### Advanced and mixed-runner setup
48
+
49
+ Plain `require "with_model"` remains framework-neutral. For manual setup,
50
+ select a runner and extend its test context directly:
32
51
 
33
52
  ```ruby
53
+ require "minitest"
34
54
  require "with_model"
35
55
 
36
56
  WithModel.runner = :minitest
57
+ Minitest::Test.extend WithModel
58
+ ```
59
+
60
+ RSpec uses `RSpec.configure { |config| config.extend WithModel }`; Test::Unit
61
+ uses `Test::Unit::TestCase.extend WithModel`. A declaration can override the
62
+ global runner when needed:
37
63
 
38
- class Minitest::Spec
39
- extend WithModel
64
+ ```ruby
65
+ with_model :Post, runner: :test_unit do
66
+ table
40
67
  end
41
68
  ```
42
69
 
70
+ Loading multiple convenience entrypoints in one process is unsupported because
71
+ the last one changes the global runner. For mixed runners, use plain
72
+ `with_model`, direct extension, and explicit `runner:` options.
73
+
43
74
  ## Usage
44
75
 
45
76
  After setting up as above, call `with_model` and inside its block pass it a `table` block and a `model` block.
@@ -206,8 +237,9 @@ end
206
237
  A `superclass:` that cannot be used raises `WithModel::InvalidSuperclass`: one
207
238
  that is not an Active Record class, one with no table of its own
208
239
  (`ActiveRecord::Base`, or an abstract class such as a Rails app's
209
- `ApplicationRecord`), or one whose table has no inheritance column to tell a
210
- subclass's rows apart. A name that resolves to nothing raises
240
+ `ApplicationRecord`) when the model has no existing table of its own either (see
241
+ [Existing tables](#existing-tables)), or a concrete one whose table has no
242
+ inheritance column to tell a subclass's rows apart. A name that resolves to nothing raises
211
243
  `WithModel::MissingSuperclass`, a kind of `InvalidSuperclass`, quoting the
212
244
  constant Ruby could not find — for a namespaced name, that is the segment which
213
245
  is actually missing. Both are `ArgumentError`s.
@@ -218,6 +250,64 @@ enough on its own. Rows the model wrote are deleted when it goes away, since the
218
250
  name a class that is about to stop existing and would make the superclass
219
251
  unloadable.
220
252
 
253
+ ### Existing tables
254
+
255
+ `table(false)` also suits a model that maps to a table the suite already has,
256
+ such as a legacy table or one that several models share. Set `self.table_name`
257
+ in the model block, or leave it out to use the table Active Record names after
258
+ the model (`phoenixes` for `Phoenix`):
259
+
260
+ ```ruby
261
+ describe "with_model supports existing tables" do
262
+ with_table :legendary_creatures do |t|
263
+ t.string "name"
264
+ end
265
+
266
+ with_model :Phoenix do
267
+ table(false)
268
+
269
+ model do
270
+ self.table_name = "legendary_creatures"
271
+ end
272
+ end
273
+
274
+ it "uses the table it names" do
275
+ Phoenix.create!(name: "Fawkes")
276
+
277
+ expect(Phoenix.table_name).to eq "legendary_creatures"
278
+ end
279
+ end
280
+ ```
281
+
282
+ The table must exist before the model is set up, so declare `with_table` (or
283
+ whatever creates it) first. It belongs to the suite, not the model, so its rows
284
+ are left in place when the model goes away. Clean them up as you would the rest of that table, with
285
+ transactional tests or otherwise.
286
+
287
+ The superclass can be abstract, as a Rails app's `ApplicationRecord` is. An
288
+ abstract model needs no table, so declare it with `table(false)` as well:
289
+
290
+ ```ruby
291
+ with_model :LegendaryCreature do
292
+ table(false)
293
+
294
+ model do
295
+ self.abstract_class = true
296
+ end
297
+ end
298
+
299
+ with_model :Phoenix, superclass: :LegendaryCreature do
300
+ table(false)
301
+
302
+ model do
303
+ self.table_name = "legendary_creatures"
304
+ end
305
+ end
306
+ ```
307
+
308
+ Active Record never applies single table inheritance below an abstract class, so
309
+ an abstract superclass's table, if it has one, needs no inheritance column.
310
+
221
311
  ## Foreign keys
222
312
 
223
313
  `foreign_key: true` asks Active Record to infer the table a foreign key points
@@ -252,7 +342,13 @@ the order they are declared, and destroyed in the reverse order.
252
342
 
253
343
  ## Requirements
254
344
 
255
- See the [gemspec metadata](https://rubygems.org/gems/with_model) for dependency requirements. RSpec and minitest are indirect dependencies, and `with_model` should support any maintained version of both.
345
+ See the [gemspec metadata](https://rubygems.org/gems/with_model) for Ruby and
346
+ Active Record requirements. RSpec, Minitest, and Test::Unit are optional
347
+ consumer framework dependencies; install the framework used by its selected
348
+ entrypoint. Requiring a selected entrypoint without its framework installed
349
+ raises the framework's ordinary `LoadError`.
350
+
351
+ `scope:` is RSpec-only and is silently ignored by Minitest and Test::Unit.
256
352
 
257
353
  ## Thread-safety
258
354
 
data/Rakefile CHANGED
@@ -8,7 +8,13 @@ RSpec::Core::RakeTask.new
8
8
  require "minitest/test_task"
9
9
  Minitest::TestTask.create
10
10
 
11
+ require "rake/testtask"
12
+ Rake::TestTask.new(:test_unit) do |task|
13
+ task.libs << "lib" << "test_unit" << "test"
14
+ task.pattern = "test_unit/**/*_test.rb"
15
+ end
16
+
11
17
  # standard rake task
12
18
  require "standard/rake"
13
19
 
14
- task default: %i[spec test standard]
20
+ task default: %i[spec test test_unit standard]
data/docs/minitest.md ADDED
@@ -0,0 +1,45 @@
1
+ # Minitest integration
2
+
3
+ Load the Minitest entrypoint before defining tests:
4
+
5
+ ```ruby
6
+ require "with_model/minitest"
7
+ ```
8
+
9
+ This requires `minitest`, then `with_model`, selects the
10
+ `:minitest` runner, and extends `Minitest::Test`. Its class-level DSL is
11
+ inherited by `Minitest::Test` subclasses, including `Minitest::Spec` and
12
+ `ActiveSupport::TestCase`. The entrypoint does not require or start Minitest's
13
+ autorun — your process or test framework owns Minitest startup.
14
+
15
+ ## Lifecycle
16
+
17
+ The Minitest runner creates declared models and tables in `before_setup` and
18
+ destroys them in `after_teardown`. This makes them available to ordinary setup
19
+ methods and keeps them available through teardown. `scope:` is silently ignored
20
+ by Minitest because it is an RSpec-only option.
21
+
22
+ ## Manual setup
23
+
24
+ If another process or tool owns Minitest configuration, configure manually:
25
+
26
+ ```ruby
27
+ require "minitest"
28
+ require "with_model"
29
+
30
+ WithModel.runner = :minitest
31
+ Minitest::Test.extend WithModel
32
+ ```
33
+
34
+ Minitest is an optional consumer dependency. Requiring `with_model/minitest`
35
+ without Minitest installed raises Minitest's ordinary `LoadError`.
36
+
37
+ ## Mixed runners
38
+
39
+ Do not load multiple convenience entrypoints in one process: each changes the
40
+ global runner, and the last one wins. For mixed runners, load plain
41
+ `with_model`, extend each framework boundary directly, and select a runner per
42
+ declaration with `runner:`.
43
+
44
+ See the [general DSL reference](../README.md#usage) for declaring models and
45
+ tables.
data/docs/rspec.md ADDED
@@ -0,0 +1,43 @@
1
+ # RSpec integration
2
+
3
+ Load the RSpec entrypoint before defining example groups:
4
+
5
+ ```ruby
6
+ require "with_model/rspec"
7
+ ```
8
+
9
+ The entrypoint requires `rspec/core` and `with_model`, selects the `:rspec`
10
+ runner, and extends RSpec example groups through `RSpec.configure`. It does not
11
+ start RSpec; the RSpec command-line runner remains in control.
12
+
13
+ ## Lifecycle
14
+
15
+ `with_model` and `with_table` register RSpec `before` and `after` hooks. Models
16
+ and tables are available to examples after setup and are removed after cleanup.
17
+ Use `scope:` when RSpec hook scope is needed, including `scope: :all` for a
18
+ model needed by `before(:all)`. `scope:` is an RSpec-only option.
19
+
20
+ ## Manual setup
21
+
22
+ For runner-owned setup, require the framework and `with_model` separately:
23
+
24
+ ```ruby
25
+ require "rspec/core"
26
+ require "with_model"
27
+
28
+ WithModel.runner = :rspec
29
+ RSpec.configure { |config| config.extend WithModel }
30
+ ```
31
+
32
+ RSpec is an optional consumer dependency. Requiring `with_model/rspec` without
33
+ RSpec installed raises RSpec's ordinary `LoadError`.
34
+
35
+ ## Mixed runners
36
+
37
+ Do not load multiple convenience entrypoints in one process: each changes the
38
+ global runner, and the last one wins. For mixed runners, load plain
39
+ `with_model`, extend each framework boundary directly, and select a runner per
40
+ declaration with `runner:`.
41
+
42
+ See the [general DSL reference](../README.md#usage) for declaring models and
43
+ tables.
data/docs/test-unit.md ADDED
@@ -0,0 +1,73 @@
1
+ # Test::Unit integration
2
+
3
+ Load the Test::Unit entrypoint before defining tests:
4
+
5
+ ```ruby
6
+ require "with_model/test_unit"
7
+ ```
8
+
9
+ The entrypoint requires `test/unit`, then `with_model`, selects the
10
+ `:test_unit` runner, and extends `Test::Unit::TestCase`. Test::Unit retains
11
+ ownership of autorun and fixture execution.
12
+
13
+ ## Lifecycle
14
+
15
+ `with_model` and `with_table` register Test::Unit fixture callbacks with exact
16
+ placement: setup uses `before: :append`, while teardown uses `after: :prepend`.
17
+ Declared models and tables therefore create in declaration order before user or
18
+ inherited setup methods and callbacks. They destroy in reverse order after user
19
+ or inherited teardown methods and callbacks.
20
+
21
+ Test::Unit runs teardown when setup raises. `WithModel::Model#destroy`
22
+ defensively handles creation that never assigned a model. `Table#destroy` checks
23
+ whether its table exists before dropping it, so teardown does not raise solely
24
+ because a reconnect replaced an in-memory database or the table otherwise
25
+ already disappeared. It does not rescue other database, connection, or drop
26
+ errors; those still propagate. This conditional drop check does not promise
27
+ generic partial-creation recovery for bare `with_table`. `scope:` is silently
28
+ ignored by Test::Unit because it is an RSpec-only option.
29
+
30
+ ## Errata and concerns
31
+
32
+ Establish the Active Record connection before `with_model`'s setup callback
33
+ creates tables and models. An ordinary `def setup` runs too late. Connect in
34
+ your test helper before test classes load, or register a connection callback
35
+ with `setup(before: :prepend)`.
36
+
37
+ ```ruby
38
+ class PostTest < Test::Unit::TestCase
39
+ setup(before: :prepend) do
40
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
41
+ end
42
+
43
+ with_model :Post do
44
+ table
45
+ end
46
+ end
47
+ ```
48
+
49
+ ## Manual setup
50
+
51
+ For runner-owned setup, require Test::Unit and `with_model` separately:
52
+
53
+ ```ruby
54
+ require "test/unit"
55
+ require "with_model"
56
+
57
+ WithModel.runner = :test_unit
58
+ Test::Unit::TestCase.extend WithModel
59
+ ```
60
+
61
+ Test::Unit is an optional consumer dependency. Requiring
62
+ `with_model/test_unit` without Test::Unit installed raises Test::Unit's ordinary
63
+ `LoadError`.
64
+
65
+ ## Mixed runners
66
+
67
+ Do not load multiple convenience entrypoints in one process: each changes the
68
+ global runner, and the last one wins. For mixed runners, load plain
69
+ `with_model`, extend each framework boundary directly, and select a runner per
70
+ declaration with `runner:`.
71
+
72
+ See the [general DSL reference](../README.md#usage) for declaring models and
73
+ tables.
@@ -74,14 +74,6 @@ module WithModel
74
74
  end
75
75
  end
76
76
 
77
- class ActiveRecord::Base
78
- extend WithModel::DescendantsTracker::DestroyedClassesFiltering
79
- end
80
-
81
- module ActiveSupport
82
- module DescendantsTracker
83
- class << self
84
- attr_reader :clear_disabled
85
- end
86
- end
87
- end
77
+ ActiveRecord::Base.singleton_class.prepend(
78
+ WithModel::DescendantsTracker::DestroyedClassesFiltering
79
+ )
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "minitest"
4
+ require "with_model"
5
+
6
+ WithModel.runner = :minitest
7
+ Minitest::Test.extend WithModel
@@ -13,7 +13,9 @@ module WithModel
13
13
  #
14
14
  # Pass `false` instead of options to create no table at all, so that the
15
15
  # model inherits its superclass's table as Rails Single Table Inheritance
16
- # requires. `table(false)` takes no block.
16
+ # requires, or uses an existing table: the one its model block names with
17
+ # `self.table_name`, or else the one Active Record names after the model.
18
+ # An abstract model needs no table at all. `table(false)` takes no block.
17
19
  #
18
20
  # @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table
19
21
  def table(options = {}, &block)
@@ -73,11 +73,7 @@ module WithModel
73
73
  # Before `unstub_const`: a teardown that identifies this model's own rows
74
74
  # can only do so while the class still has its name.
75
75
  table.teardown(@model)
76
- stubber.unstub_const
77
- cleanup_descendants_tracking
78
- reset_dependencies_cache
79
- WithModel::DescendantsTracker.clear([@model])
80
- @model = nil
76
+ discard_model
81
77
  end
82
78
 
83
79
  private
@@ -129,18 +125,24 @@ module WithModel
129
125
  def setup_model
130
126
  table.configure(@model)
131
127
  @model.class_eval(&@model_block) if @model_block
128
+ verify_model
132
129
  @model.reset_column_information
133
130
  end
134
131
 
135
- def cleanup_descendants_tracking
136
- ActiveSupport::DescendantsTracker.clear([@model]) \
137
- unless ActiveSupport::DescendantsTracker.clear_disabled
132
+ # A model rejected here was never usable, so it is discarded at once rather
133
+ # than left for teardown: there are no rows to clean up, and a caller that
134
+ # does not tear down would otherwise be left with its constant.
135
+ def verify_model
136
+ table.verify(@model)
137
+ rescue InvalidSuperclass
138
+ discard_model
139
+ raise
138
140
  end
139
141
 
140
- def reset_dependencies_cache
141
- return unless defined?(ActiveSupport::Dependencies::Reference)
142
-
143
- ActiveSupport::Dependencies::Reference.clear!
142
+ def discard_model
143
+ stubber.unstub_const
144
+ WithModel::DescendantsTracker.clear([@model])
145
+ @model = nil
144
146
  end
145
147
 
146
148
  def stubber