ensql 0.6.0 → 0.6.5

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: 3097f158523b78a965c84dbf0e79f41ce4be744d5dd0842fc9f5f780ec9b5fba
4
- data.tar.gz: e5a123a39ab5f6c1b1911bf46972e441f6bb77d69584fd7bb005192baa5a24c8
3
+ metadata.gz: a9e2413596055c82bef5870277ed617889235a66bc6854c762886f14783580c7
4
+ data.tar.gz: 2993ee9976c316a975fd51dc18b53f187298f7e6e2a4627b0b59dc9bd233ec54
5
5
  SHA512:
6
- metadata.gz: 02a9e0a720bc3b861e27782233fac13ec9e58cfb4b3a6892b2d224f3a0d1de76051f2300370ded32fd9acfe677b71705510e3ee1dd95085cbb7b1fdfd8dda676
7
- data.tar.gz: 724701d41daf5554702c6173a2aa6e063034ca3d094ed29eb4cf760c6aba467a13a623f4e5fbc904ca95418a111e281cca4104eb55e8b04ce8d3673323b2d77b
6
+ metadata.gz: 47ee3648dc665dacc57263befd5c46466f36688138120d7c7b82b5a3464daf3c262e28bcc2eb9dd7f58f6cdea13838a352fe93d9b58f63a9543eca2aadcab40d
7
+ data.tar.gz: 51afecfd75ac23a5820538cd6c1914d48aeba21fea5e2b8f07a2bb193f4474329b9a6723c43addb5bcfc24642d3ca96c6efd7883ce1762ecc2ee57598f495461
@@ -0,0 +1,52 @@
1
+ ---
2
+ ###########################
3
+ ###########################
4
+ ## Linter GitHub Actions ##
5
+ ###########################
6
+ ###########################
7
+ name: Lint Code Base
8
+
9
+ #
10
+ # Documentation:
11
+ # https://help.github.com/en/articles/workflow-syntax-for-github-actions
12
+ #
13
+
14
+ #############################
15
+ # Start the job on all push #
16
+ #############################
17
+ on:
18
+ pull_request:
19
+ branches: [master]
20
+
21
+ ###############
22
+ # Set the Job #
23
+ ###############
24
+ jobs:
25
+ build:
26
+ # Name the Job
27
+ name: Lint Code Base
28
+ # Set the agent to run on
29
+ runs-on: ubuntu-latest
30
+
31
+ ##################
32
+ # Load all steps #
33
+ ##################
34
+ steps:
35
+ ##########################
36
+ # Checkout the code base #
37
+ ##########################
38
+ - name: Checkout Code
39
+ uses: actions/checkout@v2
40
+ with:
41
+ # Full git history is needed to get a proper list of changed files within `super-linter`
42
+ fetch-depth: 0
43
+
44
+ ################################
45
+ # Run Linter against code base #
46
+ ################################
47
+ - name: Lint Code Base
48
+ uses: github/super-linter@v3
49
+ env:
50
+ VALIDATE_ALL_CODEBASE: false
51
+ DEFAULT_BRANCH: master
52
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,59 @@
1
+ name: Specs
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+
14
+ # Service containers to run with `runner-job`
15
+ services:
16
+ # Label used to access the service container
17
+ postgres:
18
+ # Docker Hub image
19
+ image: postgres
20
+ env:
21
+ POSTGRES_HOST_AUTH_METHOD: trust
22
+ POSTGRES_USER: runner
23
+ # Set health checks to wait until postgres has started
24
+ options: >-
25
+ --health-cmd pg_isready
26
+ --health-interval 10s
27
+ --health-timeout 5s
28
+ --health-retries 5
29
+ ports:
30
+ # Maps tcp port 5432 on service container to the host
31
+ - 5432:5432
32
+
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ include:
37
+ - ruby-version: 3.0
38
+ gemfile: Gemfile
39
+ - ruby-version: 2.5
40
+ gemfile: gemfiles/maintained.gemfile
41
+ - ruby-version: 2.4.0
42
+ gemfile: gemfiles/minimum.gemfile
43
+
44
+
45
+ env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
46
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
47
+ COVERAGE: ${{ matrix.gemfile == 'Gemfile' }}
48
+
49
+ steps:
50
+ - uses: actions/checkout@v2
51
+ - name: Set up Ruby
52
+ uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: ${{ matrix.ruby-version }}
55
+ bundler-cache: true
56
+ - name: Install dependencies
57
+ run: bundle install
58
+ - name: Run tests
59
+ run: bundle exec rake
data/.yardopts CHANGED
@@ -1 +1,3 @@
1
1
  --markup markdown
2
+ -
3
+ CHANGELOG.md
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
- ## [Unreleased]
1
+ # Change Log
2
2
 
3
- ## [0.1.0] - 2021-02-15
3
+ ## [0.6.5] - 2021-03-24
4
+
5
+ - Raises `Ensql::Error` with a more helpful message when `load_sql` can't find a file.
6
+
7
+ ## [0.6.4] - 2021-03-12
8
+
9
+ - Exposes `PostgresAdapter#query_type_map` to extend PG type mapping.
10
+ - Defers building type maps for PostgreSQL connections, to avoid bugs with ActiveRecord.
11
+
12
+ ## [0.6.3] - 2021-03-11
13
+
14
+ - Supports transaction flow control using any flavour SQL with `Ensql.transaction` and `Ensql.rollback!`.
15
+ - Eliminates cyclic dependencies for `Error` and `Ensql.adapter`.
16
+ - Tidies specs.
17
+ - Adopts [standardrb](https://github.com/testdouble/standard).
18
+
19
+ ## [0.6.2] - 2021-03-09
20
+
21
+ - Adds a specialised adapter for PostgreSQL.
22
+ - Uses instances instead of modules for SequelAdapter and ActiveRecordAdapter. The use of the (now) classes as adapters is deprecated.
23
+ - Adds connection pool wrappers for ActiveRecord and Sequel.
24
+ - Ensures SQL#each_row returns nil.
25
+ - Makes adapter attribute thread-safe.
26
+
27
+ ## [0.6.1] - 2021-02-25
28
+
29
+ - Enables the use of streaming with the SequelAdapter
30
+ - Improves performance of #first_row and #each_row
31
+ - Tests against Sequel 5.9
32
+
33
+ ## [0.6.0] - 2021-02-15
4
34
 
5
35
  - Initial release
data/Gemfile CHANGED
@@ -5,17 +5,11 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in ensql.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
9
-
10
- gem "rspec", "~> 3.0"
11
- # Ensure test coverage
12
- gem "simplecov", "~> 0.21.2"
13
-
14
- # Database adapters
15
- require_relative 'lib/ensql/version'
16
- gem "activerecord", ENV['ACTIVERECORD_VERSION'] || Ensql::ACTIVERECORD_VERSION
17
- gem "sequel", ENV['SEQUEL_VERSION'] || Ensql::SEQUEL_VERSION
18
- gem "sqlite3", ENV['SQLITE3_VERSION'] || "~> 1.4"
19
- gem "pg", ENV['PG_VERSION'] || "~> 1.2"
20
-
21
- gem "yard", "~> 0.9.26"
8
+ group :adapters do
9
+ require_relative "lib/ensql/version"
10
+ gem "activerecord", Ensql::SUPPORTED_ACTIVERECORD_VERSIONS
11
+ gem "sequel", Ensql::SUPPORTED_SEQUEL_VERSIONS
12
+ gem "sqlite3", "~> 1.4"
13
+ gem "pg", "~> 1.2"
14
+ gem "sequel_pg"
15
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ensql (0.6.0)
4
+ ensql (0.6.5)
5
+ connection_pool (>= 0.9.3, < 3)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -18,11 +19,12 @@ GEM
18
19
  tzinfo (~> 2.0)
19
20
  zeitwerk (~> 2.3)
20
21
  concurrent-ruby (1.1.8)
22
+ connection_pool (2.2.3)
21
23
  diff-lcs (1.4.4)
22
24
  docile (1.3.5)
23
25
  i18n (1.8.9)
24
26
  concurrent-ruby (~> 1.0)
25
- minitest (5.14.3)
27
+ minitest (5.14.4)
26
28
  pg (1.2.3)
27
29
  rake (13.0.3)
28
30
  rspec (3.10.0)
@@ -39,6 +41,9 @@ GEM
39
41
  rspec-support (~> 3.10.0)
40
42
  rspec-support (3.10.2)
41
43
  sequel (5.41.0)
44
+ sequel_pg (1.14.0)
45
+ pg (>= 0.18.0, != 1.2.0)
46
+ sequel (>= 4.38.0)
42
47
  simplecov (0.21.2)
43
48
  docile (~> 1.1)
44
49
  simplecov-html (~> 0.11)
@@ -53,6 +58,7 @@ GEM
53
58
 
54
59
  PLATFORMS
55
60
  x86_64-darwin-18
61
+ x86_64-linux
56
62
 
57
63
  DEPENDENCIES
58
64
  activerecord (>= 5.0, < 6.2)
@@ -60,7 +66,8 @@ DEPENDENCIES
60
66
  pg (~> 1.2)
61
67
  rake (~> 13.0)
62
68
  rspec (~> 3.0)
63
- sequel (~> 5.10)
69
+ sequel (~> 5.9)
70
+ sequel_pg
64
71
  simplecov (~> 0.21.2)
65
72
  sqlite3 (~> 1.4)
66
73
  yard (~> 0.9.26)
data/README.md CHANGED
@@ -1,38 +1,41 @@
1
1
  # Ensql
2
2
 
3
- Ensql lets you write SQL for your application the safe and simple way. Ditch your ORM and embrace the power and
4
- simplicity of writing plain SQL again.
3
+ [![Gem Version](https://badge.fury.io/rb/ensql.svg)](https://badge.fury.io/rb/ensql)
4
+ [![Ruby](https://github.com/danielfone/ensql/actions/workflows/specs.yml/badge.svg)](https://github.com/danielfone/ensql/actions/workflows/specs.yml)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a4ab07e1a03c4d1e8043/maintainability)](https://codeclimate.com/github/danielfone/ensql/maintainability)
6
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
5
7
 
6
- * **Write exactly the SQL you want.** Don't limit your queries to what's in the Rails docs. Composable scopes and
7
- dynamic includes can cripple performance for non-trivial queries. Break through the ORM abstraction and unlock the
8
- power of your database with well-structured SQL and modern database features.
8
+ Ensql provides a light-weight wrapper over your existing database connections, letting you write plain SQL for your
9
+ application safely and simply. Escape your ORM and embrace the power and ease of writing SQL again.
9
10
 
10
- * **Keep your SQL in its own files.** Just like models or view templates, it makes sense to organise your SQL on its
11
- own terms. Storing the queries in their own files encourages better formatted, well commented, literate SQL. It also
12
- leverages the syntax highlighting and autocompletion available in your editor. Snippets of HTML scatter through .rb
13
- files is an awkward code smell, and SQL is no different.
11
+ * **Write exactly the SQL you want.** Don't limit your queries to what's in the Rails docs. Composable scopes and
12
+ dynamic includes can cripple performance for non-trivial queries. Break through the ORM abstraction and unlock the
13
+ power of your database with well-structured SQL and modern database features.
14
14
 
15
- * **Do more with your database.** Having a place to organise clean and readable SQL encourages you to make the most of it.
16
- In every project I've worked on I've been able to replace useful amounts of imperative ruby logic with a declarative
17
- SQL query, improving performance and reducing the opportunity for type errors and untested branches.
15
+ * **Keep your SQL in its own files.** Just like models or view templates, it makes sense to organise your SQL on its
16
+ own terms. Storing the queries in their own files encourages better formatted, well commented, literate SQL. It also
17
+ leverages the syntax highlighting and autocompletion available in your editor. Snippets of HTML scattered through .rb
18
+ files is an awkward code smell, and SQL is no different.
18
19
 
19
- * **Safely interpolate user-supplied data.** Every web developer knows the risks of SQL injection. Ensql takes a
20
- fail-safe approach to interpolation, leveraging the underlying database adapter to turn ruby objects into properly
21
- quoted SQL literals. As long as user-supplied input is passed as parameters, your queries will be safe and
22
- well-formed.
20
+ * **Do more with your database.** Having a place to organise clean and readable SQL encourages you to make the most of
21
+ it. In every project I've worked on I've been able to replace substantial amounts of imperative Ruby logic with a
22
+ declarative SQL query, improving performance and reducing the opportunity for type errors and untested branches.
23
23
 
24
- * **Use your existing database connection.** Ensql works with ActiveRecord or Sequel so you don't need to manage a
25
- separate connection to the database.
24
+ * **Safely interpolate user-supplied data.** Every web developer knows the risks of SQL injection. Ensql takes a
25
+ fail-safe approach to interpolation, leveraging the underlying database adapter to turn ruby objects into properly
26
+ quoted SQL literals. As long as user-supplied input is passed as parameters, your queries will be safe and
27
+ well-formed.
26
28
 
27
- ```ruby
28
- # Run adhoc statements
29
- Ensql.run("SET TIME ZONE 'UTC'")
29
+ * **Use your existing database connection.** As well as using PostrgeSQL connections directly, Ensql can work with
30
+ ActiveRecord or Sequel so you don't need to manage a separate connection to the database.
30
31
 
31
- # Run adhoc D/U/I statements and get the affected row count
32
- Ensql.sql('DELETE FROM logs WHERE timestamp < %{expiry}', expiry: 1.month.ago).count # => 100
32
+ ```ruby
33
+ # Safely interpolate parameters into adhoc statements with correct quoting and escaping.
34
+ Ensql.run("INSERT INTO users (email) VALUES (%{email})", email: params[:email])
35
+ Ensql.sql("DELETE FROM logs WHERE timestamp < %{expiry}", expiry: 1.month.ago).count # => 100
33
36
 
34
- # Organise your SQL and fetch results as convenient Ruby primitives
35
- Ensql.sql_path = 'app/sql'
37
+ # Organise your SQL and fetch results as convenient Ruby primitives.
38
+ Ensql.sql_path = 'app/sql' # Defaults to './sql'. This can be set in an initializer or similar.
36
39
  Ensql.load_sql('customers/revenue_report', params).rows # => [{ "customer_id" => 100, "revenue" => 1000}, … ]
37
40
 
38
41
  # Easily retrive results in the simplest shape
@@ -46,59 +49,87 @@ current_results = Ensql.load_sql('results/page', results: all_results, page: 2)
46
49
  total = Ensql.load_sql('count', subquery: all_results)
47
50
  result = { data: current_results.rows, total: total.first_field }
48
51
  ```
52
+ Links:
53
+
54
+ * [Source Code](https://github.com/danielfone/ensql)
55
+ * [API Documentation](https://rubydoc.info/gems/ensql)
56
+ * [Ruby Gem](https://rubygems.org/gems/ensql)
49
57
 
50
58
  ## Installation
51
59
 
52
60
  Add this gem to your Gemfile by running:
53
61
 
54
- $ bundle add ensql
55
-
62
+ ```shell
63
+ bundle add ensql
64
+ ```
56
65
  Or install it manually with:
57
66
 
58
- $ gem install ensql
67
+ ```shell
68
+ gem install ensql
69
+ ```
70
+ Ensql requires:
71
+
72
+ * ruby >= 2.4.0
73
+ * sequel >= 5.9 if using SequelAdapter
74
+ * activerecord >= 5.0 if using ActiveRecordAdapter
75
+ * pg >= 0.19 if using PostgresAdapter
59
76
 
60
77
  ## Usage
61
78
 
62
79
  Typically, you don't need to configure anything. Ensql will look for Sequel or ActiveRecord (in that order) and load the
63
- appropriate adapter. You can override this if you need to, or configure your own adapter. See {Ensql::Adapter} for
64
- details of the interface.
80
+ appropriate adapter. You can override this if the wrong adapter is autoconfigured, or if you're using PostgreSQL and
81
+ want to use the much faster and more convenient PostgresAdapter.
65
82
 
66
83
  ```ruby
67
- Ensql.adapter = Ensql::ActiveRecordAdapter # Will use ActiveRecord instead
84
+ # Use ActiveRecord instead of Sequel if both are available
85
+ Ensql.adapter = Ensql::ActiveRecordAdapter.new
86
+
87
+ # Use the PostgreSQL specific adapter, with ActiveRecord's connection pool
88
+ Ensql.adapter = Ensql::PostgresAdapter.new Ensql::ActiveRecordAdapter.pool
89
+
90
+ # Use the PostgreSQL specific adapter, with Sequel's connection pool
91
+ DB = Sequel.connect(ENV['DATABASE_URL'])
92
+ Ensql.adapter = Ensql::PostgresAdapter.new Ensql::SequelAdapter.pool(DB)
93
+
94
+ # Use the PostgreSQL specific adapter, with our own thread-safe connection pool
95
+ Ensql.adapter = Ensql::PostgresAdapter.pool { PG.connect ENV['DATABASE_URL'] }
68
96
  ```
97
+ You can also supply your own adapter (see [the API docs](https://rubydoc.info/gems/ensql/Ensql/Adapter) for details of the interface).
69
98
 
70
99
  SQL can be supplied directly or read from a file. You're encouraged to organise all but the most trivial statements in
71
100
  their own *.sql files, for the reasons outlined above. You can organise them in whatever way makes most sense for your
72
101
  project, but I've found sorting them into directories based on their purpose works well. For example:
73
102
 
74
- app/sql
75
- ├── analytics
76
- │   └── results.sql
77
- ├── program_details
78
- │   ├── widget_query.sql
79
- │   ├── item_query.sql
80
- │   ├── organisation_query.sql
81
- │   └── test_query.sql
82
- ├── reports
83
- │   ├── csv_export.sql
84
- │   ├── filtered.sql
85
- │   └── index.sql
86
- ├── redaction.sql
87
- ├── count.sql
88
- └── set_timeout.sql
103
+ ```text
104
+ app/sql
105
+ ├── analytics
106
+ │   └── results.sql
107
+ ├── program_details
108
+ │   ├── widget_query.sql
109
+ │   ├── item_query.sql
110
+ │   ├── organisation_query.sql
111
+ │   └── test_query.sql
112
+ ├── reports
113
+ │   ├── csv_export.sql
114
+ │   ├── filtered.sql
115
+ │   └── index.sql
116
+ ├── redaction.sql
117
+ ├── count.sql
118
+ └── set_timeout.sql
119
+ ```
89
120
 
90
121
  ### Interpolation
91
122
 
92
123
  All interpolation is marked by `%{}` placeholders in the SQL. This is the only place that user-supplied input should be
93
- allowed. Only various forms of literal interpolation are supported - identifier interpolation is not supported at this
94
- stage.
124
+ allowed. Only literal interpolation is supported - identifier interpolation is not supported at this stage.
95
125
 
96
- There are 4 types of interpolation, see {Ensql::SQL} for details.
126
+ There are 3 types of safe (correctly quoted/escaped) interpolation:
97
127
 
98
- 1. `%{param}` interpolates a Ruby object as a SQL literal.
99
- 2. `%{(param)}` expands an array into a list of SQL literals.
100
- 3. `%{param( nested sql )}` interpolates the nested sql with each hash in an array.
101
- 4. `%{!sql_param}` only interpolates Ensql::SQL objects as SQL fragments.
128
+ 1. `%{param}` interpolates a Ruby object as a single SQL literal.
129
+ 2. `%{(param)}` expands a Ruby Array into a list of SQL literals.
130
+ 3. `%{param( nested sql )}` interpolates an Array of Hashes into the nested sql with each hash in an array.
131
+
132
+ In addition you can interpolate raw SQL with `%{!sql_param}`. It's up to you to ensure this is safe!
102
133
 
103
134
  ```ruby
104
135
  # Interpolate a literal
@@ -115,12 +146,12 @@ Ensql.sql('INSERT INTO users (name, created_at) VALUES %{users( %{name}, now() )
115
146
  )
116
147
  # INSERT INTO users VALUES ('Claudia Buss', now()), ('Lundy L''Anglais', now())
117
148
 
118
- # Interpolate a SQL fragement
149
+ # Interpolate a raw SQL fragment without quoting. Use with care!
119
150
  Ensql.sql('SELECT * FROM users ORDER BY %{!orderby}', orderby: Ensql.sql('name asc'))
120
151
  # SELECT * FROM users ORDER BY name asc
121
152
  ```
122
153
 
123
- Interpolation occurs just before the SQL is executed.
154
+ See [the API docs](https://rubydoc.info/gems/ensql/Ensql/SQL) for details.
124
155
 
125
156
  ### Results
126
157
 
@@ -155,6 +186,22 @@ Ensql.sql('TRUNCATE logs').run # => nil
155
186
  Ensql.run('TRUNCATE logs') # same thing
156
187
  ```
157
188
 
189
+ ### Transactions
190
+
191
+ Ensql encourages you to write pure unmediated SQL with very little procedural management. However, transaction blocks
192
+ are the exception to this rule. Any exceptions inside a transaction block will trigger a rollback, otherwise the block
193
+ will be committed. The block uses SQL-standard commands by default, but custom SQL can be supplied.
194
+
195
+ ```ruby
196
+ Ensql.transaction(start: 'BEGIN ISOLATION LEVEL SERIALIZABLE') do
197
+ do_thing1
198
+ result = check_thing2
199
+ Ensql.rollback! unless result
200
+ do_thing3
201
+ end
202
+ ```
203
+ See [the API docs](https://rubydoc.info/gems/ensql/Ensql#transaction-class_method) for details.
204
+
158
205
  ## Things To Improve
159
206
 
160
207
  - Interpolation syntax. I'd love to ground this in something more reasonable than ruby's custom sprintf format. Maybe we
@@ -163,25 +210,38 @@ Ensql.run('TRUNCATE logs') # same thing
163
210
  - Maybe we could use type hinting like `%{param:pgarray}` to indicated how to serialise the object as a literal.
164
211
 
165
212
  - Detecting the database and switching to a db specific adapters. This allows us to be more efficient and optimise some
166
- literals in a database specific format, e.g. postgres array literals.
213
+ literals in a database specific format, e.g. PostgreSQL array literals.
167
214
 
168
- - Handling specific connections rather than just grabbing the default.
169
-
170
- - Establishing connections directly.
215
+ - Proper single-row mode support for the pg adapter
171
216
 
172
217
  ## Development
173
218
 
174
219
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You'll
175
- need a running postgres database. You can also run `bin/console` for an interactive prompt that will allow you to
220
+ need a running PostgreSQL database. You can also run `bin/console` for an interactive prompt that will allow you to
176
221
  experiment.
177
222
 
178
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
179
- version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
180
- push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
223
+ To install this gem onto your local machine, run `bundle exec rake install`.
224
+
225
+ ### PR Checklist
226
+
227
+ - [ ] Confirm the code works locally
228
+ - [ ] Update any relevant documentation
229
+ - [ ] Try to break it
230
+ - [ ] Tests the described behaviour
231
+ - [ ] Add a changelog entry (with version bump if needed)
232
+
233
+ ### Release Checklist
234
+
235
+ - [ ] Review changes in master since last release, especially the public API.
236
+ - [ ] Ensure documentation is up to date.
237
+ - [ ] Bump appropriate part of version in `version.rb`.
238
+ - [ ] Update the spec version in each `.lock`.
239
+ - [ ] Update `Changelog.md` with summary of new version.
240
+ - [ ] Run `rake release` to create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
181
241
 
182
242
  ## Contributing
183
243
 
184
- Bug reports and pull requests are welcome on GitHub at https://github.com/danielfone/ensql.
244
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/danielfone/ensql>.
185
245
 
186
246
  ## License
187
247