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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44bb802f0b2f4372668de58fa4026c7b89ceaf6b24e59021efe0ac66add311c1
4
- data.tar.gz: ce0ad5cdaa52001ec451467e865e8fc3c53102984a2aec3256393a51683b668d
3
+ metadata.gz: 832a3ffb62fa691ed10139478a2cc262978c8a4c382baf9392357d1b78548164
4
+ data.tar.gz: 85a4bf51dac77883338be30112725f380483db6b7cad121d193652095e886ab9
5
5
  SHA512:
6
- metadata.gz: 8ba98db39d88023a2cf4b2573e83a87a018fa8e3c5959d757ca798f1b7d268b817cf8f2166ba3c04c1a60fc08804c025d31fb231ef2abea074bdadeccb74b6d0
7
- data.tar.gz: 496473875489e1276471c09e5307c75502318153ab5de9d4debe0f0261e78fe3036bde69681323fd44431b5b849cd57c95213b697eef4804defa6596e4022bf0
6
+ metadata.gz: 78a6a4546a9abdc6764d72c04d4419a1895b51399f9d77789f7dd6a4e1c86983d210deabf5744e072ebf98a807c20d3fc26129f2384c85e061745263d3bc4c15
7
+ data.tar.gz: df6d66dbef7f356ee7adfa23211f8bcf6c8df4d67f1f158c410824d403fb354d7b472af707411f4b2e672a8a4356163c3e55978fb559b4f18f4b14cf971340ce
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  coverage
2
2
  *.swp
3
+ *.gemfile.lock
3
4
  Gemfile.lock
4
5
  _site/
5
6
  .sass-cache/
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 = selector_node.select + [selector_node.resource.model.primary_key.to_sym]
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
- def explain_query(query, eager_hash)
43
- @logger.debug("Query plan for ...#{selector.resource.model} with selectors: #{JSON.generate(selector.dump)}")
44
- @logger.debug(" ActiveRecord query: #{selector.resource.model}.includes(#{eager_hash})")
45
- query.explain
46
- @logger.debug('Query plan end')
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Praxis
4
- VERSION = '2.0.pre.35'
4
+ VERSION = '2.0.pre.36'
5
5
  end
@@ -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) { Praxis::Mapper::SelectorGenerator.new.add(ActiveBookResource, selector_fields).selectors }
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) { described_class.new(query: query, selectors: selector_node, debug: debug) }
36
- context '#generate with a mocked' do
37
- let(:query) { double('Query') }
38
- it 'calls the select columns for the top level, and includes the right association hashes' do
39
- expect(query).to receive(:select).with(*expected_select_from_to_query).and_return(query)
40
- expected_includes = {
41
- author: {
42
- books: {}
43
- },
44
- category: {
45
- books: {}
46
- },
47
- tags: {}
48
- }
49
- expect(query).to receive(:includes).with(expected_includes).and_return(query)
50
- expect(subject).to_not receive(:explain_query)
51
- subject.generate
52
- end
53
- context 'when debug is enabled' do
54
- let(:debug) { true }
55
- it 'calls the explain method' do
56
- expect(query).to receive(:select).and_return(query)
57
- expect(query).to receive(:includes).and_return(query)
58
- expect(subject).to receive(:explain_query)
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
- context '#generate with a real AR model' do
65
- let(:query) { ActiveBook }
80
+ context 'with a real AR model' do
81
+ let(:query) { ActiveBook }
66
82
 
67
- it 'calls the select columns for the top level, and includes the right association hashes' do
68
- expected_includes = {
69
- author: {
70
- books: {}
71
- },
72
- category: {
73
- books: {}
74
- },
75
- tags: {}
76
- }
77
- # expect(query).to receive(:includes).with(expected_includes).and_return(query)
78
- expect(subject).to_not receive(:explain_query)
79
- final_query = subject.generate
80
- expect(final_query.select_values).to match_array(expected_select_from_to_query)
81
- # Our query selector always uses a single hash tree from the top, not an array of things
82
- includes_hash = final_query.includes_values.first
83
- expect(includes_hash).to match(expected_includes)
84
- # Also, make AR do the actual query to make sure everything is wired up correctly
85
- result = final_query.to_a
86
- expect(result.size).to be > 2 # We are using 2 but we've seeded more
87
- book1 = result[0]
88
- book2 = result[1]
89
- expect(book1.author.id).to eq 11
90
- expect(book1.author.books.size).to eq 1
91
- expect(book1.author.books.map(&:simple_name)).to eq(['Book1'])
92
- expect(book1.category.name).to eq 'cat1'
93
- expect(book1.tags.map(&:name)).to match_array(%w[blue red green])
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
- expect(book2.author.id).to eq 22
96
- expect(book2.author.books.size).to eq 1
97
- expect(book2.author.books.map(&:simple_name)).to eq(['Book2'])
98
- expect(book2.category.name).to eq 'cat2'
99
- expect(book2.tags.map(&:name)).to match_array(['red'])
100
- end
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
- it 'calls the explain debug method if enabled' do
103
- suppress_output do
104
- # Actually make it run all the way...but suppressing the output
105
- subject.generate
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.35
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-06-20 00:00:00.000000000 Z
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