praxis 2.0.pre.35 → 2.0.pre.36
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +10 -0
- data/lib/praxis/docs/open_api/schema_object.rb +5 -0
- data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +47 -6
- data/lib/praxis/version.rb +1 -1
- data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +121 -70
- metadata +2 -4
- data/gemfiles/active_6.gemfile.lock +0 -205
- data/gemfiles/active_7.gemfile.lock +0 -203
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 832a3ffb62fa691ed10139478a2cc262978c8a4c382baf9392357d1b78548164
|
4
|
+
data.tar.gz: 85a4bf51dac77883338be30112725f380483db6b7cad121d193652095e886ab9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78a6a4546a9abdc6764d72c04d4419a1895b51399f9d77789f7dd6a4e1c86983d210deabf5744e072ebf98a807c20d3fc26129f2384c85e061745263d3bc4c15
|
7
|
+
data.tar.gz: df6d66dbef7f356ee7adfa23211f8bcf6c8df4d67f1f158c410824d403fb354d7b472af707411f4b2e672a8a4356163c3e55978fb559b4f18f4b14cf971340ce
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
# Praxis Changelog
|
2
2
|
|
3
3
|
## next
|
4
|
+
- OpenAPI generation enhancement:
|
5
|
+
- expose nullable: true, in situations where the 'null:' key isn't specified in an attribute, but the builtin default behavior is true
|
6
|
+
- Change ActiveRecord query planner strategy for selecting fields in the root model when that model is also appearing in inner joins/associations (triggered by a new AR7 behavior)
|
7
|
+
- Until now, our AR planner would only select the necessary fields for the top level model of the query, and would simply select * for any inner associations (as that's what AR allows)
|
8
|
+
- AR7 has change its behavior (in our mind, a bug) where if there are inner associations that point to the same model type of the root query ... instead of loading and creating new instances of those, it now simply points to already
|
9
|
+
existing instances in memory that might have previously been loaded for the same id. This can certainly reduce the amount of memory and DB round trips if there's a lot of overlap, however, this change does not have in mind that
|
10
|
+
the already loaded model might not actually have all fields, therefore if we're loading an inner association of a model, where we expect to use any of its fields...but that inner model, instead of being loaded with "SELECT *", simply
|
11
|
+
points to a loaded model with the same 'id' ... then we're at the mercy of whatever fields that initial model was loaded with.
|
12
|
+
The current solution we've adopted, is to make our query planner smarter, and make sure that we use a top level model select clause that includes ALL of possible fields for that model, regardless of how deep the inner associations might be.
|
13
|
+
This can technically add more loaded fields at the top (i.e., some memory bloat), but if that's the case, it is very likely that such extra bloat on field memory is compensated by the fact that any of the inner associations using the same model type will now likely not have to be loaded and instantiated. It really depends on the pattern of the query and the cardinality of such associations
|
4
14
|
|
5
15
|
## 2.0.pre.35
|
6
16
|
- Fix reported nullability property in OpenAPI generation. Looking at null: true | false isn't enough. The system needs to look at the default null behavior from Attributor, to properly ascertain if the exclusion of a 'null' option means nullable or not. This PR fixes this.
|
@@ -40,6 +40,11 @@ module Praxis
|
|
40
40
|
if base_options.key?(:null)
|
41
41
|
base_options[:nullable] = Attributor::Attribute::nullable_attribute?(base_options)
|
42
42
|
base_options.delete(:null)
|
43
|
+
else
|
44
|
+
# Even though no :null option is passed in, still see if the default is 'nullable', and if so, pass it in.
|
45
|
+
# This is to handle the case where a type is defined as nullable by default, but the user didn't explicitly
|
46
|
+
# pass in the null: true option
|
47
|
+
base_options[:nullable] = true if Attributor::Attribute.default_for_null
|
43
48
|
end
|
44
49
|
|
45
50
|
# We will dump schemas for mediatypes by simply creating a reference to the components' section
|
@@ -29,21 +29,62 @@ module Praxis
|
|
29
29
|
# We're gonna always require the PK of the model, as it is a special case for AR, and the app itself
|
30
30
|
# might assume it is always there and not be surprised by the fact that if it isn't, it won't blow up
|
31
31
|
# in the same way as any other attribute not being loaded...i.e., ActiveModel::MissingAttributeError: missing attribute: xyz
|
32
|
-
select_fields =
|
32
|
+
select_fields =
|
33
|
+
_hoist_select(
|
34
|
+
selector_node: selector_node,
|
35
|
+
fields_closure:
|
36
|
+
Set.new([selector_node.resource.model.primary_key.to_sym]),
|
37
|
+
).to_a
|
33
38
|
select_fields.empty? ? query : query.select(*select_fields)
|
34
39
|
end
|
35
40
|
|
41
|
+
def explain_query(query, eager_hash)
|
42
|
+
@logger.debug(
|
43
|
+
"Query plan for ...#{selector.resource.model} with selectors: #{JSON.generate(selector.dump)}",
|
44
|
+
)
|
45
|
+
@logger.debug(
|
46
|
+
" ActiveRecord query: #{selector.resource.model}.includes(#{eager_hash})",
|
47
|
+
)
|
48
|
+
query.explain
|
49
|
+
@logger.debug('Query plan end')
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
36
54
|
def _eager(selector_node)
|
37
55
|
selector_node.tracks.transform_values do |track_node|
|
38
56
|
_eager(track_node)
|
39
57
|
end
|
40
58
|
end
|
41
59
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
60
|
+
# This deals with a performance optimization introduced in ActiveRecord 7
|
61
|
+
# When preloading associations, they now reuse model instances that have already
|
62
|
+
# been loaded as part of the same chain of queries.
|
63
|
+
#
|
64
|
+
# If the root uses a `select` constraint, then some attributes may not be loaded
|
65
|
+
# if the record is reused elsewhere in the resulting graph of models. In former
|
66
|
+
# versions of ActiveRecord, a `SELECT *` would have been used to instantiate these
|
67
|
+
# nested versions of the model and so all attributes would have been loaded.
|
68
|
+
#
|
69
|
+
# To account for this discrepancy, we hoist all transitive columns of the root
|
70
|
+
# model up to the root of the query tree, preserving the optimization benefit
|
71
|
+
# of a narrow field selector while ensuring that all requested fields are
|
72
|
+
# available at every node in the model graph.
|
73
|
+
#
|
74
|
+
# @return [Set<Symbol]
|
75
|
+
def _hoist_select(root_node: nil, selector_node:, fields_closure:)
|
76
|
+
root_node ||= selector_node
|
77
|
+
if root_node.resource == selector_node.resource
|
78
|
+
fields_closure.merge(selector_node.select)
|
79
|
+
end
|
80
|
+
selector_node.tracks.values.each do |track_node|
|
81
|
+
_hoist_select(
|
82
|
+
root_node: root_node,
|
83
|
+
selector_node: track_node,
|
84
|
+
fields_closure: fields_closure,
|
85
|
+
)
|
86
|
+
end
|
87
|
+
fields_closure
|
47
88
|
end
|
48
89
|
end
|
49
90
|
end
|
data/lib/praxis/version.rb
CHANGED
@@ -8,101 +8,152 @@ describe Praxis::Extensions::FieldSelection::ActiveRecordQuerySelector do
|
|
8
8
|
name: true,
|
9
9
|
author: {
|
10
10
|
id: true,
|
11
|
-
books: true
|
11
|
+
books: true,
|
12
12
|
},
|
13
13
|
category: {
|
14
14
|
name: true,
|
15
|
-
books: true
|
15
|
+
books: true,
|
16
16
|
},
|
17
17
|
tags: {
|
18
|
-
name: true
|
19
|
-
}
|
18
|
+
name: true,
|
19
|
+
},
|
20
20
|
}
|
21
21
|
end
|
22
22
|
let(:expected_select_from_to_query) do
|
23
23
|
# The columns to select from the top Simple model
|
24
24
|
[
|
25
|
+
:id, # We always load the primary keys
|
25
26
|
:simple_name, # from the :name alias
|
26
27
|
:author_id, # the FK needed for the author association
|
27
28
|
:added_column, # from the extra column defined in the parent property
|
28
29
|
:category_uuid, # the FK needed for the cateory association
|
29
|
-
:id # We always load the primary keys
|
30
30
|
]
|
31
31
|
end
|
32
|
-
let(:selector_node)
|
32
|
+
let(:selector_node) do
|
33
|
+
Praxis::Mapper::SelectorGenerator
|
34
|
+
.new
|
35
|
+
.add(ActiveBookResource, selector_fields)
|
36
|
+
.selectors
|
37
|
+
end
|
33
38
|
let(:debug) { false }
|
34
39
|
|
35
|
-
subject(:selector)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
expect(
|
40
|
+
subject(:selector) do
|
41
|
+
described_class.new(query: query, selectors: selector_node, debug: debug)
|
42
|
+
end
|
43
|
+
|
44
|
+
context '#generate' do
|
45
|
+
context 'with a mock model' do
|
46
|
+
let(:query) { double('Query') }
|
47
|
+
it 'calls the select columns for the top level, and includes the right association hashes' do
|
48
|
+
expect(query).to receive(:select).with(
|
49
|
+
*expected_select_from_to_query,
|
50
|
+
).and_return(query)
|
51
|
+
expected_includes = {
|
52
|
+
author: {
|
53
|
+
books: {
|
54
|
+
},
|
55
|
+
},
|
56
|
+
category: {
|
57
|
+
books: {
|
58
|
+
},
|
59
|
+
},
|
60
|
+
tags: {
|
61
|
+
},
|
62
|
+
}
|
63
|
+
expect(query).to receive(:includes).with(expected_includes).and_return(
|
64
|
+
query,
|
65
|
+
)
|
66
|
+
expect(subject).to_not receive(:explain_query)
|
59
67
|
subject.generate
|
60
68
|
end
|
69
|
+
context 'when debug is enabled' do
|
70
|
+
let(:debug) { true }
|
71
|
+
it 'calls the explain method' do
|
72
|
+
expect(query).to receive(:select).and_return(query)
|
73
|
+
expect(query).to receive(:includes).and_return(query)
|
74
|
+
expect(subject).to receive(:explain_query)
|
75
|
+
subject.generate
|
76
|
+
end
|
77
|
+
end
|
61
78
|
end
|
62
|
-
end
|
63
79
|
|
64
|
-
|
65
|
-
|
80
|
+
context 'with a real AR model' do
|
81
|
+
let(:query) { ActiveBook }
|
66
82
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
83
|
+
it 'calls the select columns for the top level, and includes the right association hashes' do
|
84
|
+
expected_includes = {
|
85
|
+
author: {
|
86
|
+
books: {
|
87
|
+
},
|
88
|
+
},
|
89
|
+
category: {
|
90
|
+
books: {
|
91
|
+
},
|
92
|
+
},
|
93
|
+
tags: {
|
94
|
+
},
|
95
|
+
}
|
96
|
+
# expect(query).to receive(:includes).with(expected_includes).and_return(query)
|
97
|
+
expect(subject).to_not receive(:explain_query)
|
98
|
+
final_query = subject.generate
|
99
|
+
expect(final_query.select_values).to match_array(
|
100
|
+
expected_select_from_to_query,
|
101
|
+
)
|
102
|
+
# Our query selector always uses a single hash tree from the top, not an array of things
|
103
|
+
includes_hash = final_query.includes_values.first
|
104
|
+
expect(includes_hash).to match(expected_includes)
|
105
|
+
# Also, make AR do the actual query to make sure everything is wired up correctly
|
106
|
+
result = final_query.to_a
|
107
|
+
expect(result.size).to be > 2 # We are using 2 but we've seeded more
|
108
|
+
book1 = result[0]
|
109
|
+
book2 = result[1]
|
110
|
+
expect(book1.author.id).to eq 11
|
111
|
+
expect(book1.author.books.size).to eq 1
|
112
|
+
expect(book1.author.books.map(&:simple_name)).to eq(['Book1'])
|
113
|
+
expect(book1.category.name).to eq 'cat1'
|
114
|
+
expect(book1.tags.map(&:name)).to match_array(%w[blue red green])
|
94
115
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
116
|
+
expect(book2.author.id).to eq 22
|
117
|
+
expect(book2.author.books.size).to eq 1
|
118
|
+
expect(book2.author.books.map(&:simple_name)).to eq(['Book2'])
|
119
|
+
expect(book2.category.name).to eq 'cat2'
|
120
|
+
expect(book2.tags.map(&:name)).to match_array(['red'])
|
121
|
+
end
|
101
122
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
123
|
+
it 'calls the explain debug method if enabled' do
|
124
|
+
suppress_output do
|
125
|
+
# Actually make it run all the way...but suppressing the output
|
126
|
+
subject.generate
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'transitivity' do
|
131
|
+
let(:selector_fields) { { author: {} } }
|
132
|
+
|
133
|
+
let(:expected_select_from_to_query) do
|
134
|
+
# The columns to select from the top Simple model
|
135
|
+
[
|
136
|
+
:id, # We always load the primary keys
|
137
|
+
:author_id, # the FK needed for the author association
|
138
|
+
:added_column, # from the extra column defined in the parent property
|
139
|
+
]
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'includes the root columns' do
|
143
|
+
expect(subject.generate.select_values).to match_array(
|
144
|
+
expected_select_from_to_query,
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with references to the root model' do
|
149
|
+
let(:selector_fields) { { author: { books: { isbn: true } } } }
|
150
|
+
|
151
|
+
it 'hoists transitive columns to the root' do
|
152
|
+
expect(subject.generate.select_values).to match_array(
|
153
|
+
expected_select_from_to_query + [:isbn], # from the transitive author.books.isbn
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
106
157
|
end
|
107
158
|
end
|
108
159
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: praxis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.pre.
|
4
|
+
version: 2.0.pre.36
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josep M. Blanquer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-07-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -360,9 +360,7 @@ files:
|
|
360
360
|
- SELECTOR_NOTES.txt
|
361
361
|
- bin/praxis
|
362
362
|
- gemfiles/active_6.gemfile
|
363
|
-
- gemfiles/active_6.gemfile.lock
|
364
363
|
- gemfiles/active_7.gemfile
|
365
|
-
- gemfiles/active_7.gemfile.lock
|
366
364
|
- lib/praxis.rb
|
367
365
|
- lib/praxis/action_definition.rb
|
368
366
|
- lib/praxis/action_definition/headers_dsl_compiler.rb
|
@@ -1,205 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
praxis (2.0.pre.34)
|
5
|
-
activesupport (>= 3)
|
6
|
-
attributor (>= 7.1)
|
7
|
-
mime (~> 0)
|
8
|
-
mustermann (>= 1.1)
|
9
|
-
rack (>= 1)
|
10
|
-
terminal-table (~> 1.4)
|
11
|
-
thor
|
12
|
-
|
13
|
-
GEM
|
14
|
-
remote: https://rubygems.org/
|
15
|
-
specs:
|
16
|
-
activemodel (6.1.7.3)
|
17
|
-
activesupport (= 6.1.7.3)
|
18
|
-
activerecord (6.1.7.3)
|
19
|
-
activemodel (= 6.1.7.3)
|
20
|
-
activesupport (= 6.1.7.3)
|
21
|
-
activesupport (6.1.7.3)
|
22
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
23
|
-
i18n (>= 1.6, < 2)
|
24
|
-
minitest (>= 5.1)
|
25
|
-
tzinfo (~> 2.0)
|
26
|
-
zeitwerk (~> 2.3)
|
27
|
-
appraisal (2.4.1)
|
28
|
-
bundler
|
29
|
-
rake
|
30
|
-
thor (>= 0.14.0)
|
31
|
-
ast (2.4.2)
|
32
|
-
attributor (7.1)
|
33
|
-
activesupport (>= 3)
|
34
|
-
hashie (~> 3)
|
35
|
-
randexp (~> 0)
|
36
|
-
binding_of_caller (1.0.0)
|
37
|
-
debug_inspector (>= 0.0.1)
|
38
|
-
builder (3.2.4)
|
39
|
-
byebug (11.1.3)
|
40
|
-
coderay (1.1.3)
|
41
|
-
concurrent-ruby (1.2.2)
|
42
|
-
coveralls_reborn (0.27.0)
|
43
|
-
simplecov (~> 0.22.0)
|
44
|
-
term-ansicolor (~> 1.7)
|
45
|
-
thor (~> 1.2)
|
46
|
-
tins (~> 1.32)
|
47
|
-
debug_inspector (1.1.0)
|
48
|
-
diff-lcs (1.5.0)
|
49
|
-
docile (1.4.0)
|
50
|
-
ffi (1.15.5)
|
51
|
-
formatador (1.1.0)
|
52
|
-
fuubar (2.5.1)
|
53
|
-
rspec-core (~> 3.0)
|
54
|
-
ruby-progressbar (~> 1.4)
|
55
|
-
guard (2.18.0)
|
56
|
-
formatador (>= 0.2.4)
|
57
|
-
listen (>= 2.7, < 4.0)
|
58
|
-
lumberjack (>= 1.0.12, < 2.0)
|
59
|
-
nenv (~> 0.1)
|
60
|
-
notiffany (~> 0.0)
|
61
|
-
pry (>= 0.13.0)
|
62
|
-
shellany (~> 0.0)
|
63
|
-
thor (>= 0.18.1)
|
64
|
-
guard-bundler (2.2.1)
|
65
|
-
bundler (>= 1.3.0, < 3)
|
66
|
-
guard (~> 2.2)
|
67
|
-
guard-compat (~> 1.1)
|
68
|
-
guard-compat (1.2.1)
|
69
|
-
guard-rspec (4.7.3)
|
70
|
-
guard (~> 2.1)
|
71
|
-
guard-compat (~> 1.1)
|
72
|
-
rspec (>= 2.99.0, < 4.0)
|
73
|
-
hashie (3.6.0)
|
74
|
-
i18n (1.13.0)
|
75
|
-
concurrent-ruby (~> 1.0)
|
76
|
-
json (2.6.3)
|
77
|
-
link_header (0.0.8)
|
78
|
-
listen (3.8.0)
|
79
|
-
rb-fsevent (~> 0.10, >= 0.10.3)
|
80
|
-
rb-inotify (~> 0.9, >= 0.9.10)
|
81
|
-
lumberjack (1.2.8)
|
82
|
-
method_source (1.0.0)
|
83
|
-
mime (0.4.4)
|
84
|
-
mini_portile2 (2.8.2)
|
85
|
-
minitest (5.18.0)
|
86
|
-
mustermann (3.0.0)
|
87
|
-
ruby2_keywords (~> 0.0.1)
|
88
|
-
nenv (0.3.0)
|
89
|
-
notiffany (0.1.3)
|
90
|
-
nenv (~> 0.1)
|
91
|
-
shellany (~> 0.0)
|
92
|
-
oj (3.14.2)
|
93
|
-
parallel (1.23.0)
|
94
|
-
parser (3.2.2.1)
|
95
|
-
ast (~> 2.4.1)
|
96
|
-
parslet (2.0.0)
|
97
|
-
pry (0.14.2)
|
98
|
-
coderay (~> 1.1)
|
99
|
-
method_source (~> 1.0)
|
100
|
-
pry-byebug (3.10.1)
|
101
|
-
byebug (~> 11.0)
|
102
|
-
pry (>= 0.13, < 0.15)
|
103
|
-
pry-stack_explorer (0.6.1)
|
104
|
-
binding_of_caller (~> 1.0)
|
105
|
-
pry (~> 0.13)
|
106
|
-
rack (2.2.7)
|
107
|
-
rack-test (0.8.3)
|
108
|
-
rack (>= 1.0, < 3)
|
109
|
-
rainbow (3.1.1)
|
110
|
-
rake (13.0.6)
|
111
|
-
randexp (0.1.7)
|
112
|
-
rb-fsevent (0.11.2)
|
113
|
-
rb-inotify (0.10.1)
|
114
|
-
ffi (~> 1.0)
|
115
|
-
regexp_parser (2.8.0)
|
116
|
-
rexml (3.2.5)
|
117
|
-
rspec (3.12.0)
|
118
|
-
rspec-core (~> 3.12.0)
|
119
|
-
rspec-expectations (~> 3.12.0)
|
120
|
-
rspec-mocks (~> 3.12.0)
|
121
|
-
rspec-collection_matchers (1.2.0)
|
122
|
-
rspec-expectations (>= 2.99.0.beta1)
|
123
|
-
rspec-core (3.12.1)
|
124
|
-
rspec-support (~> 3.12.0)
|
125
|
-
rspec-expectations (3.12.2)
|
126
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
127
|
-
rspec-support (~> 3.12.0)
|
128
|
-
rspec-its (1.3.0)
|
129
|
-
rspec-core (>= 3.0.0)
|
130
|
-
rspec-expectations (>= 3.0.0)
|
131
|
-
rspec-mocks (3.12.3)
|
132
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
133
|
-
rspec-support (~> 3.12.0)
|
134
|
-
rspec-support (3.12.0)
|
135
|
-
rubocop (1.48.1)
|
136
|
-
json (~> 2.3)
|
137
|
-
parallel (~> 1.10)
|
138
|
-
parser (>= 3.2.0.0)
|
139
|
-
rainbow (>= 2.2.2, < 4.0)
|
140
|
-
regexp_parser (>= 1.8, < 3.0)
|
141
|
-
rexml (>= 3.2.5, < 4.0)
|
142
|
-
rubocop-ast (>= 1.26.0, < 2.0)
|
143
|
-
ruby-progressbar (~> 1.7)
|
144
|
-
unicode-display_width (>= 2.4.0, < 3.0)
|
145
|
-
rubocop-ast (1.28.0)
|
146
|
-
parser (>= 3.2.1.0)
|
147
|
-
ruby-progressbar (1.13.0)
|
148
|
-
ruby2_keywords (0.0.5)
|
149
|
-
sequel (5.55.0)
|
150
|
-
shellany (0.0.1)
|
151
|
-
simplecov (0.22.0)
|
152
|
-
docile (~> 1.1)
|
153
|
-
simplecov-html (~> 0.11)
|
154
|
-
simplecov_json_formatter (~> 0.1)
|
155
|
-
simplecov-html (0.12.3)
|
156
|
-
simplecov_json_formatter (0.1.4)
|
157
|
-
sqlite3 (1.6.1)
|
158
|
-
mini_portile2 (~> 2.8.0)
|
159
|
-
sqlite3 (1.6.1-x86_64-darwin)
|
160
|
-
sqlite3 (1.6.1-x86_64-linux)
|
161
|
-
sync (0.5.0)
|
162
|
-
term-ansicolor (1.7.1)
|
163
|
-
tins (~> 1.0)
|
164
|
-
terminal-table (1.6.0)
|
165
|
-
thor (1.2.2)
|
166
|
-
tins (1.32.1)
|
167
|
-
sync
|
168
|
-
tzinfo (2.0.6)
|
169
|
-
concurrent-ruby (~> 1.0)
|
170
|
-
unicode-display_width (2.4.2)
|
171
|
-
zeitwerk (2.6.8)
|
172
|
-
|
173
|
-
PLATFORMS
|
174
|
-
ruby
|
175
|
-
x86_64-darwin-20
|
176
|
-
x86_64-linux
|
177
|
-
|
178
|
-
DEPENDENCIES
|
179
|
-
activerecord (> 4, < 7)
|
180
|
-
appraisal
|
181
|
-
builder
|
182
|
-
bundler
|
183
|
-
coveralls_reborn (~> 0.27.0)
|
184
|
-
fuubar (~> 2)
|
185
|
-
guard (~> 2)
|
186
|
-
guard-bundler (~> 2)
|
187
|
-
guard-rspec (~> 4)
|
188
|
-
link_header
|
189
|
-
oj
|
190
|
-
parslet
|
191
|
-
praxis!
|
192
|
-
pry
|
193
|
-
pry-byebug
|
194
|
-
pry-stack_explorer
|
195
|
-
rack-test (~> 0)
|
196
|
-
rake (>= 12.3.3)
|
197
|
-
rspec (~> 3)
|
198
|
-
rspec-collection_matchers (~> 1)
|
199
|
-
rspec-its (~> 1)
|
200
|
-
rubocop
|
201
|
-
sequel (~> 5)
|
202
|
-
sqlite3 (~> 1)
|
203
|
-
|
204
|
-
BUNDLED WITH
|
205
|
-
2.4.12
|
@@ -1,203 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
praxis (2.0.pre.34)
|
5
|
-
activesupport (>= 3)
|
6
|
-
attributor (>= 7.1)
|
7
|
-
mime (~> 0)
|
8
|
-
mustermann (>= 1.1)
|
9
|
-
rack (>= 1)
|
10
|
-
terminal-table (~> 1.4)
|
11
|
-
thor
|
12
|
-
|
13
|
-
GEM
|
14
|
-
remote: https://rubygems.org/
|
15
|
-
specs:
|
16
|
-
activemodel (7.0.4.2)
|
17
|
-
activesupport (= 7.0.4.2)
|
18
|
-
activerecord (7.0.4.2)
|
19
|
-
activemodel (= 7.0.4.2)
|
20
|
-
activesupport (= 7.0.4.2)
|
21
|
-
activesupport (7.0.4.2)
|
22
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
23
|
-
i18n (>= 1.6, < 2)
|
24
|
-
minitest (>= 5.1)
|
25
|
-
tzinfo (~> 2.0)
|
26
|
-
appraisal (2.4.1)
|
27
|
-
bundler
|
28
|
-
rake
|
29
|
-
thor (>= 0.14.0)
|
30
|
-
ast (2.4.2)
|
31
|
-
attributor (7.1)
|
32
|
-
activesupport (>= 3)
|
33
|
-
hashie (~> 3)
|
34
|
-
randexp (~> 0)
|
35
|
-
binding_of_caller (1.0.0)
|
36
|
-
debug_inspector (>= 0.0.1)
|
37
|
-
builder (3.2.4)
|
38
|
-
byebug (11.1.3)
|
39
|
-
coderay (1.1.3)
|
40
|
-
concurrent-ruby (1.2.2)
|
41
|
-
coveralls_reborn (0.27.0)
|
42
|
-
simplecov (~> 0.22.0)
|
43
|
-
term-ansicolor (~> 1.7)
|
44
|
-
thor (~> 1.2)
|
45
|
-
tins (~> 1.32)
|
46
|
-
debug_inspector (1.1.0)
|
47
|
-
diff-lcs (1.5.0)
|
48
|
-
docile (1.4.0)
|
49
|
-
ffi (1.15.5)
|
50
|
-
formatador (1.1.0)
|
51
|
-
fuubar (2.5.1)
|
52
|
-
rspec-core (~> 3.0)
|
53
|
-
ruby-progressbar (~> 1.4)
|
54
|
-
guard (2.18.0)
|
55
|
-
formatador (>= 0.2.4)
|
56
|
-
listen (>= 2.7, < 4.0)
|
57
|
-
lumberjack (>= 1.0.12, < 2.0)
|
58
|
-
nenv (~> 0.1)
|
59
|
-
notiffany (~> 0.0)
|
60
|
-
pry (>= 0.13.0)
|
61
|
-
shellany (~> 0.0)
|
62
|
-
thor (>= 0.18.1)
|
63
|
-
guard-bundler (2.2.1)
|
64
|
-
bundler (>= 1.3.0, < 3)
|
65
|
-
guard (~> 2.2)
|
66
|
-
guard-compat (~> 1.1)
|
67
|
-
guard-compat (1.2.1)
|
68
|
-
guard-rspec (4.7.3)
|
69
|
-
guard (~> 2.1)
|
70
|
-
guard-compat (~> 1.1)
|
71
|
-
rspec (>= 2.99.0, < 4.0)
|
72
|
-
hashie (3.6.0)
|
73
|
-
i18n (1.13.0)
|
74
|
-
concurrent-ruby (~> 1.0)
|
75
|
-
json (2.6.3)
|
76
|
-
link_header (0.0.8)
|
77
|
-
listen (3.8.0)
|
78
|
-
rb-fsevent (~> 0.10, >= 0.10.3)
|
79
|
-
rb-inotify (~> 0.9, >= 0.9.10)
|
80
|
-
lumberjack (1.2.8)
|
81
|
-
method_source (1.0.0)
|
82
|
-
mime (0.4.4)
|
83
|
-
mini_portile2 (2.8.2)
|
84
|
-
minitest (5.18.0)
|
85
|
-
mustermann (3.0.0)
|
86
|
-
ruby2_keywords (~> 0.0.1)
|
87
|
-
nenv (0.3.0)
|
88
|
-
notiffany (0.1.3)
|
89
|
-
nenv (~> 0.1)
|
90
|
-
shellany (~> 0.0)
|
91
|
-
oj (3.14.2)
|
92
|
-
parallel (1.23.0)
|
93
|
-
parser (3.2.2.1)
|
94
|
-
ast (~> 2.4.1)
|
95
|
-
parslet (2.0.0)
|
96
|
-
pry (0.14.2)
|
97
|
-
coderay (~> 1.1)
|
98
|
-
method_source (~> 1.0)
|
99
|
-
pry-byebug (3.10.1)
|
100
|
-
byebug (~> 11.0)
|
101
|
-
pry (>= 0.13, < 0.15)
|
102
|
-
pry-stack_explorer (0.6.1)
|
103
|
-
binding_of_caller (~> 1.0)
|
104
|
-
pry (~> 0.13)
|
105
|
-
rack (2.2.7)
|
106
|
-
rack-test (0.8.3)
|
107
|
-
rack (>= 1.0, < 3)
|
108
|
-
rainbow (3.1.1)
|
109
|
-
rake (13.0.6)
|
110
|
-
randexp (0.1.7)
|
111
|
-
rb-fsevent (0.11.2)
|
112
|
-
rb-inotify (0.10.1)
|
113
|
-
ffi (~> 1.0)
|
114
|
-
regexp_parser (2.8.0)
|
115
|
-
rexml (3.2.5)
|
116
|
-
rspec (3.12.0)
|
117
|
-
rspec-core (~> 3.12.0)
|
118
|
-
rspec-expectations (~> 3.12.0)
|
119
|
-
rspec-mocks (~> 3.12.0)
|
120
|
-
rspec-collection_matchers (1.2.0)
|
121
|
-
rspec-expectations (>= 2.99.0.beta1)
|
122
|
-
rspec-core (3.12.1)
|
123
|
-
rspec-support (~> 3.12.0)
|
124
|
-
rspec-expectations (3.12.2)
|
125
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
126
|
-
rspec-support (~> 3.12.0)
|
127
|
-
rspec-its (1.3.0)
|
128
|
-
rspec-core (>= 3.0.0)
|
129
|
-
rspec-expectations (>= 3.0.0)
|
130
|
-
rspec-mocks (3.12.3)
|
131
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
132
|
-
rspec-support (~> 3.12.0)
|
133
|
-
rspec-support (3.12.0)
|
134
|
-
rubocop (1.48.1)
|
135
|
-
json (~> 2.3)
|
136
|
-
parallel (~> 1.10)
|
137
|
-
parser (>= 3.2.0.0)
|
138
|
-
rainbow (>= 2.2.2, < 4.0)
|
139
|
-
regexp_parser (>= 1.8, < 3.0)
|
140
|
-
rexml (>= 3.2.5, < 4.0)
|
141
|
-
rubocop-ast (>= 1.26.0, < 2.0)
|
142
|
-
ruby-progressbar (~> 1.7)
|
143
|
-
unicode-display_width (>= 2.4.0, < 3.0)
|
144
|
-
rubocop-ast (1.28.0)
|
145
|
-
parser (>= 3.2.1.0)
|
146
|
-
ruby-progressbar (1.13.0)
|
147
|
-
ruby2_keywords (0.0.5)
|
148
|
-
sequel (5.55.0)
|
149
|
-
shellany (0.0.1)
|
150
|
-
simplecov (0.22.0)
|
151
|
-
docile (~> 1.1)
|
152
|
-
simplecov-html (~> 0.11)
|
153
|
-
simplecov_json_formatter (~> 0.1)
|
154
|
-
simplecov-html (0.12.3)
|
155
|
-
simplecov_json_formatter (0.1.4)
|
156
|
-
sqlite3 (1.6.1)
|
157
|
-
mini_portile2 (~> 2.8.0)
|
158
|
-
sqlite3 (1.6.1-x86_64-darwin)
|
159
|
-
sqlite3 (1.6.1-x86_64-linux)
|
160
|
-
sync (0.5.0)
|
161
|
-
term-ansicolor (1.7.1)
|
162
|
-
tins (~> 1.0)
|
163
|
-
terminal-table (1.6.0)
|
164
|
-
thor (1.2.2)
|
165
|
-
tins (1.32.1)
|
166
|
-
sync
|
167
|
-
tzinfo (2.0.6)
|
168
|
-
concurrent-ruby (~> 1.0)
|
169
|
-
unicode-display_width (2.4.2)
|
170
|
-
|
171
|
-
PLATFORMS
|
172
|
-
ruby
|
173
|
-
x86_64-darwin-20
|
174
|
-
x86_64-linux
|
175
|
-
|
176
|
-
DEPENDENCIES
|
177
|
-
activerecord (>= 7)
|
178
|
-
appraisal
|
179
|
-
builder
|
180
|
-
bundler
|
181
|
-
coveralls_reborn (~> 0.27.0)
|
182
|
-
fuubar (~> 2)
|
183
|
-
guard (~> 2)
|
184
|
-
guard-bundler (~> 2)
|
185
|
-
guard-rspec (~> 4)
|
186
|
-
link_header
|
187
|
-
oj
|
188
|
-
parslet
|
189
|
-
praxis!
|
190
|
-
pry
|
191
|
-
pry-byebug
|
192
|
-
pry-stack_explorer
|
193
|
-
rack-test (~> 0)
|
194
|
-
rake (>= 12.3.3)
|
195
|
-
rspec (~> 3)
|
196
|
-
rspec-collection_matchers (~> 1)
|
197
|
-
rspec-its (~> 1)
|
198
|
-
rubocop
|
199
|
-
sequel (~> 5)
|
200
|
-
sqlite3 (~> 1)
|
201
|
-
|
202
|
-
BUNDLED WITH
|
203
|
-
2.4.12
|