dynamo-record 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.dockerignore +15 -0
- data/.gitignore +9 -5
- data/.rspec +1 -0
- data/.rubocop.yml +9 -30
- data/.travis.yml +18 -2
- data/Dockerfile +22 -0
- data/Gemfile +0 -1
- data/LICENSE.txt +21 -0
- data/README.md +75 -17
- data/build.sh +10 -20
- data/docker-compose.override.example.yml +19 -0
- data/docker-compose.yml +7 -2
- data/dynamo-record.gemspec +40 -28
- data/lib/dynamo/record.rb +17 -0
- data/lib/dynamo/record/marshalers.rb +46 -0
- data/lib/dynamo/record/model.rb +127 -0
- data/lib/dynamo/record/model_existence_validator.rb +10 -0
- data/lib/{dynamo-record → dynamo}/record/railtie.rb +1 -3
- data/lib/dynamo/record/table_migration.rb +59 -0
- data/lib/dynamo/record/task_helpers/cleanup.rb +21 -0
- data/lib/dynamo/record/task_helpers/drop_all_tables.rb +19 -0
- data/lib/dynamo/record/task_helpers/drop_table.rb +13 -0
- data/lib/dynamo/record/task_helpers/list_tables.rb +15 -0
- data/lib/dynamo/record/task_helpers/migration_runner.rb +72 -0
- data/lib/dynamo/record/task_helpers/scale.rb +90 -0
- data/lib/dynamo/record/version.rb +5 -0
- data/lib/tasks/dynamo.rake +7 -7
- metadata +96 -37
- data/Dockerfile.test +0 -23
- data/Gemfile.lock +0 -178
- data/doc/testing.md +0 -11
- data/docker-compose.dev.override.yml +0 -6
- data/lib/dynamo-record.rb +0 -4
- data/lib/dynamo-record/marshalers.rb +0 -44
- data/lib/dynamo-record/model.rb +0 -127
- data/lib/dynamo-record/record.rb +0 -7
- data/lib/dynamo-record/record/version.rb +0 -5
- data/lib/dynamo-record/table_migration.rb +0 -58
- data/lib/dynamo-record/task_helpers/cleanup.rb +0 -19
- data/lib/dynamo-record/task_helpers/drop_all_tables.rb +0 -17
- data/lib/dynamo-record/task_helpers/drop_table.rb +0 -11
- data/lib/dynamo-record/task_helpers/list_tables.rb +0 -13
- data/lib/dynamo-record/task_helpers/migration_runner.rb +0 -70
- data/lib/dynamo-record/task_helpers/scale.rb +0 -86
- data/lib/model_existence_validator.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc3a4024e4ef59d2f27311c320b5bf33aa91ffb4
|
4
|
+
data.tar.gz: 793d770c42ac639e77a0ce1e4db3ca1fd6cef2fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19daa6e06995bfc7d57d4c05d5454e6def992562742edc9d20b0aea56fd8011f3ca8343f9b5dcba1c5ba21b8921aa1c3ec2ce644963273e0ab992e6dc1ead98b
|
7
|
+
data.tar.gz: 9578863c9c36e8dfa7577af2f48b5f357eea6b7f9281c2964fa3bcde6134a02b87677769fcfde57c69ac990c808ab6f465f10304f9d84a55d5200ba68afe72b0
|
data/.dockerignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
/coverage/
|
2
|
+
/doc/
|
3
|
+
/Dockerfile
|
4
|
+
/docker-compose.yml
|
5
|
+
/docker-compose.override.example.yml
|
6
|
+
/docker-compose.override.yml
|
7
|
+
/Gemfile.lock
|
8
|
+
/log/
|
9
|
+
/pkg/
|
10
|
+
/spec/gemfiles/.bundle/
|
11
|
+
/spec/dummy/log/
|
12
|
+
/spec/dummy/tmp/
|
13
|
+
/spec/gemfiles/*.gemfile.lock
|
14
|
+
/switchman-inst-jobs-*.gem
|
15
|
+
/tmp/
|
data/.gitignore
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
/docker-compose.override.yml
|
2
|
-
|
3
1
|
/.bundle/
|
2
|
+
/.rspec_status
|
3
|
+
/.ruby-version
|
4
4
|
/.yardoc
|
5
5
|
/_yardoc/
|
6
6
|
/coverage/
|
7
|
+
/docker-compose.override.yml
|
8
|
+
/dynamo-record-*.gem
|
9
|
+
/Gemfile.lock
|
7
10
|
/pkg/
|
11
|
+
/spec/gemfiles/.bundle/
|
12
|
+
/spec/dummy/log/
|
13
|
+
/spec/dummy/tmp/
|
14
|
+
/spec/gemfiles/*.gemfile.lock
|
8
15
|
/spec/reports/
|
9
16
|
/tmp/
|
10
|
-
|
11
|
-
# rspec failure tracking
|
12
|
-
.rspec_status
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Rails:
|
2
2
|
Enabled: true
|
3
3
|
|
4
|
-
Rails/HttpPositionalArguments:
|
5
|
-
# Renable once we are on Rails v5
|
6
|
-
Enabled: false
|
7
|
-
|
8
4
|
AllCops:
|
5
|
+
TargetRailsVersion: 4.2
|
9
6
|
TargetRubyVersion: 2.3
|
10
7
|
|
8
|
+
Metrics/AbcSize:
|
9
|
+
Max: 20 # Default: 15
|
10
|
+
|
11
11
|
Metrics/ClassLength:
|
12
12
|
Max: 200 # Default: 100
|
13
13
|
|
@@ -20,9 +20,10 @@ Metrics/MethodLength:
|
|
20
20
|
Metrics/BlockLength:
|
21
21
|
Max: 30
|
22
22
|
Exclude:
|
23
|
+
- 'dynamo-record.gemspec'
|
23
24
|
- 'spec/**/*.rb'
|
24
25
|
|
25
|
-
|
26
|
+
Layout/AlignParameters:
|
26
27
|
# Alignment of parameters in multi-line method calls.
|
27
28
|
#
|
28
29
|
# The `with_fixed_indentation` style aligns the following lines with one
|
@@ -32,24 +33,8 @@ Style/AlignParameters:
|
|
32
33
|
# b)
|
33
34
|
EnforcedStyle: with_fixed_indentation
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
#
|
38
|
-
# Basically there are two different styles:
|
39
|
-
#
|
40
|
-
# `nested` - have each child on a separate line
|
41
|
-
# class Foo
|
42
|
-
# class Bar
|
43
|
-
# end
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# `compact` - combine definitions as much as possible
|
47
|
-
# class Foo::Bar
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# The compact style is only forced, for classes / modules with one child.
|
51
|
-
EnforcedStyle: nested
|
52
|
-
Enabled: false
|
36
|
+
Lint/EndAlignment:
|
37
|
+
EnforcedStyleAlignWith: variable
|
53
38
|
|
54
39
|
Style/Documentation:
|
55
40
|
# This cop checks for missing top-level documentation of classes and modules.
|
@@ -58,12 +43,6 @@ Style/Documentation:
|
|
58
43
|
# classes or other modules.
|
59
44
|
Enabled: false
|
60
45
|
|
61
|
-
Lint/EndAlignment:
|
62
|
-
AlignWith: variable
|
63
|
-
|
64
|
-
Style/CaseIndentation:
|
65
|
-
IndentWhenRelativeTo: end
|
66
|
-
|
67
46
|
Style/FrozenStringLiteralComment:
|
68
47
|
# `when_needed` will add the frozen string literal comment to files
|
69
48
|
# only when the `TargetRubyVersion` is set to 2.3+.
|
@@ -78,4 +57,4 @@ Style/FrozenStringLiteralComment:
|
|
78
57
|
|
79
58
|
Style/NumericPredicate:
|
80
59
|
Exclude:
|
81
|
-
- 'spec
|
60
|
+
- 'spec/**/*.rb'
|
data/.travis.yml
CHANGED
@@ -1,5 +1,21 @@
|
|
1
|
+
dist: trusty
|
1
2
|
sudo: false
|
2
3
|
language: ruby
|
4
|
+
cache: bundler
|
5
|
+
|
3
6
|
rvm:
|
4
|
-
- 2.3
|
5
|
-
|
7
|
+
- 2.3
|
8
|
+
- 2.4
|
9
|
+
|
10
|
+
gemfile:
|
11
|
+
- spec/gemfiles/rails-4.2.gemfile
|
12
|
+
- spec/gemfiles/rails-5.0.gemfile
|
13
|
+
- spec/gemfiles/rails-5.1.gemfile
|
14
|
+
|
15
|
+
before_install: gem update bundler
|
16
|
+
bundler_args: --jobs 3
|
17
|
+
install: bundle install --jobs 3
|
18
|
+
|
19
|
+
script:
|
20
|
+
- bash -c "if [ '$TRAVIS_RUBY_VERSION' = '2.4' ] && [[ '$BUNDLE_GEMFILE' == *'rails-5.0'* ]]; then bundle exec rubocop --fail-level autocorrect; fi"
|
21
|
+
- bundle exec rspec
|
data/Dockerfile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
FROM instructure/rvm
|
2
|
+
|
3
|
+
WORKDIR /app
|
4
|
+
|
5
|
+
COPY dynamo-record.gemspec Gemfile /app/
|
6
|
+
COPY lib/dynamo/record/version.rb /app/lib/dynamo/record/version.rb
|
7
|
+
|
8
|
+
USER root
|
9
|
+
RUN mkdir -p /app/coverage \
|
10
|
+
/app/spec/gemfiles/.bundle \
|
11
|
+
/app/spec/internal/log \
|
12
|
+
&& chown -R docker:docker /app
|
13
|
+
|
14
|
+
USER docker
|
15
|
+
RUN /bin/bash -l -c "cd /app && rvm-exec 2.4 bundle install --jobs 5"
|
16
|
+
COPY . /app
|
17
|
+
|
18
|
+
USER root
|
19
|
+
RUN chown -R docker:docker /app
|
20
|
+
USER docker
|
21
|
+
|
22
|
+
CMD /bin/bash -l -c "rvm-exec 2.4 bundle exec wwtd"
|
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Instructure, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
#
|
1
|
+
# Dynamo::Record
|
2
2
|
|
3
3
|
Provides helpful rake tasks and model extensions on top of
|
4
4
|
[aws-record](https://github.com/aws/aws-sdk-ruby-record).
|
5
5
|
|
6
|
+
|
6
7
|
## Installation
|
7
8
|
|
8
9
|
Add this line to your application's Gemfile:
|
@@ -19,11 +20,12 @@ Or install it yourself as:
|
|
19
20
|
|
20
21
|
$ gem install dynamo-record
|
21
22
|
|
23
|
+
|
22
24
|
## Usage
|
23
25
|
|
24
26
|
### Models
|
25
27
|
|
26
|
-
In `app/models`, create a class that includes `
|
28
|
+
In `app/models`, create a class that includes `Dynamo::Record::Model` and contains
|
27
29
|
one or more of the
|
28
30
|
[standard set](http://docs.aws.amazon.com/awssdkrubyrecord/api/Aws/Record.html)
|
29
31
|
of attribute declarations, along with the following new composite attribute
|
@@ -34,9 +36,9 @@ types:
|
|
34
36
|
|
35
37
|
An example file:
|
36
38
|
|
37
|
-
```
|
39
|
+
```ruby
|
38
40
|
class MyModel
|
39
|
-
include
|
41
|
+
include Dynamo::Record::Model
|
40
42
|
composite_string_attr(
|
41
43
|
:model_key,
|
42
44
|
hash_key: true,
|
@@ -57,7 +59,7 @@ Declaring secondary indexes are included in `aws-record` and are defined
|
|
57
59
|
|
58
60
|
As an example, a global secondary index can be defined as follows:
|
59
61
|
|
60
|
-
```
|
62
|
+
```ruby
|
61
63
|
global_secondary_index(
|
62
64
|
:user_idx,
|
63
65
|
hash_key: :user_id,
|
@@ -73,7 +75,7 @@ As an example, a global secondary index can be defined as follows:
|
|
73
75
|
|
74
76
|
As an example, a local secondary index can be defined as follows:
|
75
77
|
|
76
|
-
```
|
78
|
+
```ruby
|
77
79
|
local_secondary_index(
|
78
80
|
:score_idx,
|
79
81
|
range_key: :score,
|
@@ -98,7 +100,7 @@ Query helpers are included as class methods.
|
|
98
100
|
For models that have composite attributes, create a composite key value from the
|
99
101
|
individual attribute parts:
|
100
102
|
|
101
|
-
```
|
103
|
+
```ruby
|
102
104
|
hash_key = MyModel.composite_key('model_1', 'account_1')
|
103
105
|
```
|
104
106
|
|
@@ -106,7 +108,7 @@ hash_key = MyModel.composite_key('model_1', 'account_1')
|
|
106
108
|
|
107
109
|
Split a composite attribute value into its individual attribute parts:
|
108
110
|
|
109
|
-
```
|
111
|
+
```ruby
|
110
112
|
model_id, acccount_id = MyModel.split_composite(hash_key)
|
111
113
|
```
|
112
114
|
|
@@ -115,7 +117,7 @@ model_id, acccount_id = MyModel.split_composite(hash_key)
|
|
115
117
|
Find all item instances that match a given hash key value. `opts` are options
|
116
118
|
passed to the underlying query.
|
117
119
|
|
118
|
-
```
|
120
|
+
```ruby
|
119
121
|
MyModel.find_all_by_hash_key(hash_key)
|
120
122
|
```
|
121
123
|
|
@@ -124,7 +126,7 @@ MyModel.find_all_by_hash_key(hash_key)
|
|
124
126
|
Find all item instances using a global secondary instance using a hash key
|
125
127
|
value. `opts` are options passed to the underlying query.
|
126
128
|
|
127
|
-
```
|
129
|
+
```ruby
|
128
130
|
MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1')
|
129
131
|
```
|
130
132
|
|
@@ -133,7 +135,7 @@ MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1')
|
|
133
135
|
Find all item instances using a global secondary instance using a hash key value
|
134
136
|
and range key value.
|
135
137
|
|
136
|
-
```
|
138
|
+
```ruby
|
137
139
|
MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1', 0.0)
|
138
140
|
```
|
139
141
|
|
@@ -142,7 +144,7 @@ MyModel.find_all_by_gsi_hash_key('user_idx', 'user_1', 0.0)
|
|
142
144
|
Find all item instances using a local secondary instance using a hash key value.
|
143
145
|
`opts` are options passed to the underlying query.
|
144
146
|
|
145
|
-
```
|
147
|
+
```ruby
|
146
148
|
MyModel.find_all_by_lsi_hash_key('score_idx', 'user_1')
|
147
149
|
```
|
148
150
|
|
@@ -151,7 +153,7 @@ MyModel.find_all_by_lsi_hash_key('score_idx', 'user_1')
|
|
151
153
|
Find all item instances using a local secondary instance using a hash key value
|
152
154
|
and range key value.
|
153
155
|
|
154
|
-
```
|
156
|
+
```ruby
|
155
157
|
MyModel.find_all_by_lsi_hash_key('score_idx', 'user_1', 0.0)
|
156
158
|
```
|
157
159
|
|
@@ -163,9 +165,9 @@ follows the style of standard Rails migration files like
|
|
163
165
|
`YYYYMMDDHHMMSS_create_model_1.rb`. A migration file that creates a Dynamo table
|
164
166
|
looks like:
|
165
167
|
|
166
|
-
```
|
168
|
+
```ruby
|
167
169
|
module DynamoMigrate
|
168
|
-
class CreateMyModel <
|
170
|
+
class CreateMyModel < Dynamo::Record::TableMigration
|
169
171
|
def self.up
|
170
172
|
migrate(MyModel) do |migration|
|
171
173
|
migration.create!(
|
@@ -191,12 +193,68 @@ throughput of the secondary index.
|
|
191
193
|
|
192
194
|
A migration file that creates a Dynamo stream looks like:
|
193
195
|
|
194
|
-
```
|
196
|
+
```ruby
|
195
197
|
module DynamoMigrate
|
196
|
-
class AddMyModelStream <
|
198
|
+
class AddMyModelStream < Dynamo::Record::TableMigration
|
197
199
|
def self.update
|
198
200
|
add_stream(MyModel)
|
199
201
|
end
|
200
202
|
end
|
201
203
|
end
|
202
204
|
```
|
205
|
+
|
206
|
+
|
207
|
+
## Development
|
208
|
+
|
209
|
+
A simple docker environment has been provided for spinning up and testing this
|
210
|
+
gem with multiple versions of Ruby. This requires docker and docker-compose to
|
211
|
+
be installed. To get started, run the following:
|
212
|
+
|
213
|
+
```bash
|
214
|
+
./build.sh
|
215
|
+
```
|
216
|
+
|
217
|
+
This will install the gem in a docker image with all versions of Ruby installed,
|
218
|
+
and install all gem dependencies in the Ruby 2.4 set of gems. It will also
|
219
|
+
download and spin up a DynamoDB Local container for use with specs. Finally, it
|
220
|
+
will run [wwtd](https://github.com/grosser/wwtd), which runs all specs across
|
221
|
+
all supported version of Ruby and Rails, bundling gems for each combination
|
222
|
+
along the way.
|
223
|
+
|
224
|
+
The first build will take a long time, however, docker images and gems are
|
225
|
+
cached, making additional runs significantly faster.
|
226
|
+
|
227
|
+
Individual spec runs can be started like so:
|
228
|
+
|
229
|
+
```bash
|
230
|
+
docker-compose run --rm app /bin/bash -l -c \
|
231
|
+
"BUNDLE_GEMFILE=spec/gemfiles/rails-5.0.gemfile rvm-exec 2.4 bundle exec rspec"
|
232
|
+
```
|
233
|
+
|
234
|
+
If you'd like to mount your git checkout within the docker container running
|
235
|
+
tests so changes are easier to test, use the override provided:
|
236
|
+
|
237
|
+
```bash
|
238
|
+
cp docker-compose.override.example.yml docker-compose.override.yml
|
239
|
+
```
|
240
|
+
|
241
|
+
|
242
|
+
## Making a new Release
|
243
|
+
|
244
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
245
|
+
release a new version, update the version number in `version.rb`, and then just
|
246
|
+
run `bundle exec rake release`, which will create a git tag for the version,
|
247
|
+
push git commits and tags, and push the `.gem` file to
|
248
|
+
[rubygems.org](https://rubygems.org).
|
249
|
+
|
250
|
+
|
251
|
+
## Contributing
|
252
|
+
|
253
|
+
Bug reports and pull requests are welcome on GitHub at
|
254
|
+
https://github.com/instructure/dynamo-record.
|
255
|
+
|
256
|
+
|
257
|
+
## License
|
258
|
+
|
259
|
+
The gem is available as open source under the terms of the
|
260
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
data/build.sh
CHANGED
@@ -1,28 +1,18 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
|
3
|
-
export COMPOSE_PROJECT_NAME=dynamorecord
|
4
|
-
export COMPOSE_FILE=docker-compose.yml
|
1
|
+
#!/bin/bash -ex
|
5
2
|
|
6
3
|
function cleanup() {
|
7
4
|
exit_code=$?
|
8
5
|
set +e
|
9
|
-
docker
|
10
|
-
docker-compose
|
11
|
-
docker
|
6
|
+
docker cp coverage:/app/coverage .
|
7
|
+
docker-compose kill
|
8
|
+
docker-compose rm -f
|
12
9
|
exit $exit_code
|
13
10
|
}
|
14
11
|
trap cleanup INT TERM EXIT
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
docker-compose build --pull
|
19
|
-
docker-compose run --
|
20
|
-
|
21
|
-
|
22
|
-
#echo "Reporting test coverage"
|
23
|
-
#if [[ $? -eq 0 && -a 'coverage/.last_run.json' ]]; then
|
24
|
-
# ruby_coverage=$(cat coverage/api/.last_run.json | grep 'covered_percent' | egrep -o '[0-9]+(\.[0-9]+)?')
|
25
|
-
# echo "Sending to gergich"
|
26
|
-
# gergich message ":ruby: <http://jenkins.instructure.com/job/dynamo-record/${BUILD_ID}/|${ruby_coverage}%>"
|
27
|
-
# gergich publish
|
28
|
-
#fi
|
13
|
+
docker-compose pull dynamo
|
14
|
+
docker-compose up -d dynamo
|
15
|
+
docker-compose build --pull app
|
16
|
+
docker-compose run --rm app /bin/bash -l -c \
|
17
|
+
"rvm-exec 2.4 bundle exec rubocop --fail-level autocorrect"
|
18
|
+
docker-compose run --name coverage app $@
|
@@ -0,0 +1,19 @@
|
|
1
|
+
version: '2'
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
volumes:
|
6
|
+
- .:/app
|
7
|
+
- gems:/home/docker/.rvm/gems
|
8
|
+
# Disable the rest of these volumes if the container can safely write to
|
9
|
+
# your host filesystem mount named above. You might want to use the rest
|
10
|
+
# of these unless you're using dinghy on OSX (usually needed for linux).
|
11
|
+
- coverage:/app/coverage
|
12
|
+
- bundle-config:/app/spec/gemfiles/.bundle
|
13
|
+
- internal-log:/app/spec/internal/log
|
14
|
+
|
15
|
+
volumes:
|
16
|
+
coverage: {}
|
17
|
+
bundle-config: {}
|
18
|
+
gems: {}
|
19
|
+
internal-log: {}
|