db_fuel 1.0.0.pre.alpha → 1.2.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/.tool-versions +1 -0
- data/CHANGELOG.md +13 -2
- data/README.md +422 -3
- data/db_fuel.gemspec +6 -6
- data/lib/db_fuel.rb +6 -0
- data/lib/db_fuel/db_provider.rb +82 -0
- data/lib/db_fuel/library.rb +19 -2
- data/lib/db_fuel/library/active_record/base.rb +55 -0
- data/lib/db_fuel/library/active_record/find_or_insert.rb +103 -0
- data/lib/db_fuel/library/active_record/insert.rb +80 -0
- data/lib/db_fuel/library/active_record/update.rb +105 -0
- data/lib/db_fuel/library/active_record/update_all.rb +96 -0
- data/lib/db_fuel/library/active_record/upsert.rb +210 -0
- data/lib/db_fuel/library/dbee/base.rb +5 -0
- data/lib/db_fuel/library/dbee/query.rb +2 -2
- data/lib/db_fuel/library/dbee/range.rb +20 -7
- data/lib/db_fuel/modeling.rb +11 -0
- data/lib/db_fuel/modeling/attribute_renderer_set.rb +83 -0
- data/lib/db_fuel/modeling/keyed_column.rb +30 -0
- data/lib/db_fuel/version.rb +1 -1
- metadata +22 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4f5691edb9519be2c43b787f9eeee14d2e2e83fcf9071e21dbef2442449d3fa
|
4
|
+
data.tar.gz: a95cc6d63d3eba9256c022891328352662b64cf8e0391a92962609f6d3a8062c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36c2477f3010bd60a7ef7a49f60f7a5302d2cec2ad8be034d83e18923eed07820578a87993a9ebc07e1121c8853d45e5060eaca4d4895222afb3b69b8a8b61f9
|
7
|
+
data.tar.gz: 54f65f7f0d56271bacb6b67512f10135b4d22ddb64dd0a7d1fc864e6d2cd29a0d7e4579056f518cf517b5b3353715bafc489743d596cc8bd8e3e9a0812d6755b
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 2.5
|
3
3
|
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
4
5
|
|
5
6
|
Layout/LineLength:
|
6
7
|
Max: 100
|
@@ -8,7 +9,7 @@ Layout/LineLength:
|
|
8
9
|
- db_fuel.gemspec
|
9
10
|
|
10
11
|
Metrics/BlockLength:
|
11
|
-
|
12
|
+
IgnoredMethods:
|
12
13
|
- let
|
13
14
|
- it
|
14
15
|
- describe
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.6.6
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
-
# 1.
|
1
|
+
# 1.1.0 (Decmeber 1st, 2020)
|
2
2
|
|
3
|
-
|
3
|
+
New Jobs:
|
4
|
+
|
5
|
+
* db_fuel/active_record/find_or_insert
|
6
|
+
* db_fuel/active_record/insert
|
7
|
+
* db_fuel/active_record/update
|
8
|
+
|
9
|
+
# 1.0.0 (November 18th, 2020)
|
10
|
+
|
11
|
+
Initial implementation. Includes jobs:
|
12
|
+
|
13
|
+
* db_fuel/dbee/query
|
14
|
+
* db_fuel/dbee/range
|
4
15
|
|
5
16
|
# 0.0.1
|
6
17
|
|
data/README.md
CHANGED
@@ -1,5 +1,424 @@
|
|
1
|
-
#
|
1
|
+
# DB Fuel
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/db_fuel.svg)](https://badge.fury.io/rb/db_fuel) [![Build Status](https://travis-ci.org/bluemarblepayroll/db_fuel.svg?branch=master)](https://travis-ci.org/bluemarblepayroll/db_fuel) [![Maintainability](https://api.codeclimate.com/v1/badges/21945483950d9c35fabb/maintainability)](https://codeclimate.com/github/bluemarblepayroll/db_fuel/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/21945483950d9c35fabb/test_coverage)](https://codeclimate.com/github/bluemarblepayroll/db_fuel/test_coverage) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
4
4
|
|
5
|
-
|
5
|
+
This library is a plugin for [Burner](https://github.com/bluemarblepayroll/burner). Burner, by itself, cannot use a database. So, if you wish to use a database as a data source or as a target for mutation then you need to add a library similar to this.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To install through Rubygems:
|
10
|
+
|
11
|
+
````bash
|
12
|
+
gem install db_fuel
|
13
|
+
````
|
14
|
+
|
15
|
+
You can also add this to your Gemfile:
|
16
|
+
|
17
|
+
````bash
|
18
|
+
bundle add db_fuel
|
19
|
+
````
|
20
|
+
|
21
|
+
## Jobs
|
22
|
+
|
23
|
+
Refer to the [Burner](https://github.com/bluemarblepayroll/burner) library for more specific information on how Burner works. This section will just focus on what this library directly adds.
|
24
|
+
|
25
|
+
### ActiveRecord Jobs
|
26
|
+
|
27
|
+
* **db_fuel/active_record/find_or_insert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps, unique_attributes]: An extension of the `db_fuel/active_record/insert` job that adds an existence check before SQL insertion. The `unique_attributes` will be converted to WHERE clauses for performing the existence check.
|
28
|
+
* **db_fuel/active_record/insert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps]: This job can take the objects in a register and insert them into a database table. If primary_key is specified then its key will be set to the primary key. Note that composite primary keys are not supported. Attributes defines which object properties to convert to SQL. Refer to the class and constructor specification for more detail.
|
29
|
+
* **db_fuel/active_record/update_all** [name, table_name, attributes, debug, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses. One or more records may be updated at a time. Refer to the class and constructor specification for more detail.
|
30
|
+
* **db_fuel/active_record/update** [name, table_name, attributes, debug, register, primary_key, separator, timestamps, unique_attributes]: This job can take the unique objects in a register and updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while unique_attributes translate to WHERE clauses to find the records to update. The primary_key is used to update the unique record. Only one record will be updated per statement. Refer to the class and constructor specification for more detail.
|
31
|
+
* **db_fuel/active_record/upsert** [name, table_name, attributes, debug, primary_key, register, separator, timestamps, unique_attributes]: This job can take the objects in a register and either inserts or updates them within a database table. Attributes defines which object properties to convert to SQL SET clauses while each key in unique_attributes become a WHERE clause in order to check for the existence of a specific record. The updated record will use the primary_key specified to perform the UPDATE operation. Note that composite primary keys are not supported. Refer to the class and constructor specification for more detail.
|
32
|
+
|
33
|
+
### Dbee Jobs
|
34
|
+
|
35
|
+
* **db_fuel/dbee/query** [model, query, register]: Pass in a [Dbee](https://github.com/bluemarblepayroll/dbee) model and query and store the results in the specified register. Refer to the [Dbee](https://github.com/bluemarblepayroll/dbee) library directly on how to craft a model or query.
|
36
|
+
* **db_fuel/dbee/range** [key, key_path, model, query, register, separator]: Similar to `db_fuel/dbee/query` with the addition of being able to grab a list of values from the register to use as a Dbee EQUALS/IN filter. This helps to dynamically limit the resulting record set. The key is used to specify where to grab the list of values, while the key_path will be used to craft the [Dbee equal's filter](https://github.com/bluemarblepayroll/dbee/blob/master/lib/dbee/query/filters/equals.rb). Separator is exposed in case nested object support is necessary.
|
37
|
+
|
38
|
+
## Examples
|
39
|
+
|
40
|
+
In all the examples we will assume we have the following schema:
|
41
|
+
|
42
|
+
````ruby
|
43
|
+
ActiveRecord::Schema.define do
|
44
|
+
create_table :statuses do |t|
|
45
|
+
t.string :code, null: false, limit: 25
|
46
|
+
t.integer :priority, null: false, default: 0
|
47
|
+
t.timestamps
|
48
|
+
end
|
49
|
+
|
50
|
+
create_table :patients do |t|
|
51
|
+
t.string :chart_number
|
52
|
+
t.string :first_name
|
53
|
+
t.string :middle_name
|
54
|
+
t.string :last_name
|
55
|
+
t.references :status
|
56
|
+
t.timestamps
|
57
|
+
end
|
58
|
+
end
|
59
|
+
````
|
60
|
+
|
61
|
+
### Querying the Database
|
62
|
+
|
63
|
+
The `db_fuel/dbee/query` job can be utilized to process a SQL query and store the results in a Burner::Payload register.
|
64
|
+
|
65
|
+
Let's say for example we have a list of patients we would like to retrieve:
|
66
|
+
|
67
|
+
````ruby
|
68
|
+
pipeline = {
|
69
|
+
jobs: [
|
70
|
+
{
|
71
|
+
name: 'retrieve_patients',
|
72
|
+
type: 'db_fuel/dbee/query',
|
73
|
+
model: {
|
74
|
+
name: :patients
|
75
|
+
},
|
76
|
+
query: {
|
77
|
+
fields: [
|
78
|
+
{ key_path: :id },
|
79
|
+
{ key_path: :first_name }
|
80
|
+
],
|
81
|
+
sorters: [
|
82
|
+
{ key_path: :first_name }
|
83
|
+
]
|
84
|
+
},
|
85
|
+
register: :patients
|
86
|
+
}
|
87
|
+
]
|
88
|
+
}
|
89
|
+
|
90
|
+
payload = Burner::Payload.new
|
91
|
+
|
92
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
93
|
+
````
|
94
|
+
|
95
|
+
If we were to inspect the contents of `payload` we should see the patient's result set loaded:
|
96
|
+
|
97
|
+
````ruby
|
98
|
+
payload['patients'] # array in form of: [ { "id" => 1, "first_name" => "Something" }, ... ]
|
99
|
+
````
|
100
|
+
|
101
|
+
### Limiting Result Sets
|
102
|
+
|
103
|
+
The `db_fuel/dbee/query` does not provide a way to dynamically connect the query to existing data. You are free to put any Dbee query filters in the query declaration, but what if you would like to further limit this based on the knowledge of a range of values? The `db_fuel/dbee/range` job is meant to do exactly this. On the surface it is mainly an extension of the `db_fuel/dbee/query` job.
|
104
|
+
|
105
|
+
Let's say we would like to query patients but we want to limit it to an inputted list of first names:
|
106
|
+
|
107
|
+
````ruby
|
108
|
+
pipeline = {
|
109
|
+
jobs: [
|
110
|
+
{
|
111
|
+
name: :load_first_names,
|
112
|
+
type: 'b/value/static',
|
113
|
+
register: :patients,
|
114
|
+
value: [
|
115
|
+
{ fname: 'Bozo' },
|
116
|
+
{ fname: 'Bugs' },
|
117
|
+
]
|
118
|
+
},
|
119
|
+
{
|
120
|
+
name: 'retrieve_patients',
|
121
|
+
type: 'db_fuel/dbee/range',
|
122
|
+
model: {
|
123
|
+
name: :patients
|
124
|
+
},
|
125
|
+
query: {
|
126
|
+
fields: [
|
127
|
+
{ key_path: :id },
|
128
|
+
{ key_path: :first_name }
|
129
|
+
],
|
130
|
+
sorters: [
|
131
|
+
{ key_path: :first_name }
|
132
|
+
]
|
133
|
+
},
|
134
|
+
register: :patients,
|
135
|
+
key: :fname,
|
136
|
+
key_path: :first_name
|
137
|
+
}
|
138
|
+
]
|
139
|
+
}
|
140
|
+
|
141
|
+
payload = Burner::Payload.new
|
142
|
+
|
143
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
144
|
+
````
|
145
|
+
|
146
|
+
If we were to inspect the contents of `payload` we should see the patient's result set loaded:
|
147
|
+
|
148
|
+
````ruby
|
149
|
+
payload['patients'] # array in form of: [ { "id" => 1, "first_name" => "Something" }, ... ]
|
150
|
+
````
|
151
|
+
|
152
|
+
The only difference between the query and range jobs should be the latter is limited based on the incoming first names.
|
153
|
+
|
154
|
+
### Updating the Database
|
155
|
+
|
156
|
+
#### Inserting Records
|
157
|
+
|
158
|
+
We can deal with persistence using the db_fuel/active_record/* jobs. In order to insert new records we can use the `db_fuel/active_record/insert` job. For example:
|
159
|
+
|
160
|
+
````ruby
|
161
|
+
pipeline = {
|
162
|
+
jobs: [
|
163
|
+
{
|
164
|
+
name: :load_patients,
|
165
|
+
type: 'b/value/static',
|
166
|
+
register: :patients,
|
167
|
+
value: [
|
168
|
+
{ chart_number: 'B0001', first_name: 'Bugs', last_name: 'Bunny' },
|
169
|
+
{ chart_number: 'B0002', first_name: 'Babs', last_name: 'Bunny' }
|
170
|
+
]
|
171
|
+
},
|
172
|
+
{
|
173
|
+
name: 'insert_patients',
|
174
|
+
type: 'db_fuel/active_record/insert',
|
175
|
+
register: :patients,
|
176
|
+
attributes: [
|
177
|
+
{ key: :chart_number },
|
178
|
+
{ key: :first_name },
|
179
|
+
{ key: :last_name }
|
180
|
+
],
|
181
|
+
table_name: 'patients',
|
182
|
+
primary_key: {
|
183
|
+
key: :id
|
184
|
+
}
|
185
|
+
}
|
186
|
+
]
|
187
|
+
}
|
188
|
+
|
189
|
+
payload = Burner::Payload.new
|
190
|
+
|
191
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
192
|
+
````
|
193
|
+
|
194
|
+
There should now be two new patients, AB0 and AB1, present in the table `patients`.
|
195
|
+
|
196
|
+
Notes:
|
197
|
+
|
198
|
+
* Since we specified the `primary_key`, the records' `id` attributes should be set to their respective primary key values.
|
199
|
+
* Composite primary keys are not currently supported.
|
200
|
+
* Set `debug: true` to print out each INSERT statement in the output (not for production use.)
|
201
|
+
|
202
|
+
#### Inserting Only New Records
|
203
|
+
|
204
|
+
Another job `db_fuel/active_record/find_or_insert` allows for an existence check to performed each insertion. If a record is found then it will not insert the record. If `primary_key` is set then the existence check will also still set the primary key on the payload's respective object. Note that composite primary keys are not currently supported. We can build on the above insert example for only inserting new patients if their chart_number is unique:
|
205
|
+
|
206
|
+
````ruby
|
207
|
+
pipeline = {
|
208
|
+
jobs: [
|
209
|
+
{
|
210
|
+
name: :load_patients,
|
211
|
+
type: 'b/value/static',
|
212
|
+
register: :patients,
|
213
|
+
value: [
|
214
|
+
{ chart_number: 'B0001', first_name: 'Bugs', last_name: 'Bunny' },
|
215
|
+
{ chart_number: 'B0002', first_name: 'Babs', last_name: 'Bunny' }
|
216
|
+
]
|
217
|
+
},
|
218
|
+
{
|
219
|
+
name: 'insert_patients',
|
220
|
+
type: 'db_fuel/active_record/insert',
|
221
|
+
register: :patients,
|
222
|
+
attributes: [
|
223
|
+
{ key: :chart_number },
|
224
|
+
{ key: :first_name },
|
225
|
+
{ key: :last_name }
|
226
|
+
],
|
227
|
+
table_name: 'patients',
|
228
|
+
primary_key: {
|
229
|
+
key: :id
|
230
|
+
},
|
231
|
+
unique_attributes: [
|
232
|
+
{ key: :chart_number }
|
233
|
+
]
|
234
|
+
}
|
235
|
+
]
|
236
|
+
}
|
237
|
+
|
238
|
+
payload = Burner::Payload.new
|
239
|
+
|
240
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
241
|
+
````
|
242
|
+
|
243
|
+
Now only records where the chart_number does not match an existing record will be inserted.
|
244
|
+
|
245
|
+
#### Updating Records
|
246
|
+
|
247
|
+
Let's say we now want to update these unique records' last names:
|
248
|
+
|
249
|
+
````ruby
|
250
|
+
pipeline = {
|
251
|
+
jobs: [
|
252
|
+
{
|
253
|
+
name: :load_patients,
|
254
|
+
type: 'b/value/static',
|
255
|
+
register: :patients,
|
256
|
+
value: [
|
257
|
+
{ chart_number: 'B0001', last_name: 'Fox' },
|
258
|
+
{ chart_number: 'B0002', last_name: 'Smurf' }
|
259
|
+
]
|
260
|
+
},
|
261
|
+
{
|
262
|
+
name: 'update_patients',
|
263
|
+
type: 'db_fuel/active_record/update',
|
264
|
+
register: :patients,
|
265
|
+
attributes: [
|
266
|
+
{ key: :last_name }
|
267
|
+
],
|
268
|
+
table_name: 'patients',
|
269
|
+
primary_key: {
|
270
|
+
key: :id
|
271
|
+
},
|
272
|
+
unique_attributes: [
|
273
|
+
{ key: :chart_number }
|
274
|
+
]
|
275
|
+
}
|
276
|
+
]
|
277
|
+
}
|
278
|
+
|
279
|
+
payload = Burner::Payload.new
|
280
|
+
|
281
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
282
|
+
````
|
283
|
+
|
284
|
+
Each database record should have been updated with their new respective last names based on the primary key specified.
|
285
|
+
|
286
|
+
#### Updating All Records
|
287
|
+
|
288
|
+
Let's say we want to update those records' midddle names:
|
289
|
+
|
290
|
+
````ruby
|
291
|
+
pipeline = {
|
292
|
+
jobs: [
|
293
|
+
{
|
294
|
+
name: :load_patients,
|
295
|
+
type: 'b/value/static',
|
296
|
+
register: :patients,
|
297
|
+
value: [
|
298
|
+
{ chart_number: 'B0001', middle_name: 'Rabbit' },
|
299
|
+
{ chart_number: 'C0001', middle_name: 'Elf' }
|
300
|
+
]
|
301
|
+
},
|
302
|
+
{
|
303
|
+
name: 'update_patients',
|
304
|
+
type: 'db_fuel/active_record/update_all',
|
305
|
+
register: :patients,
|
306
|
+
attributes: [
|
307
|
+
{ key: :last_name }
|
308
|
+
],
|
309
|
+
table_name: 'patients',
|
310
|
+
unique_attributes: [
|
311
|
+
{ key: :chart_number }
|
312
|
+
]
|
313
|
+
}
|
314
|
+
]
|
315
|
+
}
|
316
|
+
|
317
|
+
payload = Burner::Payload.new
|
318
|
+
|
319
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
320
|
+
````
|
321
|
+
|
322
|
+
Each database record should have been updated with their new respective middle names based on chart_number.
|
323
|
+
|
324
|
+
#### Upserting Records
|
325
|
+
|
326
|
+
Let's say we don't know if these chart_number values already exist or not.
|
327
|
+
So we want db_fuel to either insert a record if the chart_number doesn't exist or update the record if the chart_number already exists.
|
328
|
+
|
329
|
+
````ruby
|
330
|
+
pipeline = {
|
331
|
+
jobs: [
|
332
|
+
{
|
333
|
+
name: :load_patients,
|
334
|
+
type: 'b/value/static',
|
335
|
+
register: :patients,
|
336
|
+
value: [
|
337
|
+
{ chart_number: 'B0002', first_name: 'Babs', last_name: 'Bunny' },
|
338
|
+
{ chart_number: 'B0003', first_name: 'Daffy', last_name: 'Duck' }
|
339
|
+
]
|
340
|
+
},
|
341
|
+
{
|
342
|
+
name: 'update_patients',
|
343
|
+
type: 'db_fuel/active_record/upsert',
|
344
|
+
register: :patients,
|
345
|
+
attributes: [
|
346
|
+
{ key: :chart_number },
|
347
|
+
{ key: :first_name },
|
348
|
+
{ key: :last_name }
|
349
|
+
],
|
350
|
+
table_name: 'patients',
|
351
|
+
primary_key: {
|
352
|
+
key: :id
|
353
|
+
},
|
354
|
+
unique_attributes: [
|
355
|
+
{ key: :chart_number }
|
356
|
+
]
|
357
|
+
}
|
358
|
+
]
|
359
|
+
}
|
360
|
+
|
361
|
+
payload = Burner::Payload.new
|
362
|
+
|
363
|
+
Burner::Pipeline.make(pipeline).execute(payload: payload)
|
364
|
+
````
|
365
|
+
|
366
|
+
Each database record should have been either inserted or updated with their corresponding values. In this case Babs' last name
|
367
|
+
was switched back to Bunny and a new record was created for Daffy Duck.
|
368
|
+
|
369
|
+
Notes:
|
370
|
+
|
371
|
+
* The `unique_attributes` translate to WHERE clauses.
|
372
|
+
* Set `debug: true` to print out each UPDATE statement in the output (not for production use.)
|
373
|
+
## Contributing
|
374
|
+
|
375
|
+
### Development Environment Configuration
|
376
|
+
|
377
|
+
Basic steps to take to get this repository compiling:
|
378
|
+
|
379
|
+
1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/) (check db_fuel.gemspec for versions supported)
|
380
|
+
2. Install bundler (gem install bundler)
|
381
|
+
3. Clone the repository (git clone git@github.com:bluemarblepayroll/db_fuel.git)
|
382
|
+
4. Navigate to the root folder (cd db_fuel)
|
383
|
+
5. Install dependencies (bundle)
|
384
|
+
|
385
|
+
### Running Tests
|
386
|
+
|
387
|
+
To execute the test suite run:
|
388
|
+
|
389
|
+
````bash
|
390
|
+
bundle exec rspec spec --format documentation
|
391
|
+
````
|
392
|
+
|
393
|
+
Alternatively, you can have Guard watch for changes:
|
394
|
+
|
395
|
+
````bash
|
396
|
+
bundle exec guard
|
397
|
+
````
|
398
|
+
|
399
|
+
Also, do not forget to run Rubocop:
|
400
|
+
|
401
|
+
````bash
|
402
|
+
bundle exec rubocop
|
403
|
+
````
|
404
|
+
|
405
|
+
### Publishing
|
406
|
+
|
407
|
+
Note: ensure you have proper authorization before trying to publish new versions.
|
408
|
+
|
409
|
+
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
|
410
|
+
|
411
|
+
1. Merge Pull Request into master
|
412
|
+
2. Update `lib/db_fuel/version.rb` using [semantic versioning](https://semver.org/)
|
413
|
+
3. Install dependencies: `bundle`
|
414
|
+
4. Update `CHANGELOG.md` with release notes
|
415
|
+
5. Commit & push master to remote and ensure CI builds master successfully
|
416
|
+
6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
417
|
+
|
418
|
+
## Code of Conduct
|
419
|
+
|
420
|
+
Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bluemarblepayroll/db_fuel/blob/master/CODE_OF_CONDUCT.md).
|
421
|
+
|
422
|
+
## License
|
423
|
+
|
424
|
+
This project is MIT Licensed.
|