koromo 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 +7 -0
- data/LICENSE +22 -0
- data/README.md +33 -0
- data/bin/koromo +16 -0
- data/bin/koromo_config +3 -0
- data/koromo.gemspec +24 -0
- data/lib/koromo/config-example.yml +64 -0
- data/lib/koromo/config.rb +21 -0
- data/lib/koromo/helper.rb +54 -0
- data/lib/koromo/server.rb +87 -0
- data/lib/koromo/sql.rb +96 -0
- data/lib/koromo/version.rb +5 -0
- data/lib/koromo.rb +1 -0
- metadata +128 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 274989dcaa69f9b1c7d25faa5697bc9a645c43b1
|
4
|
+
data.tar.gz: f2f827427f6fd76bfb0fa7fd871ac8a3bef99b9f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 29d602aeb709c3564889119de0e6f2f850e62e4d8febfbdeaed197875d0f24867e15221e92464dac57f1b6cf208492384cd767933e61dd71cb9dc9e990e68586
|
7
|
+
data.tar.gz: 2d0bb77811fe6f7dd17a67b06e9ce55251586dd82a6b9807e472d2fadec56785bf9ba8c6aebafaa5eae56a9092c04d139c6f061433e5c384ebb4ae10c5f991f3
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Ken J.
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# koromo
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/koromo) [](https://codeclimate.com/github/kenjij/koromo)
|
4
|
+
|
5
|
+
A proxy server for MS SQL Server to present as a RESTful service.
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
- Ruby 2.0.0 <=
|
10
|
+
- FreeTDS library (uses the [tiny_tds](https://rubygems.org/gems/tiny_tds/) gem)
|
11
|
+
|
12
|
+
## Getting Started
|
13
|
+
|
14
|
+
### Install
|
15
|
+
|
16
|
+
```
|
17
|
+
$ gem install koromo
|
18
|
+
```
|
19
|
+
|
20
|
+
### Use
|
21
|
+
|
22
|
+
```
|
23
|
+
$ koromo start -c config.yml
|
24
|
+
```
|
25
|
+
|
26
|
+
### Examples
|
27
|
+
|
28
|
+
Config file.
|
29
|
+
|
30
|
+
```
|
31
|
+
$ koromo_config
|
32
|
+
```
|
33
|
+
|
data/bin/koromo
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'kajiki'
|
3
|
+
require 'thin'
|
4
|
+
require 'koromo'
|
5
|
+
|
6
|
+
|
7
|
+
opts = Kajiki.preset_options(:server, {config: true})
|
8
|
+
|
9
|
+
Kajiki.run(opts) do |cmd|
|
10
|
+
case cmd
|
11
|
+
when 'start'
|
12
|
+
Thin::Server.start(opts[:address], opts[:port]) do
|
13
|
+
run Koromo::Server.new(opts)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/bin/koromo_config
ADDED
data/koromo.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
|
+
require 'koromo/version'
|
3
|
+
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'koromo'
|
7
|
+
s.version = Koromo::Version
|
8
|
+
s.authors = ['Ken J.']
|
9
|
+
s.email = ['kenjij@gmail.com']
|
10
|
+
s.summary = %q{MS SQL Server RESTful access proxy}
|
11
|
+
s.description = %q{A proxy server for MS SQL Server to present as a RESTful service.}
|
12
|
+
s.homepage = 'https://github.com/kenjij/koromo'
|
13
|
+
s.license = 'MIT'
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split($/)
|
16
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'kajiki', '~> 1.1'
|
20
|
+
s.add_runtime_dependency 'thin', '~> 1.6'
|
21
|
+
s.add_runtime_dependency 'sinatra', '~> 1.4'
|
22
|
+
s.add_runtime_dependency 'tiny_tds', '~> 1.0'
|
23
|
+
s.add_runtime_dependency 'sequel', '~> 4.0'
|
24
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
---
|
2
|
+
# TDS options
|
3
|
+
:mssql:
|
4
|
+
# The database server user
|
5
|
+
:user: username
|
6
|
+
# The user password
|
7
|
+
:password: p4sSw0rD
|
8
|
+
# Used if :dataserver blank; can be an hostname or an IP address
|
9
|
+
:host: 192.168.0.100
|
10
|
+
# Defaults to 1433; only used if :host is configured
|
11
|
+
:port: 1433
|
12
|
+
# The default database to use
|
13
|
+
:database: master
|
14
|
+
# Other TDS options can be configure as well; default examples below
|
15
|
+
# :login_timeout: 60
|
16
|
+
# :timeout: 5
|
17
|
+
# :encoding: UTF-8
|
18
|
+
# :azure: false
|
19
|
+
|
20
|
+
:global:
|
21
|
+
:pretty_json: YES
|
22
|
+
# Basic security by requiring strings below to be passed in "auth" param
|
23
|
+
:auth_tokens:
|
24
|
+
:any:
|
25
|
+
- sEcReT_sTrInG_0N3
|
26
|
+
- SeCrEt_StRiNg_7W0
|
27
|
+
|
28
|
+
# API definitions
|
29
|
+
:resources:
|
30
|
+
# Name of the resource available via API
|
31
|
+
:resource1:
|
32
|
+
# Name of the DB table
|
33
|
+
:table: :table1
|
34
|
+
# Name of columns to return from the table
|
35
|
+
:columns:
|
36
|
+
- :id
|
37
|
+
- :name
|
38
|
+
- :description
|
39
|
+
- :date
|
40
|
+
# Name of the column to search when resource ID is present
|
41
|
+
:key: :id
|
42
|
+
# Optional; otherwise restricted to 10
|
43
|
+
:limit: 25
|
44
|
+
# Optional
|
45
|
+
:order: :date
|
46
|
+
# Optional; defaults to ASC without this option present
|
47
|
+
:desc: true
|
48
|
+
# Settings for GET calls
|
49
|
+
:get:
|
50
|
+
# Return as Hash or Array
|
51
|
+
:class: Hash
|
52
|
+
# Optional only with Hash; response will become a simple key-value pair
|
53
|
+
:value: :name
|
54
|
+
:books:
|
55
|
+
:table: :books
|
56
|
+
:columns:
|
57
|
+
- :id
|
58
|
+
- :isbn
|
59
|
+
- :title
|
60
|
+
- :author
|
61
|
+
- :date
|
62
|
+
:key: :isbn
|
63
|
+
:get:
|
64
|
+
:class: Array
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Koromo
|
4
|
+
|
5
|
+
# Load YAML config file
|
6
|
+
# @param path [String] config file
|
7
|
+
# @return [Object] config; a shared instance
|
8
|
+
def self.load_config(path)
|
9
|
+
raise 'config file missing' unless path
|
10
|
+
@config ||= YAML.load_file(path)
|
11
|
+
if file = @config[:require_file]
|
12
|
+
require File.expand_path(file, path)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# see #self.load_config
|
17
|
+
def self.config
|
18
|
+
@config
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Koromo
|
4
|
+
|
5
|
+
module Helper
|
6
|
+
|
7
|
+
# Convert object into JSON, optionally pretty-format
|
8
|
+
# @param obj [Object] any Ruby object
|
9
|
+
# @param opts [Hash] any JSON options
|
10
|
+
# @return [String] JSON string
|
11
|
+
def json_with_object(obj, pretty: nil, opts: nil)
|
12
|
+
return '{}' if obj.nil?
|
13
|
+
pretty ||= Koromo.config[:global][:pretty_json]
|
14
|
+
if pretty
|
15
|
+
opts = {
|
16
|
+
indent: ' ',
|
17
|
+
space: ' ',
|
18
|
+
object_nl: "\n",
|
19
|
+
array_nl: "\n"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
JSON.fast_generate(json_format_value(obj), opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return Ruby object/value to JSON standard format
|
26
|
+
# @param val [Object]
|
27
|
+
# @return [Object]
|
28
|
+
def json_format_value(val)
|
29
|
+
case val
|
30
|
+
when Array
|
31
|
+
val.map { |v| json_format_value(v) }
|
32
|
+
when Hash
|
33
|
+
val.reduce({}) { |h, (k, v)| h.merge({k => json_format_value(v)}) }
|
34
|
+
when BigDecimal
|
35
|
+
# val.to_s('F')
|
36
|
+
val.to_f
|
37
|
+
when String
|
38
|
+
val.encode!('UTF-8', {invalid: :replace, undef: :replace})
|
39
|
+
when Time
|
40
|
+
val.utc.iso8601
|
41
|
+
else
|
42
|
+
val
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_token?(token, method = :any)
|
47
|
+
tokens = Koromo.config[:global][:auth_tokens][method]
|
48
|
+
return true if tokens.nil?
|
49
|
+
tokens.include?(token)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'logger'
|
3
|
+
require 'koromo/config'
|
4
|
+
require 'koromo/helper'
|
5
|
+
require 'koromo/sql'
|
6
|
+
|
7
|
+
module Koromo
|
8
|
+
|
9
|
+
# The Sinatra server
|
10
|
+
class Server < Sinatra::Base
|
11
|
+
|
12
|
+
attr_reader :rack_opts
|
13
|
+
# attr_reader :config
|
14
|
+
|
15
|
+
def initialize(opts)
|
16
|
+
super()
|
17
|
+
@rack_opts = opts
|
18
|
+
Koromo.load_config(rack_opts[:config])
|
19
|
+
end
|
20
|
+
|
21
|
+
def slogger
|
22
|
+
return logger if settings.logging
|
23
|
+
@slogger ||= Logger.new(STDOUT)
|
24
|
+
return @slogger
|
25
|
+
end
|
26
|
+
|
27
|
+
helpers Helper, SQL
|
28
|
+
|
29
|
+
configure do
|
30
|
+
set :environment, :production
|
31
|
+
enable :logging
|
32
|
+
disable :static, :dump_errors
|
33
|
+
end
|
34
|
+
|
35
|
+
before do
|
36
|
+
# @jsonp_callback = params[:callback]
|
37
|
+
halt 401 unless valid_token?(params[:auth])
|
38
|
+
setup_sql(Koromo.config)
|
39
|
+
end
|
40
|
+
|
41
|
+
get '/:resource' do |r|
|
42
|
+
result = get_resource(r, params: params)
|
43
|
+
if result
|
44
|
+
json_with_object(result)
|
45
|
+
else
|
46
|
+
fail Sinatra::NotFound
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/:resource/:id' do |r, id|
|
51
|
+
fail Sinatra::NotFound if /\W/ =~ id
|
52
|
+
result = get_resource(r, id: id, params: params)
|
53
|
+
if result
|
54
|
+
json_with_object(result)
|
55
|
+
else
|
56
|
+
fail Sinatra::NotFound
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
not_found do
|
61
|
+
json_with_object({message: 'Huh, nothing here.'})
|
62
|
+
end
|
63
|
+
|
64
|
+
error 401 do
|
65
|
+
json_with_object({message: 'Oops, need a valid auth.'})
|
66
|
+
end
|
67
|
+
|
68
|
+
error do
|
69
|
+
status 500
|
70
|
+
err = env['sinatra.error']
|
71
|
+
slogger.error "#{err.class.name} - #{err}"
|
72
|
+
json_with_object({message: 'Yikes, internal error.'})
|
73
|
+
end
|
74
|
+
|
75
|
+
after do
|
76
|
+
content_type 'application/json'
|
77
|
+
# if @jsonp_callback
|
78
|
+
# content_type 'application/javascript'
|
79
|
+
# body @jsonp_callback + '(' + json_with_object(@body_object) + ')'
|
80
|
+
# else
|
81
|
+
# content_type 'application/json'
|
82
|
+
# body json_with_object(@body_object, {pretty: config[:global][:pretty_json]})
|
83
|
+
# end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
data/lib/koromo/sql.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
|
4
|
+
module Koromo
|
5
|
+
|
6
|
+
module SQL
|
7
|
+
|
8
|
+
def setup_sql(conf)
|
9
|
+
@config = conf
|
10
|
+
# Sequel connection setup
|
11
|
+
# Sequel.application_timezone = :local
|
12
|
+
# Sequel.database_timezone = :utc
|
13
|
+
Sequel::Model.db = Sequel.connect({adapter: 'tinytds'}.merge(config[:mssql]))
|
14
|
+
end
|
15
|
+
|
16
|
+
def config
|
17
|
+
@config
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_for_resource(name)
|
21
|
+
name = name.to_sym
|
22
|
+
c = config[:resources][name]
|
23
|
+
c[:limit] ||= 10
|
24
|
+
c
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get model classes
|
28
|
+
def model_for_resource(name)
|
29
|
+
name = name.to_sym
|
30
|
+
@models ||= {}
|
31
|
+
return nil unless rc = config_for_resource(name)
|
32
|
+
if @models[name].nil?
|
33
|
+
m = Class.new(Sequel::Model)
|
34
|
+
m.set_dataset(rc[:table])
|
35
|
+
@models[name] = m
|
36
|
+
end
|
37
|
+
@models[name]
|
38
|
+
end
|
39
|
+
|
40
|
+
def run_query(query)
|
41
|
+
result = mssql.execute(query)
|
42
|
+
records = []
|
43
|
+
result.each(cache_rows: false) do |row|
|
44
|
+
record = {}
|
45
|
+
row.each { |k, v| record[k] = convert_value(v) }
|
46
|
+
records.push record
|
47
|
+
end
|
48
|
+
records
|
49
|
+
# rescue => e
|
50
|
+
# puts e.message
|
51
|
+
# raise
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_resource(name, **args)
|
55
|
+
return nil unless model = model_for_resource(name)
|
56
|
+
p args[:params]
|
57
|
+
conf = config_for_resource(name)
|
58
|
+
set = model.select(*conf[:columns])
|
59
|
+
if args[:id]
|
60
|
+
array = set.where(conf[:key] => args[:id]).all
|
61
|
+
else
|
62
|
+
if args[:params]
|
63
|
+
p_limit = args[:params][:limit]
|
64
|
+
p_limit = p_limit.to_i if p_limit.class == String
|
65
|
+
p_order = args[:params][:order]
|
66
|
+
p_desc = true if args[:params][:desc]
|
67
|
+
p_desc = false if args[:params][:asc]
|
68
|
+
end
|
69
|
+
p_limit ||= conf[:limit]
|
70
|
+
p_order ||= conf[:order]
|
71
|
+
p_desc ||= conf[:desc]
|
72
|
+
set = set.limit(p_limit)
|
73
|
+
set = (p_desc ? set.reverse_order(p_order) : set.order(p_order))
|
74
|
+
p set.sql
|
75
|
+
array = set.all
|
76
|
+
end
|
77
|
+
return nil if array.empty?
|
78
|
+
case conf[:get][:class]
|
79
|
+
when 'Hash'
|
80
|
+
result = {}
|
81
|
+
key = conf[:key]
|
82
|
+
val = conf[:get][:value]
|
83
|
+
array.each do |r|
|
84
|
+
rec = r.values
|
85
|
+
result.store(rec.delete(key), val ? rec[val] : rec)
|
86
|
+
end
|
87
|
+
when 'Array'
|
88
|
+
result = array.map{ |r| r.values }
|
89
|
+
end
|
90
|
+
return result[0] if args[:id] && result.class == Array
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
data/lib/koromo.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'koromo/server'
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: koromo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken J.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kajiki
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thin
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sinatra
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: tiny_tds
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sequel
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.0'
|
83
|
+
description: A proxy server for MS SQL Server to present as a RESTful service.
|
84
|
+
email:
|
85
|
+
- kenjij@gmail.com
|
86
|
+
executables:
|
87
|
+
- koromo
|
88
|
+
- koromo_config
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- LICENSE
|
93
|
+
- README.md
|
94
|
+
- bin/koromo
|
95
|
+
- bin/koromo_config
|
96
|
+
- koromo.gemspec
|
97
|
+
- lib/koromo.rb
|
98
|
+
- lib/koromo/config-example.yml
|
99
|
+
- lib/koromo/config.rb
|
100
|
+
- lib/koromo/helper.rb
|
101
|
+
- lib/koromo/server.rb
|
102
|
+
- lib/koromo/sql.rb
|
103
|
+
- lib/koromo/version.rb
|
104
|
+
homepage: https://github.com/kenjij/koromo
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.4.3
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: MS SQL Server RESTful access proxy
|
128
|
+
test_files: []
|