query_result_presenter 0.0.1
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 +15 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +11 -0
- data/lib/query_result_presenter.rb +115 -0
- data/lib/query_result_presenter/version.rb +3 -0
- data/query_result_presenter.gemspec +23 -0
- data/test/query_result_presenter_test.rb +87 -0
- data/test/test_helper.rb +8 -0
- metadata +87 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
YzM2NmIxZWVhNWRmZGFmODJlZWY4NjJhZjQzM2U2M2ZiZTE1MzdkZQ==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
NTdhZTcxNmMzNGVkMDdkMTllZmFjMmMzMjQ4MWEzMDdmNmI0ODU2Ng==
|
|
7
|
+
!binary "U0hBNTEy":
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
OGI4Nzc2ZDcxODQ0YjhhMTQ5MDA0MTRmMWFkYmMxMTA2YTJmMWNkMzIxNWMz
|
|
10
|
+
N2I4ZmRkNTAzYTg0YzMyYTBiNDdiZTMxZjc1OWU5MzQ4Yjc1NDQyNTBkMTI5
|
|
11
|
+
YjMyYTJlMDgzZWMyYTUxNGUxYmRhNjk2MWI4NzYxOGRiMmMzYmU=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
NzBmYTgxNDUxNjM3ZmY4ZjdmMDUzOWViZTA3Y2M2MWE1NzBlZTdiOWJkODll
|
|
14
|
+
NDNkMTM1MDU4NmQxMjRlY2MyNzJkNDc2OTkwZDg5YzBlMDZmNGM3OTNhMTQ2
|
|
15
|
+
YWJiNzcxNTc0Njg4ZWJmNmFiOTQ2YzNlYzU0MGEzMDM3ZDY0YWE=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2014 Solomon
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# QueryResultPresenter
|
|
2
|
+
|
|
3
|
+
[](https://codeclimate.com/github/paperlesspost/query_result_presenter)
|
|
4
|
+
|
|
5
|
+
This is a gem to deal with a variety of query results from the
|
|
6
|
+
various database adapters that run in ruby. Most of them (pg, mysql2)
|
|
7
|
+
natively return a query result in the form of an enumerable, with each
|
|
8
|
+
result being a hash with the column name and row value of the query.
|
|
9
|
+
|
|
10
|
+
This code adds functionality to the results of these
|
|
11
|
+
database adapters, and simplifies some common things you need for
|
|
12
|
+
query reporting, especially online.
|
|
13
|
+
|
|
14
|
+
This gem uses the decorator
|
|
15
|
+
pattern, so it adds some additional methods and delegates to the
|
|
16
|
+
original result for anything it doesn't recognize.
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Add this line to your application's Gemfile:
|
|
21
|
+
|
|
22
|
+
gem 'query_result_presenter'
|
|
23
|
+
|
|
24
|
+
And then execute:
|
|
25
|
+
|
|
26
|
+
$ bundle
|
|
27
|
+
|
|
28
|
+
Or install it yourself as:
|
|
29
|
+
|
|
30
|
+
$ gem install query_result_presenter
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
All you need to do is call `QueryResultPresenter::Presenter.new(result here)`
|
|
35
|
+
on any query result returned as a hash, and you will get these
|
|
36
|
+
additional methods. If you call an unrecognized method, it will
|
|
37
|
+
call that method on the original result object using `method_missing`.
|
|
38
|
+
|
|
39
|
+
This project started as `PgResultPresenter` to be used with a postgres
|
|
40
|
+
database that returnd `PgResult` objects to which we added
|
|
41
|
+
functionality. However, since we're open sourcing our BI app, and people
|
|
42
|
+
will likely use non-postgres db's, this gem is to extend that
|
|
43
|
+
functionality beyond just postgres.
|
|
44
|
+
|
|
45
|
+
So, the `(result here)` that you load into the presenter will be a result
|
|
46
|
+
from `pg`, `mysql2`, or another db connection library. The results can
|
|
47
|
+
be different types /
|
|
48
|
+
classes, but most conform to the same format which allows this gem to
|
|
49
|
+
work.
|
|
50
|
+
|
|
51
|
+
The format needed for this to work is for results to be returned as
|
|
52
|
+
hashes, this will not work for query results
|
|
53
|
+
returned as an array. Most libraries return results as hashes by
|
|
54
|
+
default, or you are able to change the configuration in the library to
|
|
55
|
+
return the result as a hash.
|
|
56
|
+
|
|
57
|
+
The additional functions you get are:
|
|
58
|
+
|
|
59
|
+
`to_html_table` turns the query result to an html table
|
|
60
|
+
|
|
61
|
+
`to_csv_data` gives you a csv string
|
|
62
|
+
|
|
63
|
+
`to_csv_file(filename)` saves a csv file of filename. Will overwrite
|
|
64
|
+
previous files
|
|
65
|
+
|
|
66
|
+
`headers` gets you the headers of the query result (column names)
|
|
67
|
+
|
|
68
|
+
`field_values(column)` gets you the values of an individual column as an
|
|
69
|
+
array
|
|
70
|
+
|
|
71
|
+
`first_result_row` gets you the first row of the result
|
|
72
|
+
|
|
73
|
+
`has_results?` returns true if there are results
|
|
74
|
+
|
|
75
|
+
`result_count` returns the number of results
|
|
76
|
+
|
|
77
|
+
## Contributing
|
|
78
|
+
|
|
79
|
+
1. Fork it
|
|
80
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
81
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
82
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
83
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require "query_result_presenter/version"
|
|
2
|
+
require 'csv'
|
|
3
|
+
|
|
4
|
+
# This is a module to deal with a variety of query results from the
|
|
5
|
+
# various database adapters that run in ruby. Most of them (pg, mysql2)
|
|
6
|
+
# natively return a query result in the form of an enumerable, with each
|
|
7
|
+
# result being a hash with the column name and row value of the query.
|
|
8
|
+
#
|
|
9
|
+
# This code is to allow you to add functionality to the results of these
|
|
10
|
+
# database adapters, and automate certain common things you need for
|
|
11
|
+
# query reporting, especially online.
|
|
12
|
+
module QueryResultPresenter
|
|
13
|
+
class Presenter
|
|
14
|
+
attr_reader :result
|
|
15
|
+
|
|
16
|
+
def initialize(result)
|
|
17
|
+
@result = result
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Get the csv data in the form of a string
|
|
21
|
+
# @return [String]
|
|
22
|
+
def to_csv_data
|
|
23
|
+
has_results? ? csv_data : ""
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Saves a query result to file. Will overwrite any file with the
|
|
27
|
+
# same name
|
|
28
|
+
# @param [String] filename the name of the file eg 'file.csv'
|
|
29
|
+
def to_csv_file(filename)
|
|
30
|
+
File.open(filename, "w"){ |f| f.puts csv_data }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns the query result as an html table string
|
|
34
|
+
# @return [String]
|
|
35
|
+
def to_html_table
|
|
36
|
+
html_table = "<table>"
|
|
37
|
+
html_table << add_html_row(headers)
|
|
38
|
+
@result.each do |row|
|
|
39
|
+
html_table << add_html_row(row.values)
|
|
40
|
+
end
|
|
41
|
+
html_table << "</table>"
|
|
42
|
+
html_table
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the column names from the query result
|
|
46
|
+
# @return [Array]
|
|
47
|
+
def headers
|
|
48
|
+
@result.first.keys
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Gets the values in every row for a specific column
|
|
52
|
+
# @param [String] column_name
|
|
53
|
+
# @return [Array]
|
|
54
|
+
def field_values(column_name)
|
|
55
|
+
@result.to_a.map{ |r| r[column_name] }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Gets the first row from the query result
|
|
59
|
+
# @return [Array]
|
|
60
|
+
def first_result_row
|
|
61
|
+
@result.first.values
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Does this query have any results?
|
|
65
|
+
# @return [Boolean]
|
|
66
|
+
def has_results?
|
|
67
|
+
result_count > 0
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# How many rows are in the query result
|
|
71
|
+
# @return [Integer]
|
|
72
|
+
def result_count
|
|
73
|
+
@result.count
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Will delegate to the underlying object if a method can't be found
|
|
77
|
+
def method_missing(method, *args, &block)
|
|
78
|
+
@result.send(method, *args, &block)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Will be true if either this class or the underlying object
|
|
82
|
+
# responds to a method, false otherwise
|
|
83
|
+
# @return [Boolean]
|
|
84
|
+
def respond_to?(method, include_private = false)
|
|
85
|
+
super || @result.respond_to?(method, include_private)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
# Returns an array as an html row
|
|
91
|
+
# @param [Array] row_data the array you want to turn into a row
|
|
92
|
+
# @return [String]
|
|
93
|
+
def add_html_row(row_data)
|
|
94
|
+
row = "<tr>"
|
|
95
|
+
row_data.each do |d|
|
|
96
|
+
row << "<td>#{d}</td>"
|
|
97
|
+
end
|
|
98
|
+
row << "</tr>"
|
|
99
|
+
row
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Get the csv data in the form of a string
|
|
103
|
+
# @return [String]
|
|
104
|
+
def csv_data
|
|
105
|
+
csv_data = CSV.generate do |csv|
|
|
106
|
+
csv << headers
|
|
107
|
+
@result.each do |r|
|
|
108
|
+
csv << r.values
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
csv_data
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'query_result_presenter/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "query_result_presenter"
|
|
8
|
+
spec.version = QueryResultPresenter::VERSION
|
|
9
|
+
spec.authors = ["Solomon"]
|
|
10
|
+
spec.email = ["solomon.kahn@gmail.com"]
|
|
11
|
+
spec.description = %q{Works with query results in hash form. In particular, made to work with the pg gem, but will also work with any query result represented as a hash.}
|
|
12
|
+
spec.summary = %q{Adds some functionality to query results using the presenter pattern. Delegates to the underlying object using method missing for a non-recognized method.}
|
|
13
|
+
spec.homepage = "https://www.github.com/paperless-post/query_result_presenter"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class QueryResultPresenterTest < Test::Unit::TestCase
|
|
4
|
+
context "Query Result Presenter" do
|
|
5
|
+
setup do
|
|
6
|
+
@result = [
|
|
7
|
+
{"column1" => "row1", "column2" => "row1"},
|
|
8
|
+
{"column1" => "row2", "column2" => "row2"},
|
|
9
|
+
{"column1" => "row3", "column2" => "row3"}
|
|
10
|
+
]
|
|
11
|
+
@presenter = QueryResultPresenter::Presenter.new(@result)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "headers" do
|
|
15
|
+
should "have the correct headers" do
|
|
16
|
+
headers = ["column1", "column2"]
|
|
17
|
+
assert_equal(headers, @presenter.headers)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "first_result_row" do
|
|
22
|
+
should "have the correct result row" do
|
|
23
|
+
assert_equal(["row1", "row1"], @presenter.first_result_row)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "to_html_table" do
|
|
28
|
+
should "show correct table" do
|
|
29
|
+
table = "<table><tr><td>column1</td><td>column2</td></tr><tr><td>row1</td><td>row1</td></tr><tr><td>row2</td><td>row2</td></tr><tr><td>row3</td><td>row3</td></tr></table>"
|
|
30
|
+
assert_equal(table, @presenter.to_html_table)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "to_csv_data" do
|
|
35
|
+
should "return csv data in the form of a string" do
|
|
36
|
+
csv = "column1,column2\nrow1,row1\nrow2,row2\nrow3,row3\n"
|
|
37
|
+
assert_equal(csv, @presenter.to_csv_data)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "field_values" do
|
|
42
|
+
should "have the correct field values" do
|
|
43
|
+
assert_equal(["row1", "row2", "row3"], @presenter.field_values('column2'))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "has_results?" do
|
|
48
|
+
should "return true when there are results" do
|
|
49
|
+
assert_equal(true, @presenter.has_results?)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "result_count" do
|
|
54
|
+
should "return the correct number of results" do
|
|
55
|
+
assert_equal(3, @presenter.result_count)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "method_missing" do
|
|
60
|
+
should "delegate to the underlying result if method is missing" do
|
|
61
|
+
@result.expects(:to_a)
|
|
62
|
+
@presenter.to_a
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
should "raise an error when calling an unknown method" do
|
|
66
|
+
assert_raise NoMethodError do
|
|
67
|
+
@presenter.not_a_method
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "respond_to?" do
|
|
73
|
+
should "be true for presenter methods" do
|
|
74
|
+
assert @presenter.respond_to?(:headers)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
should "be true for underlying methods" do
|
|
78
|
+
assert @presenter.respond_to?(:to_a)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
should "be false for unknown methods" do
|
|
82
|
+
refute @presenter.respond_to?(:not_a_method)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: query_result_presenter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Solomon
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-05-05 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.3'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ! '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ! '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
description: Works with query results in hash form. In particular, made to work with
|
|
42
|
+
the pg gem, but will also work with any query result represented as a hash.
|
|
43
|
+
email:
|
|
44
|
+
- solomon.kahn@gmail.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- .gitignore
|
|
50
|
+
- Gemfile
|
|
51
|
+
- LICENSE.txt
|
|
52
|
+
- README.md
|
|
53
|
+
- Rakefile
|
|
54
|
+
- lib/query_result_presenter.rb
|
|
55
|
+
- lib/query_result_presenter/version.rb
|
|
56
|
+
- query_result_presenter.gemspec
|
|
57
|
+
- test/query_result_presenter_test.rb
|
|
58
|
+
- test/test_helper.rb
|
|
59
|
+
homepage: https://www.github.com/paperless-post/query_result_presenter
|
|
60
|
+
licenses:
|
|
61
|
+
- MIT
|
|
62
|
+
metadata: {}
|
|
63
|
+
post_install_message:
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ! '>='
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '0'
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ! '>='
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements: []
|
|
78
|
+
rubyforge_project:
|
|
79
|
+
rubygems_version: 2.0.3
|
|
80
|
+
signing_key:
|
|
81
|
+
specification_version: 4
|
|
82
|
+
summary: Adds some functionality to query results using the presenter pattern. Delegates
|
|
83
|
+
to the underlying object using method missing for a non-recognized method.
|
|
84
|
+
test_files:
|
|
85
|
+
- test/query_result_presenter_test.rb
|
|
86
|
+
- test/test_helper.rb
|
|
87
|
+
has_rdoc:
|