transient_record 1.0.0 → 2.0.0.rc1
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 +4 -4
- data/README.md +35 -18
- data/lib/transient_record.rb +147 -108
- metadata +19 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5307d695a68a4250343b0cb8866055f626153fcebde0f0bf69213ef791c777e1
|
4
|
+
data.tar.gz: 8b0185a7d93b93c179ccf69dc8cc497a4012f9dca66e1bf3d90decddf2375963
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43af400d4dccdfeebd0d5a01c7d7631fb2e43b00453b76fafd7e2e0f2f41bea66b0aa4abdbf057a3139d7dd06d903e5f54ba90c02994f7e44b9449a205729013
|
7
|
+
data.tar.gz: 3c84c3764e9b8c65c1703062b6f1e4ce4a60d89823f6472a9d20ac7b6157073bb3b8082304597f01617c87e084ca361fd5407546b3d9ddecd0796d8120a8d5ad
|
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,18 +119,18 @@ 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
|
115
|
-
|
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
136
|
class TransientRecord::Models::User < ActiveRecord::Base
|
@@ -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.
|
133
|
-
free to report any errors and contribute updates.
|
150
|
+
result in an error.
|
134
151
|
|
135
152
|
## Author
|
136
153
|
|
data/lib/transient_record.rb
CHANGED
@@ -2,80 +2,127 @@
|
|
2
2
|
|
3
3
|
# Transient Record helps define transient tables and Active Record models.
|
4
4
|
#
|
5
|
-
#
|
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
|
-
#
|
8
|
-
#
|
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
|
-
#
|
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
|
-
# #
|
27
|
-
#
|
28
|
-
#
|
47
|
+
# # Instantiate the model
|
48
|
+
# user = Primary::User.new email: nil
|
49
|
+
#
|
50
|
+
# # Clean up when done.
|
51
|
+
# TransientRecord.cleanup
|
29
52
|
#
|
30
|
-
# @example
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
53
|
+
# @example Defining a model for a pre-existing table
|
54
|
+
# Primary = TransientRecord.context_for ActiveRecord::Base
|
55
|
+
#
|
56
|
+
# Primary.define_model :User do
|
34
57
|
# validates :email, presence: true
|
35
58
|
# end
|
36
|
-
|
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 = "
|
75
|
+
VERSION = "2.0.0.rc1"
|
39
76
|
|
40
|
-
# A
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# TransientRecord.create_table :users do |t|
|
50
|
-
# t.string :email, null: false
|
51
|
-
# end.define_model do
|
52
|
-
# validates :email, presence: true
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# # ... the user model can be referenced via:
|
56
|
-
# TransientRecord::Models::User
|
57
|
-
module Models
|
58
|
-
# Remove all constants from the module.
|
77
|
+
# A class representing Transient Record errors.
|
78
|
+
class Error < RuntimeError; end
|
79
|
+
|
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.
|
59
86
|
#
|
60
|
-
#
|
61
|
-
#
|
87
|
+
# Active Record sets up connection pools for abstract Active Record model
|
88
|
+
# classes.
|
62
89
|
#
|
63
|
-
# @
|
64
|
-
|
65
|
-
|
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
|
66
95
|
end
|
67
|
-
end
|
68
96
|
|
69
|
-
|
70
|
-
|
97
|
+
def cleanup
|
98
|
+
@contexts.each_value(&:cleanup)
|
99
|
+
nil
|
100
|
+
end
|
71
101
|
end
|
72
102
|
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
76
124
|
|
77
|
-
|
78
|
-
# Create a transient table.
|
125
|
+
# Creates a transient table.
|
79
126
|
#
|
80
127
|
# This method can be considered to be a wrapper around +#create_table+ in
|
81
128
|
# Active Record, as it forwards its arguments and the block.
|
@@ -87,130 +134,122 @@ module TransientRecord
|
|
87
134
|
# +temporary: true+ via options, which Active Record will recognized out of
|
88
135
|
# the box.
|
89
136
|
#
|
90
|
-
# Transient tables must be dropped explicitly by calling {.cleanup}
|
137
|
+
# Transient tables must be dropped explicitly by calling {.cleanup} or
|
138
|
+
# {#cleanup}.
|
91
139
|
#
|
92
140
|
# @param table_name [String, Symbol] name of the table to create.
|
93
141
|
# @param options [Hash] options to use during table creation; they are
|
94
142
|
# forwarded as is to +create_table+ in Active Record.
|
95
143
|
#
|
96
|
-
# @yield [table] table definition forwarded to +create_table+ in
|
97
|
-
# Record.
|
144
|
+
# @yield [table] table definition block forwarded to +create_table+ in
|
145
|
+
# Active Record.
|
98
146
|
#
|
99
147
|
# @return [ModelDefinitionProxy]
|
100
148
|
#
|
101
149
|
# @see https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table Documentation for #create_table in Ruby on Rails
|
102
150
|
def create_table table_name, options = {}, &block
|
103
151
|
table_name = table_name.to_sym
|
152
|
+
@transient_tables << table_name
|
104
153
|
|
105
|
-
|
106
|
-
::ActiveRecord::Migration.create_table table_name, **options, &block
|
107
|
-
end
|
154
|
+
@base_class.connection.create_table table_name, **options, &block
|
108
155
|
|
109
|
-
|
110
|
-
# right after creating a table so that it can be followed by the model
|
111
|
-
# definition.
|
112
|
-
ModelDefinitionProxy.new table_name
|
156
|
+
ModelDefinitionProxy.new self, table_name
|
113
157
|
end
|
114
158
|
|
115
|
-
#
|
159
|
+
# Defines a transient Active Record model.
|
116
160
|
#
|
117
161
|
# Calling this method is roughly equivalent to defining a class inheriting
|
118
|
-
# from
|
119
|
-
# the method.
|
162
|
+
# from the class the context corresponds to and with class body defined by
|
163
|
+
# the block passed to the method.
|
120
164
|
#
|
121
|
-
# Transient models must be removed explicitly by calling {.cleanup}
|
165
|
+
# Transient models must be removed explicitly by calling {.cleanup} or
|
166
|
+
# {#cleanup}.
|
122
167
|
#
|
123
168
|
# @example
|
169
|
+
# Primary = TransientRecord.context_for ApplicationRecord
|
170
|
+
#
|
124
171
|
# # The following method call ...
|
125
|
-
#
|
172
|
+
# Primary.define_model(:User) do
|
126
173
|
# validates :email, presence: true
|
127
174
|
# end
|
128
175
|
#
|
129
176
|
# # ... is roughly equivalent to this class definition.
|
130
|
-
# class
|
177
|
+
# class Primary::User < ApplicationRecord
|
131
178
|
# validates :email, presence: true
|
132
179
|
# end
|
133
180
|
#
|
134
181
|
#
|
135
182
|
# @param model_name [String, Symbol] name of model to define.
|
136
|
-
# @param base_class [Class] model base class.
|
137
183
|
#
|
138
|
-
# @yield
|
184
|
+
# @yield class definition
|
139
185
|
#
|
140
186
|
# @return [nil]
|
141
|
-
def define_model model_name,
|
142
|
-
|
143
|
-
|
144
|
-
# Normally, when a class is defined via `class MyClass < MySuperclass` the
|
145
|
-
# .name class method returns the name of the class when called from within
|
146
|
-
# the class body. However, anonymous classes defined via Class.new DO NOT
|
147
|
-
# HAVE NAMES. They're assigned names when they're assigned to a constant.
|
148
|
-
# If we evaluated the class body, passed via block here, in the class
|
149
|
-
# definition below then some Active Record macros would break
|
150
|
-
# (e.g. has_and_belongs_to_many) due to nil name.
|
151
|
-
#
|
152
|
-
# We solve the problem by defining an empty model class first, assigning to
|
153
|
-
# a constant to ensure a name is assigned, and then reopening the class to
|
154
|
-
# give it a non-trivial body.
|
155
|
-
klass = Class.new base_class
|
156
|
-
Models.const_set model_name, klass
|
187
|
+
def define_model model_name, &block
|
188
|
+
klass = Class.new @base_class
|
189
|
+
const_set model_name, klass
|
157
190
|
|
158
191
|
klass.class_eval(&block) if block_given?
|
159
192
|
|
160
193
|
nil
|
161
194
|
end
|
162
195
|
|
163
|
-
#
|
196
|
+
# Drops transient tables and models.
|
164
197
|
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
198
|
+
# Calling this method removes all models and drops all tables created within
|
199
|
+
# this context. Instead of calling this method, you usually should
|
200
|
+
# {.cleanup} to cleanup **all** contexts.
|
168
201
|
#
|
169
|
-
#
|
170
|
-
# 2. Drop all tables created via {.create_table}.
|
171
|
-
# 3. Start garbage collection.
|
202
|
+
# Calling this method does the following:
|
172
203
|
#
|
173
|
-
#
|
174
|
-
#
|
204
|
+
# 1. Remove all models defined via {#define_model}.
|
205
|
+
# 2. Drop all tables created via {#create_table}.
|
206
|
+
# 3. Run garbage collection to ensure model classes are truly removed. This
|
207
|
+
# may be needed in some versions of Active Record.
|
175
208
|
#
|
176
209
|
# @return [nil]
|
177
210
|
def cleanup
|
178
|
-
|
211
|
+
constants.each { |name| remove_const name }
|
179
212
|
|
180
|
-
|
181
|
-
tables_to_remove = connection.tables
|
213
|
+
tables_to_remove = @transient_tables
|
182
214
|
drop_attempts = tables_to_remove.count * (1 + tables_to_remove.count) / 2
|
183
215
|
|
184
216
|
drop_attempts.times do
|
185
|
-
table = tables_to_remove.
|
217
|
+
table = tables_to_remove.pop
|
186
218
|
break if table.nil?
|
187
219
|
|
188
220
|
begin
|
189
|
-
connection.drop_table table, force: :cascade, if_exists: true
|
221
|
+
@base_class.connection.drop_table table, force: :cascade, if_exists: true
|
190
222
|
rescue ActiveRecord::InvalidForeignKey, ActiveRecord::StatementInvalid
|
191
223
|
# ActiveRecord::StatementInvalid is raised by MySQL when attempting to
|
192
224
|
# drop a table that has foreign keys referring to it.
|
193
|
-
tables_to_remove
|
225
|
+
tables_to_remove.unshift(table)
|
194
226
|
end
|
195
227
|
end
|
196
228
|
|
229
|
+
if !@transient_tables.empty?
|
230
|
+
raise Error.new(<<~ERROR)
|
231
|
+
The following transient tables could not be removed: #{@transient_tables.join(', ')}.
|
232
|
+
ERROR
|
233
|
+
end
|
234
|
+
|
197
235
|
GC.start
|
198
236
|
|
199
237
|
nil
|
200
238
|
end
|
201
239
|
end
|
202
240
|
|
203
|
-
# A model definition proxy is a helper class
|
204
|
-
# interface
|
241
|
+
# A model definition proxy is a helper class implementing a fluent
|
242
|
+
# interface allowing callers to create a table and its corresponding
|
205
243
|
# model in close succession. It's marked private as there's no need for
|
206
|
-
# callers to access it.
|
244
|
+
# callers to access it directly.
|
207
245
|
class ModelDefinitionProxy
|
208
|
-
def initialize table_name
|
209
|
-
@
|
246
|
+
def initialize context, table_name
|
247
|
+
@context = context
|
248
|
+
@table_name = table_name
|
210
249
|
end
|
211
250
|
|
212
251
|
def define_model &block
|
213
|
-
|
252
|
+
@context.define_model @table_name.to_s.classify, &block
|
214
253
|
end
|
215
254
|
end
|
216
255
|
|
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:
|
4
|
+
version: 2.0.0.rc1
|
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-
|
11
|
+
date: 2023-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -28,98 +28,98 @@ 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
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: 1.43.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.43.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rubocop-rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: 0.6.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 0.6.0
|
125
125
|
description:
|
@@ -148,11 +148,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
148
148
|
version: 2.4.0
|
149
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
150
|
requirements:
|
151
|
-
- - "
|
151
|
+
- - ">"
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version:
|
153
|
+
version: 1.3.1
|
154
154
|
requirements: []
|
155
|
-
rubygems_version: 3.
|
155
|
+
rubygems_version: 3.4.10
|
156
156
|
signing_key:
|
157
157
|
specification_version: 4
|
158
158
|
summary: Define transient tables and Active Record models for testing purposes.
|