transient_record 1.0.1 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -19
  3. data/lib/transient_record.rb +148 -111
  4. metadata +33 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62717fcb04dc95460008a291475193ad256735122cef3502311ac02d62326baf
4
- data.tar.gz: c0d9ac5cd578b60eb9e6e5774886d5e16737eb773766f999b9c201d5a923471c
3
+ metadata.gz: cf204f3cad36d8d1e2f81a174b617293491fd05a05c0db723ba65fc8bf2dbb9e
4
+ data.tar.gz: b9beca98152782d6946e531418497d68e1cf94f590e7437ffcc3e98d3cefb3b6
5
5
  SHA512:
6
- metadata.gz: fb93249d31a827da8ef2a652e9ebe96435d93468bd392d4a228b2200ae03fef6673c0b4995970927f5aa049b4f11d16d096b23fe8f8312749fb8562f45872083
7
- data.tar.gz: 36c7bf8748bee4035084b33be89871bb1eeee83f7a75d02a16f52e769bc09587d145318df1279a2932d399ce76245b76f8d9995314d41ba8cbd2a8b9218827a2
6
+ metadata.gz: 37c95fe8e6f9ed85a0d64ae11f17e66d241dbcb728574215315b545085cbeba1d37097554cf6bf178b047cce9864aff07cc0681dfec8249363dcbd2f71e7bfed
7
+ data.tar.gz: 9eced5b248a14742aca7ae9f06b08df15962eb36ee023112b7e63755c7533a186165e8293d90e0fba19aac3ebcb23854483d99a14b46befb5912054b85077c18
data/README.md CHANGED
@@ -16,22 +16,19 @@ Installing Transient Record is a two-step process.
16
16
  You can include Transient Record in your `Gemfile`:
17
17
 
18
18
  ```ruby
19
+ # Add the following to use the most recent release:
19
20
  gem "transient_record", group: :test
21
+
22
+ # Alternatively, you can use the most recent development version:
23
+ gem "transient_record", github: "gregnavis/transient_record", group: :test
20
24
  ```
21
25
 
26
+ Don't forget to run `bundle install`.
27
+
22
28
  The above assumes it'll be used for testing purposes only, hence the `test`
23
29
  group. However, if you intend to use the gem in other circumstances then you may
24
30
  need to adjust the group accordingly.
25
31
 
26
- If you'd like to use the latest development release then use the line below
27
- instead:
28
-
29
- ```ruby
30
- gem "transient_record", github: "gregnavis/transient_record", group: :test
31
- ```
32
-
33
- After modifying `Gemfile`, run `bundle install`.
34
-
35
32
  ### Step 2: Integrating with the Test Suite
36
33
 
37
34
  After installing the gem, Transient Record must be integrated with the test
@@ -39,6 +36,9 @@ suite. `TransientRecord.cleanup` must be called around every test case: before
39
36
  (to prepare a clean database state for the test case) and after (to leave the
40
37
  database in a clean state).
41
38
 
39
+ **Transient Record is not prepared to work with parallel test suites, so ensure
40
+ tests that use it run sequentially.**
41
+
42
42
  The snippet below demonstrates integrations with various testing libraries:
43
43
 
44
44
  ```ruby
@@ -79,7 +79,24 @@ end
79
79
  ## Usage
80
80
 
81
81
  Transient Record can be used to create temporary tables and, optionally, models
82
- backed by them.
82
+ backed by them. First, you need to define a Transient Record **context**.
83
+
84
+ A context is a module associated to a specific Active Record base class (like
85
+ `ActiveRecord::Base` or `ApplicationRecord`) that's used to connect to the
86
+ database and as a base class for transient models. Contexts are needed to
87
+ support multiple databases, as Active Record organizes database connections
88
+ around base classes. Consult [the Rails Guides](https://guides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application) to learn more
89
+ about using Active Record with multiple databases.
90
+
91
+ **If you connect to only one database then you need just one context for
92
+ `ActiveRecord::Base`**.
93
+
94
+ A context is a Ruby module used to define transient tables and models. Here's
95
+ how a context for `ActiveRecord::Base` can be defined:
96
+
97
+ ```ruby
98
+ Primary = TransientRecord.context_for ActiveRecord::Base
99
+ ```
83
100
 
84
101
  A table can be created by calling `create_table`: a thin wrapper around the
85
102
  method of the same name in Active Record. The only difference is the method
@@ -87,10 +104,11 @@ in Transient Record implemented a fluent interface that allows calling
87
104
  `define_model` on the return value.
88
105
 
89
106
  For example, the statement below creates a table named `users` with two one
90
- string column `name` and one integer column `age`:
107
+ string column `name` and one integer column `age` using the `Primary` context
108
+ introduced above:
91
109
 
92
110
  ```ruby
93
- create_table :users do |t|
111
+ Primary.create_table :users do |t|
94
112
  t.string :name, null: false
95
113
  t.integer :age, null: false
96
114
  end
@@ -101,21 +119,21 @@ for details.
101
119
 
102
120
  In order to define a model backed by that table `define_model` can be called
103
121
  **on the return value** of `create_table` with a block containing the model
104
- class body. For example, to define
122
+ class body. For example, to define
105
123
 
106
124
  ```ruby
107
- create_table :users do |t|
125
+ Primary.create_table :users do |t|
108
126
  # ...
109
127
  end.define_model do
110
128
  validates :email, presence: true
111
129
  end
112
130
  ```
113
131
 
114
- Models are automatically assigned to constants in `TransientRecord::Models`. The
115
- example above creates `TransientRecord::Models::User`, and is equivalent to:
132
+ Models are automatically assigned to constants. In the example above, the user
133
+ model is assigned to `Primary::User` via code roughly equivalent to:
116
134
 
117
135
  ```ruby
118
- class TransientRecord::Models::User < ActiveRecord::Base
136
+ class Primary::User < ActiveRecord::Base
119
137
  validates :email, presence: true
120
138
  end
121
139
  ```
@@ -129,8 +147,7 @@ reason it was decided to use regular tables with an explicit cleanup step.
129
147
 
130
148
  Transient Record may not work properly in parallelized test suites, e.g. if two
131
149
  test workers attempt to create a table with the same name then it's likely to
132
- result in an error. Full support for parallelism **is** on the roadmap, so feel
133
- free to report any errors and contribute updates.
150
+ result in an error.
134
151
 
135
152
  ## Author
136
153
 
@@ -2,87 +2,127 @@
2
2
 
3
3
  # Transient Record helps define transient tables and Active Record models.
4
4
  #
5
- # Defining a transient table and model is a two-step process:
5
+ # It's essential to understand Transient Record Contexts in order to use the
6
+ # library effectively. Let's start the discussion with how Active Record handles
7
+ # connections.
6
8
  #
7
- # 1. {#create_table} to create the table.
8
- # 2. {#define_model} to define the model.
9
+ # Active Record organizes connection pools around classes. Connecting to
10
+ # multiple databases requires defining multiple abstract classes. For example:
11
+ #
12
+ # class ApplicationRecord < ActiveRecord::Base
13
+ # end
14
+ #
15
+ # class AnalyticsRecord < ApplicationRecord
16
+ # self.abstract_class = true
17
+ #
18
+ # connects_to database: { writing: :analytics }
19
+ # end
20
+ #
21
+ # In this case, +ApplicationRecord.connection+ returns a connection to the
22
+ # primary database and +AnalyticsRecord.connection+ returns a connection to the
23
+ # other database.
24
+ #
25
+ # A context is related to an Active Record base class that's used to access the
26
+ # database directly and to define transient models. After defining an Active
27
+ # Record base class, a context can be created by calling {.context_for} and
28
+ # **must** be assigned to a constant.
29
+ #
30
+ # After the context is created, you can create tables and models by calling
31
+ # {Context#create_table} and {Context#define_model}. When you're done, call
32
+ # {.cleanup} to drop all transient tables and models
33
+ #
34
+ # @example Creating a table and a model
35
+ # # Define the context for classes using ActiveRecord::Base to connect. It's
36
+ # # a constant defined outside of the test suite.
37
+ # Primary = TransientRecord.context_for ActiveRecord::Base
9
38
  #
10
- # @example Creating a table without a model
11
39
  # # #create_table is a wrapper around #create_table in Active Record, and
12
40
  # # works almost exactly like the that method.
13
- # TransientRecord.create_table :users do |t|
14
- # t.string :email, null: false
15
- # end
16
- #
17
- # @example Creating a table and a model using fluent interface
18
- # # The difference between #create_table and its Active Record counterpart is
19
- # # the return value: Transient Record allows calling #define_model on it.
20
- # TransientRecord.create_table :users do |t|
41
+ # Primary.create_table :users do |t|
21
42
  # t.string :email, null: false
22
43
  # end.define_model do
23
44
  # validates :email, presence: true
24
45
  # end
25
46
  #
26
- # # The transient model can be referenced via TransientRecord::Models::User.
27
- # # For example, a new user instance can be instantiated via:
28
- # user = TransientRecord::Models::User.new email: nil
47
+ # # Instantiate the model
48
+ # user = Primary::User.new email: nil
49
+ #
50
+ # # Clean up when done.
51
+ # TransientRecord.cleanup
52
+ #
53
+ # @example Defining a model for a pre-existing table
54
+ # Primary = TransientRecord.context_for ActiveRecord::Base
29
55
  #
30
- # @example Creating a table and a model with regular interface
31
- # # Assuming the users table has been created (using Transient Record or
32
- # # another method), a User model can be defined via:
33
- # TransientRecord.define_model :User do
56
+ # Primary.define_model :User do
34
57
  # validates :email, presence: true
35
58
  # end
36
- module TransientRecord
59
+ #
60
+ # user = Primary::User.new email: nil
61
+ #
62
+ # @example Creating a table and a model in another database
63
+ # #
64
+ # Analytics = TransientRecord.context_for AnalyticsRecord
65
+ #
66
+ # Analytics.create_table :events do |t|
67
+ # # ...
68
+ # end.define_model do
69
+ # # ...
70
+ # end
71
+ #
72
+ # event = Analytics::Event.new
73
+ class TransientRecord
37
74
  # Transient Record version number.
38
- VERSION = "1.0.1"
75
+ VERSION = "2.0.0.rc2"
39
76
 
40
77
  # A class representing Transient Record errors.
41
78
  class Error < RuntimeError; end
42
79
 
43
- # A module where all temporary models are defined.
44
- #
45
- # Models defined via {TransientRecord.define_model}, {TransientRecord#define_model}
46
- # or {ModelDefinitionProxy#define_model} are put here in order to avoid
47
- # polluting the top-level namespace, potentially conflicting with identically
48
- # named constants defined elsewhere.
49
- #
50
- # @example
51
- # # If a transient users table and its corresponding User model are defined then ...
52
- # TransientRecord.create_table :users do |t|
53
- # t.string :email, null: false
54
- # end.define_model do
55
- # validates :email, presence: true
56
- # end
57
- #
58
- # # ... the user model can be referenced via:
59
- # TransientRecord::Models::User
60
- module Models
61
- # Remove all constants from the module.
80
+ # A mapping of Active Record base classes to TransientRecord::Contexts.
81
+ @contexts = {}
82
+
83
+ class << self
84
+ # Creates a namespace for tables and models corresponding to the given base
85
+ # class.
62
86
  #
63
- # This method is used by {TransientRecord.cleanup} to undefine temporary
64
- # model classes.
87
+ # Active Record sets up connection pools for abstract Active Record model
88
+ # classes.
65
89
  #
66
- # @api private
67
- def self.remove_all_consts
68
- constants.each { |name| remove_const name }
90
+ # @param base_class [Class] class inheriting from {::ActiveRecord::Base}
91
+ # @return [Module] module where transient models will be defined; the module
92
+ # extends {Context}, so it's instance methods can be called on the module.
93
+ def context_for base_class
94
+ @contexts[base_class] ||= Context.create base_class
69
95
  end
70
- end
71
-
72
- def create_table *args, &block
73
- TransientRecord.create_table(*args, &block)
74
- end
75
96
 
76
- def define_model *args, &block
77
- TransientRecord.define_model(*args, &block)
97
+ def cleanup
98
+ @contexts.each_value(&:cleanup)
99
+ nil
100
+ end
78
101
  end
79
102
 
80
- # Transient table names are stored in a module instance variable, so that
81
- # only transient tables can be removed in .cleanup.
82
- @transient_tables = []
103
+ # A module for creating Transient Record contexts.
104
+ #
105
+ # A context is a Ruby module (created via +Module.new+) and extended with
106
+ # {Context}. This means instance methods below should be called as module
107
+ # methods on a context, **not** as instance methods.
108
+ module Context
109
+ # Creates a context corresponding to the specified base class.
110
+ #
111
+ # @param base_class [Class] Active Record class to use to connect to the
112
+ # database and as a base class for models.
113
+ #
114
+ # @return [Module] context module used as a namespace for models
115
+ #
116
+ # @api private
117
+ def self.create base_class
118
+ Module.new do
119
+ extend Context
120
+ @base_class = base_class
121
+ @transient_tables = []
122
+ end
123
+ end
83
124
 
84
- class << self
85
- # Create a transient table.
125
+ # Creates a transient table.
86
126
  #
87
127
  # This method can be considered to be a wrapper around +#create_table+ in
88
128
  # Active Record, as it forwards its arguments and the block.
@@ -94,14 +134,15 @@ module TransientRecord
94
134
  # +temporary: true+ via options, which Active Record will recognized out of
95
135
  # the box.
96
136
  #
97
- # Transient tables must be dropped explicitly by calling {.cleanup}.
137
+ # Transient tables must be dropped explicitly by calling {.cleanup} or
138
+ # {#cleanup}.
98
139
  #
99
140
  # @param table_name [String, Symbol] name of the table to create.
100
141
  # @param options [Hash] options to use during table creation; they are
101
142
  # forwarded as is to +create_table+ in Active Record.
102
143
  #
103
- # @yield [table] table definition forwarded to +create_table+ in Active
104
- # Record.
144
+ # @yield [table] table definition block forwarded to +create_table+ in
145
+ # Active Record.
105
146
  #
106
147
  # @return [ModelDefinitionProxy]
107
148
  #
@@ -110,95 +151,90 @@ module TransientRecord
110
151
  table_name = table_name.to_sym
111
152
  @transient_tables << table_name
112
153
 
113
- ::ActiveRecord::Migration.suppress_messages do
114
- ::ActiveRecord::Migration.create_table table_name, **options, &block
115
- end
154
+ @base_class.connection.create_table table_name, **options, &block
116
155
 
117
- # Return a proxy object allowing the caller to chain #define_model
118
- # right after creating a table so that it can be followed by the model
119
- # definition.
120
- ModelDefinitionProxy.new table_name
156
+ ModelDefinitionProxy.new self, table_name
121
157
  end
122
158
 
123
- # Define a transient Active Record model.
159
+ # Defines a transient Active Record model.
124
160
  #
125
161
  # Calling this method is roughly equivalent to defining a class inheriting
126
- # from +ActiveRecord::Base+ with class body defined by the block passed to
127
- # the method.
162
+ # from the class the context corresponds to and with class body defined by
163
+ # the block passed to the method.
164
+ #
165
+ # The base class can be customized by passing in a second argument, but it
166
+ # **must** be a subclass of the context's base class.
128
167
  #
129
- # Transient models must be removed explicitly by calling {.cleanup}.
168
+ # Transient models must be removed explicitly by calling {.cleanup} or
169
+ # {#cleanup}.
130
170
  #
131
171
  # @example
172
+ # Primary = TransientRecord.context_for ApplicationRecord
173
+ #
132
174
  # # The following method call ...
133
- # TransientRecord.define_model(:User) do
175
+ # Primary.define_model(:User) do
134
176
  # validates :email, presence: true
135
177
  # end
136
178
  #
137
179
  # # ... is roughly equivalent to this class definition.
138
- # class TransientRecord::Models::User < ActiveRecord::Base
180
+ # class Primary::User < ApplicationRecord
139
181
  # validates :email, presence: true
140
182
  # end
141
183
  #
142
184
  #
143
185
  # @param model_name [String, Symbol] name of model to define.
144
- # @param base_class [Class] model base class.
186
+ # @param base_class [Class] base class the model should inherit from
145
187
  #
146
- # @yield expects the class body to be passed via the block
188
+ # @yield class definition
147
189
  #
148
190
  # @return [nil]
149
- def define_model model_name, base_class = ::ActiveRecord::Base, &block
150
- model_name = model_name.to_sym
151
-
152
- # Normally, when a class is defined via `class MyClass < MySuperclass` the
153
- # .name class method returns the name of the class when called from within
154
- # the class body. However, anonymous classes defined via Class.new DO NOT
155
- # HAVE NAMES. They're assigned names when they're assigned to a constant.
156
- # If we evaluated the class body, passed via block here, in the class
157
- # definition below then some Active Record macros would break
158
- # (e.g. has_and_belongs_to_many) due to nil name.
159
- #
160
- # We solve the problem by defining an empty model class first, assigning to
161
- # a constant to ensure a name is assigned, and then reopening the class to
162
- # give it a non-trivial body.
191
+ def define_model model_name, base_class = nil, &block
192
+ base_class ||= @base_class
193
+
194
+ if base_class > @base_class
195
+ raise Error.new(<<~ERROR)
196
+ #{model_name} base class is #{base_class.name} but it must be a descendant of #{@base_class.name}
197
+ ERROR
198
+ end
199
+
163
200
  klass = Class.new base_class
164
- Models.const_set model_name, klass
201
+ const_set model_name, klass
165
202
 
166
203
  klass.class_eval(&block) if block_given?
167
204
 
168
205
  nil
169
206
  end
170
207
 
171
- # Drop transient tables and models.
208
+ # Drops transient tables and models.
172
209
  #
173
- # This method **MUST** be called after every test cases that used Transient
174
- # Record, as it's responsible for ensuring a clean slate for the next run.
175
- # It does the following:
210
+ # Calling this method removes all models and drops all tables created within
211
+ # this context. Instead of calling this method, you usually should
212
+ # {.cleanup} to cleanup **all** contexts.
176
213
  #
177
- # 1. Remove all models defined via {.define_model}.
178
- # 2. Drop all tables created via {.create_table}.
179
- # 3. Start garbage collection.
214
+ # Calling this method does the following:
180
215
  #
181
- # The last step is to ensure model classes are actually removed, and won't
182
- # appear among the descendants hierarchy of +ActiveRecord::Base+.
216
+ # 1. Remove all models defined via {#define_model}.
217
+ # 2. Drop all tables created via {#create_table}.
218
+ # 3. Run garbage collection to ensure model classes are truly removed. This
219
+ # may be needed in some versions of Active Record.
183
220
  #
184
221
  # @return [nil]
185
222
  def cleanup
186
- Models.remove_all_consts
223
+ constants.each { |name| remove_const name }
187
224
 
188
- connection = ::ActiveRecord::Base.connection
189
225
  tables_to_remove = @transient_tables
190
226
  drop_attempts = tables_to_remove.count * (1 + tables_to_remove.count) / 2
191
227
 
192
228
  drop_attempts.times do
193
- table = tables_to_remove.shift
229
+ table = tables_to_remove.pop
194
230
  break if table.nil?
195
231
 
196
232
  begin
197
- connection.drop_table table, force: :cascade, if_exists: true
233
+ @base_class.connection.drop_table table, force: :cascade, if_exists: true
198
234
  rescue ActiveRecord::InvalidForeignKey, ActiveRecord::StatementInvalid
199
235
  # ActiveRecord::StatementInvalid is raised by MySQL when attempting to
200
236
  # drop a table that has foreign keys referring to it.
201
- tables_to_remove << table
237
+ tables_to_remove.unshift(table)
202
238
  end
203
239
  end
204
240
 
@@ -214,17 +250,18 @@ module TransientRecord
214
250
  end
215
251
  end
216
252
 
217
- # A model definition proxy is a helper class used to implement a fluent
218
- # interface to callers allowing them to create a table and its corresponding
253
+ # A model definition proxy is a helper class implementing a fluent
254
+ # interface allowing callers to create a table and its corresponding
219
255
  # model in close succession. It's marked private as there's no need for
220
- # callers to access it.
256
+ # callers to access it directly.
221
257
  class ModelDefinitionProxy
222
- def initialize table_name
223
- @table_name = table_name.to_s
258
+ def initialize context, table_name
259
+ @context = context
260
+ @table_name = table_name
224
261
  end
225
262
 
226
- def define_model &block
227
- TransientRecord.define_model @table_name.classify, &block
263
+ def define_model *args, &block
264
+ @context.define_model @table_name.to_s.classify, *args, &block
228
265
  end
229
266
  end
230
267
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transient_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Navis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-25 00:00:00.000000000 Z
11
+ date: 2023-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -28,98 +28,112 @@ dependencies:
28
28
  name: mysql2
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.5.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.5.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pg
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 1.1.4
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.1.4
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: sqlite3
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: 1.5.4
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.5.4
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: 12.3.3
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: 12.3.3
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: yard
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.9.28
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.9.28
97
+ - !ruby/object:Gem::Dependency
98
+ name: webrick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.8.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.8.1
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rubocop
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - "~>"
115
+ - - ">="
102
116
  - !ruby/object:Gem::Version
103
117
  version: 1.43.0
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - "~>"
122
+ - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: 1.43.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rubocop-rake
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
- - - "~>"
129
+ - - ">="
116
130
  - !ruby/object:Gem::Version
117
131
  version: 0.6.0
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - "~>"
136
+ - - ">="
123
137
  - !ruby/object:Gem::Version
124
138
  version: 0.6.0
125
139
  description:
@@ -148,11 +162,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
162
  version: 2.4.0
149
163
  required_rubygems_version: !ruby/object:Gem::Requirement
150
164
  requirements:
151
- - - ">="
165
+ - - ">"
152
166
  - !ruby/object:Gem::Version
153
- version: '0'
167
+ version: 1.3.1
154
168
  requirements: []
155
- rubygems_version: 3.2.33
169
+ rubygems_version: 3.4.10
156
170
  signing_key:
157
171
  specification_version: 4
158
172
  summary: Define transient tables and Active Record models for testing purposes.