db_mod 0.0.2 → 0.0.3
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/CHANGELOG.md +14 -0
- data/README.md +20 -0
- data/lib/db_mod/as.rb +38 -0
- data/lib/db_mod/as/csv.rb +37 -0
- data/lib/db_mod/statements.rb +38 -0
- data/lib/db_mod/statements/configurable_method.rb +41 -0
- data/lib/db_mod/statements/prepared.rb +4 -5
- data/lib/db_mod/statements/statement.rb +3 -5
- data/lib/db_mod/version.rb +1 -1
- data/spec/db_mod/as/csv_spec.rb +36 -0
- data/spec/db_mod/as_spec.rb +14 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fe4bb1c7e19c817bad5e788d2cd626ce909ba0d
|
4
|
+
data.tar.gz: 3bb72d90d2387e7f8e7373f41d390f779b0cc819
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9318f1de5b1fe4c8189c7bc1d03cb42533316175411bb33440824e0051dd33da5c4c64595658e95d001b8995fca4fa4e4c67d24570e229e48418d4cfd346f5e
|
7
|
+
data.tar.gz: fe369f08a3c480d4c5d3322c35b575ecccb5cbada2b7db33f5b05a3fd692ad5d17cbc9580fabf2356e936b7886d28d1cc7d322e605ad3f6f3f2b04ad5523fa1e
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
0.0.3 (2015-10-13)
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Configurable method framework. Adds `def_prepared/statement.as(:csv)` - [@dslh](https://github.com/dslh)
|
5
|
+
|
6
|
+
0.0.2 (2015-10-12)
|
7
|
+
==================
|
8
|
+
|
9
|
+
* Adds `def_statement` to compliment `def_prepared` - [@dslh](https://github.com/dslh).
|
10
|
+
|
11
|
+
0.0.1 (2015-10-11)
|
12
|
+
==================
|
13
|
+
|
14
|
+
* Initial release - [@dslh](https://github.com/dslh).
|
data/README.md
CHANGED
@@ -183,3 +183,23 @@ Db::ComplicatedStuff.prepare_all_statements my_conn
|
|
183
183
|
the SQL queries are saved in memory rather than being sent to the database
|
184
184
|
at connection time. This is useful for queries that will only be run once
|
185
185
|
or twice during a program's execution.
|
186
|
+
|
187
|
+
#### Configuring defined statements
|
188
|
+
|
189
|
+
`db_mod` contains a simple framework for extending these statement methods
|
190
|
+
and prepared methods with additional argument and result processing. For
|
191
|
+
now only `.as(:csv)` is supported, which will cause the method to format
|
192
|
+
the SQL result set as a CSV string.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
module CsvReports
|
196
|
+
include DbMod
|
197
|
+
|
198
|
+
def_prepared(:foo, 'SELECT a, b FROM foo WHERE bar_id = $id').as(:csv)
|
199
|
+
end
|
200
|
+
|
201
|
+
include CsvReports
|
202
|
+
db_connect db: 'testdb'
|
203
|
+
|
204
|
+
foo(id: 1) # => "a,b\n1,2\n3,4\n..."
|
205
|
+
```
|
data/lib/db_mod/as.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'as/csv'
|
2
|
+
|
3
|
+
module DbMod
|
4
|
+
# Contains coercers and other functions that allow
|
5
|
+
# module instance methods returning an SQL result set
|
6
|
+
# to be extended with additional result coercion and
|
7
|
+
# formatting. The normal way to access this functionality
|
8
|
+
# is via {DbMod::Statements::ConfigurableMethod#as},
|
9
|
+
# which is available when defining a statement method
|
10
|
+
# or prepared method:
|
11
|
+
#
|
12
|
+
# def_statement(:a, 'SELECT a, b, c FROM foo').as(:csv)
|
13
|
+
# def_prepared(:b, 'SELECT d, e, f FROM bar').as(:csv)
|
14
|
+
module As
|
15
|
+
# List of available result coercion methods.
|
16
|
+
# Only keys defined here are allowed as arguments
|
17
|
+
# to {DbMod::Statements::ConfigurableMethod#as}.
|
18
|
+
COERCERS = {
|
19
|
+
csv: DbMod::As::Csv
|
20
|
+
}
|
21
|
+
|
22
|
+
# Extend a method so that the SQL result set it
|
23
|
+
# returns will be coerced to the given type.
|
24
|
+
# See {COERCERS} for a list of defined coercion
|
25
|
+
# methods.
|
26
|
+
#
|
27
|
+
# @param mod [Module] module where the method has been defined
|
28
|
+
# @param name [Symbol] method name
|
29
|
+
# @param type [Symbol] type to which result set should be coerced
|
30
|
+
def self.extend_method(mod, name, type)
|
31
|
+
unless COERCERS.key? type
|
32
|
+
fail ArgumentError, "#{type} not in #{COERCERS.keys.join ', '}"
|
33
|
+
end
|
34
|
+
|
35
|
+
Statements.extend_method(mod, name, COERCERS[type])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DbMod
|
2
|
+
module As
|
3
|
+
# Coercer which converts an SQL result set
|
4
|
+
# into a string formatted as a CSV document.
|
5
|
+
# May be enabled for a prepared method or
|
6
|
+
# statement method using +.as(:csv)+:
|
7
|
+
#
|
8
|
+
# def_statement(:a, 'SELECT a, b FROM foo').as(:csv)
|
9
|
+
# def_prepared(:b, 'SELECT b, c FROM bar').as(:csv)
|
10
|
+
#
|
11
|
+
# def do_stuff
|
12
|
+
# a # => "a,b\r\n1,2\r\n3,4\r\n..."
|
13
|
+
# end
|
14
|
+
module Csv
|
15
|
+
# Enables this module to be passed to {DbMod::Statements.extend_method}
|
16
|
+
# as the +wrapper+ function, in which case it will retrieve the results
|
17
|
+
# and format them as a CSV document using the column names from the
|
18
|
+
# result set.
|
19
|
+
#
|
20
|
+
# @param wrapped_method [Method] the method that has been wrapped
|
21
|
+
# @param args [*] arguments expected to be passed to the wrapped method
|
22
|
+
# @return [String] a CSV formatted document
|
23
|
+
def self.call(wrapped_method, *args)
|
24
|
+
results = wrapped_method.call(*args)
|
25
|
+
|
26
|
+
headers = nil
|
27
|
+
CSV.generate do |csv|
|
28
|
+
results.each do |row|
|
29
|
+
csv << (headers = row.keys) unless headers
|
30
|
+
|
31
|
+
csv << headers.map { |col| row[col] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/db_mod/statements.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require_relative 'statements/configurable_method'
|
1
2
|
require_relative 'statements/statement'
|
2
3
|
require_relative 'statements/prepared'
|
3
4
|
|
@@ -15,5 +16,42 @@ module DbMod
|
|
15
16
|
DbMod::Statements::Prepared.setup(mod)
|
16
17
|
DbMod::Statements::Statement.setup(mod)
|
17
18
|
end
|
19
|
+
|
20
|
+
# Used by submodules to when defining a method as declared by
|
21
|
+
# +def_statement+ or +def_prepared+. Wraps the defined method
|
22
|
+
# so that it may be extended with additional argument and
|
23
|
+
# result processing.
|
24
|
+
#
|
25
|
+
# @param mod [Module] the module where the method has been declared
|
26
|
+
# @param name [Symbol] the name of the module that has been defined
|
27
|
+
# @param definition [Proc] method definition
|
28
|
+
# @return [DbMod::Statements::ConfigurableMethod] dsl object for
|
29
|
+
# further extending the method
|
30
|
+
def self.configurable_method(mod, name, definition)
|
31
|
+
mod.instance_eval { define_method(name, definition) }
|
32
|
+
|
33
|
+
ConfigurableMethod.new(mod, name)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Used by {ConfigurableMethod} (and associated code) to wrap a defined
|
37
|
+
# statement method or prepared method with additional parameter or result
|
38
|
+
# processing. A wrapper method definition should be provided, which will
|
39
|
+
# be called in place of the original method. It will be called with the
|
40
|
+
# original method proc as a first argument followed by the original
|
41
|
+
# method arguments (before +DbMod+ has made any attempt to validate them!).
|
42
|
+
# It is expected to yield to the original proc at some point, although it
|
43
|
+
# is allowed to do whatever it wants with the results before returning them.
|
44
|
+
#
|
45
|
+
# @param mod [Module] the module where the method has been defined
|
46
|
+
# @param name [Symbol] the method name
|
47
|
+
# @param wrapper [Proc] a function which will be used to wrap the
|
48
|
+
# original method definition
|
49
|
+
def self.extend_method(mod, name, wrapper)
|
50
|
+
mod.instance_eval do
|
51
|
+
wrapped = instance_method(name)
|
52
|
+
|
53
|
+
define_method name, ->(*args) { wrapper.call wrapped.bind(self), *args }
|
54
|
+
end
|
55
|
+
end
|
18
56
|
end
|
19
57
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'db_mod/as'
|
2
|
+
|
3
|
+
module DbMod
|
4
|
+
module Statements
|
5
|
+
# Encapsulates a method that has just been defined
|
6
|
+
# via the dsl exposed in {DbMod::Statements} so that
|
7
|
+
# it can be extended with additional processing such
|
8
|
+
# as result coercion.
|
9
|
+
#
|
10
|
+
# The pattern here is something similar to rack's middleware.
|
11
|
+
# Calling any of the extension methods below will replace
|
12
|
+
# the original method defined by +def_prepared+ or +def_statement+
|
13
|
+
# with a wrapper function that may perform processing on given
|
14
|
+
# arguments, pass them to the original function, then perform
|
15
|
+
# additional processing on the result.
|
16
|
+
class ConfigurableMethod
|
17
|
+
# Encapsulate a method that has been newly defined
|
18
|
+
# by a {DbMod} dsl function, for additional configuration.
|
19
|
+
#
|
20
|
+
# @param mod [Module] the {DbMod} enabled module
|
21
|
+
# where the method was defined
|
22
|
+
# @param name [Symbol] the method name
|
23
|
+
def initialize(mod, name)
|
24
|
+
@mod = mod
|
25
|
+
@name = name
|
26
|
+
end
|
27
|
+
|
28
|
+
# Extend the method by converting results into a given
|
29
|
+
# format, using one of the coercion methods defined
|
30
|
+
# under {DbMod::As}.
|
31
|
+
#
|
32
|
+
# @param type [Symbol] for now, only :csv is accepted
|
33
|
+
# @return [self]
|
34
|
+
def as(type)
|
35
|
+
DbMod::As.extend_method(@mod, @name, type)
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -145,9 +145,8 @@ module DbMod
|
|
145
145
|
# @param name [Symbol] name of the method to be defined
|
146
146
|
# and the prepared query to be called.
|
147
147
|
def self.define_no_args_prepared_method(mod, name)
|
148
|
-
|
149
|
-
|
150
|
-
end
|
148
|
+
method = ->() { conn.exec_prepared(name.to_s) }
|
149
|
+
Statements.configurable_method mod, name, method
|
151
150
|
end
|
152
151
|
|
153
152
|
# Define a method with the given name that accepts the
|
@@ -165,7 +164,7 @@ module DbMod
|
|
165
164
|
conn.exec_prepared(name.to_s, args)
|
166
165
|
end
|
167
166
|
|
168
|
-
|
167
|
+
Statements.configurable_method mod, name, method
|
169
168
|
end
|
170
169
|
|
171
170
|
# Define a method with the given name that accepts a fixed
|
@@ -186,7 +185,7 @@ module DbMod
|
|
186
185
|
conn.exec_prepared(name.to_s, args)
|
187
186
|
end
|
188
187
|
|
189
|
-
mod
|
188
|
+
Statements.configurable_method(mod, name, method)
|
190
189
|
end
|
191
190
|
|
192
191
|
# Adds +prepared_statements+ to a module. This list of named
|
@@ -83,9 +83,7 @@ module DbMod
|
|
83
83
|
# @param name [Symbol] name of the method to be defined
|
84
84
|
# @param sql [String] parameterless SQL statement to execute
|
85
85
|
def self.define_no_args_statement_method(mod, name, sql)
|
86
|
-
|
87
|
-
define_method name, ->() { query(sql) }
|
88
|
-
end
|
86
|
+
Statements.configurable_method mod, name, ->() { query(sql) }
|
89
87
|
end
|
90
88
|
|
91
89
|
# Define a method with the given name, that accepts the
|
@@ -101,7 +99,7 @@ module DbMod
|
|
101
99
|
conn.exec_params(sql, args)
|
102
100
|
end
|
103
101
|
|
104
|
-
|
102
|
+
Statements.configurable_method mod, name, method
|
105
103
|
end
|
106
104
|
|
107
105
|
# Define a method with the given name that accepts a fixed number
|
@@ -119,7 +117,7 @@ module DbMod
|
|
119
117
|
conn.exec_params(sql, args)
|
120
118
|
end
|
121
119
|
|
122
|
-
|
120
|
+
Statements.configurable_method mod, name, method
|
123
121
|
end
|
124
122
|
end
|
125
123
|
end
|
data/lib/db_mod/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
describe DbMod::As::Csv do
|
5
|
+
subject do
|
6
|
+
Module.new do
|
7
|
+
include DbMod
|
8
|
+
|
9
|
+
def_statement(:statement, 'SELECT a, b FROM foo').as(:csv)
|
10
|
+
def_prepared(:prepared, 'SELECT c, d FROM bar').as(:csv)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
before do
|
15
|
+
@conn = instance_double 'PGconn'
|
16
|
+
allow(@conn).to receive(:prepare)
|
17
|
+
allow(PGconn).to receive(:connect).and_return @conn
|
18
|
+
end
|
19
|
+
|
20
|
+
{
|
21
|
+
statement: :query,
|
22
|
+
prepared: :exec_prepared
|
23
|
+
}.each do |method_type, exec_type|
|
24
|
+
context "#{method_type} methods" do
|
25
|
+
it 'coerces results to csv' do
|
26
|
+
expect(@conn).to receive(exec_type).and_return([
|
27
|
+
{ 'a' => '1', 'b' => '2' },
|
28
|
+
{ 'a' => '3', 'b' => '4' }
|
29
|
+
])
|
30
|
+
|
31
|
+
csv = subject.create(db: 'testdb').send(method_type)
|
32
|
+
expect(csv).to eq("a,b\n1,2\n3,4\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# See submodules for more
|
4
|
+
describe DbMod::As do
|
5
|
+
it 'disallows unknown coercions' do
|
6
|
+
expect do
|
7
|
+
Module.new do
|
8
|
+
include DbMod
|
9
|
+
|
10
|
+
def_statement(:foo, 'SELECT 1').as(:lolwut)
|
11
|
+
end
|
12
|
+
end.to raise_exception ArgumentError
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: db_mod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doug Hammond
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -105,6 +105,7 @@ files:
|
|
105
105
|
- ".rspec"
|
106
106
|
- ".rubocop.yml"
|
107
107
|
- ".travis.yml"
|
108
|
+
- CHANGELOG.md
|
108
109
|
- CODE_OF_CONDUCT.md
|
109
110
|
- Gemfile
|
110
111
|
- Guardfile
|
@@ -113,6 +114,8 @@ files:
|
|
113
114
|
- Rakefile
|
114
115
|
- db_mod.gemspec
|
115
116
|
- lib/db_mod.rb
|
117
|
+
- lib/db_mod/as.rb
|
118
|
+
- lib/db_mod/as/csv.rb
|
116
119
|
- lib/db_mod/create.rb
|
117
120
|
- lib/db_mod/exceptions.rb
|
118
121
|
- lib/db_mod/exceptions/already_in_transaction.rb
|
@@ -120,11 +123,14 @@ files:
|
|
120
123
|
- lib/db_mod/exceptions/connection_not_set.rb
|
121
124
|
- lib/db_mod/exceptions/duplicate_statement_name.rb
|
122
125
|
- lib/db_mod/statements.rb
|
126
|
+
- lib/db_mod/statements/configurable_method.rb
|
123
127
|
- lib/db_mod/statements/parameters.rb
|
124
128
|
- lib/db_mod/statements/prepared.rb
|
125
129
|
- lib/db_mod/statements/statement.rb
|
126
130
|
- lib/db_mod/transaction.rb
|
127
131
|
- lib/db_mod/version.rb
|
132
|
+
- spec/db_mod/as/csv_spec.rb
|
133
|
+
- spec/db_mod/as_spec.rb
|
128
134
|
- spec/db_mod/create_spec.rb
|
129
135
|
- spec/db_mod/statements/prepared_spec.rb
|
130
136
|
- spec/db_mod/statements/statement_spec.rb
|
@@ -156,6 +162,8 @@ signing_key:
|
|
156
162
|
specification_version: 4
|
157
163
|
summary: Declarative, modular database library framework.
|
158
164
|
test_files:
|
165
|
+
- spec/db_mod/as/csv_spec.rb
|
166
|
+
- spec/db_mod/as_spec.rb
|
159
167
|
- spec/db_mod/create_spec.rb
|
160
168
|
- spec/db_mod/statements/prepared_spec.rb
|
161
169
|
- spec/db_mod/statements/statement_spec.rb
|