sqlcached_client 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/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +2 -0
- data/lib/sqlcached_client/entity.rb +152 -0
- data/lib/sqlcached_client/hash_struct.rb +70 -0
- data/lib/sqlcached_client/resultset.rb +73 -0
- data/lib/sqlcached_client/server.rb +76 -0
- data/lib/sqlcached_client/version.rb +3 -0
- data/lib/sqlcached_client.rb +5 -0
- data/spec/sqlcached_client/hash_struct_spec.rb +26 -0
- data/sqlcached_client.gemspec +26 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2f642ec5bff84d1fb7738aff7fedad4d695e8224
|
4
|
+
data.tar.gz: 0168729e04f2d4eca81b5159e09efaa8c0cedd5f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a96a6163594e8a34a86e93b503552d453bd67b0ff96ef4da4b97386da954fdf767504acf3876b1903bf06e18e3e519bc940ca60b3ded5f63fc2bbc34e813361
|
7
|
+
data.tar.gz: d494b4126fa2e8fb60ddfa7562675b48e6f94e9fd9474f2712d51631a11117905c3d9934fe2250b1f1ea4f9bfed498916697d672ec065c8bcbfd632e442f8097
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Roberto Maestroni
|
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,77 @@
|
|
1
|
+
# SqlcachedClient
|
2
|
+
|
3
|
+
A Ruby client for [Sqlcached](https://github.com/rmaestroni/sqlcached).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'sqlcached_client'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install sqlcached_client
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Create your models as you would do with `ActiveRecord`.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'sqlcached_client'
|
25
|
+
|
26
|
+
class Base < SqlcachedClient::Entity
|
27
|
+
# things shared amongst all models
|
28
|
+
server({ host: 'localhost', port: 8081 })
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
class User < Base
|
33
|
+
entity_name 'user'
|
34
|
+
|
35
|
+
query <<-SQL
|
36
|
+
SELECT * FROM users WHERE id IN ({{ ids }})
|
37
|
+
SQL
|
38
|
+
|
39
|
+
has_many :posts, where: { user_id: :id }
|
40
|
+
|
41
|
+
has_many :pictures, class_name: 'Image',
|
42
|
+
where: { imageable_id: :id, imageable_type: 'User' }
|
43
|
+
|
44
|
+
has_one :address, where: { user_id: :id }
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class Post < Base
|
49
|
+
entity_name 'post'
|
50
|
+
|
51
|
+
query <<-SQL
|
52
|
+
SELECT * FROM posts WHERE author_id = {{ user_id }}
|
53
|
+
SQL
|
54
|
+
end
|
55
|
+
|
56
|
+
```
|
57
|
+
|
58
|
+
Run some queries:
|
59
|
+
```ruby
|
60
|
+
users = User.where(ids: '1, 2, 3, 4')
|
61
|
+
|
62
|
+
users[0].pictures.each # you can navigate through the associations
|
63
|
+
```
|
64
|
+
|
65
|
+
Load in memory every associated set recursively:
|
66
|
+
```ruby
|
67
|
+
users.build_associations # for each entity in the resultset, or...
|
68
|
+
users[0].build_associations # for a single entity
|
69
|
+
```
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
1. Fork it ( https://github.com/rmaestroni/sqlcached_client/fork )
|
74
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
76
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'sqlcached_client/hash_struct'
|
2
|
+
require 'sqlcached_client/resultset'
|
3
|
+
require 'sqlcached_client/server'
|
4
|
+
|
5
|
+
module SqlcachedClient
|
6
|
+
class Entity < HashStruct
|
7
|
+
|
8
|
+
attr_reader :attribute_names
|
9
|
+
|
10
|
+
# @param attributes [Hash]
|
11
|
+
def initialize(attributes)
|
12
|
+
@attribute_names = attributes.keys
|
13
|
+
super(attributes)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
class << self
|
18
|
+
attr_reader :query_id
|
19
|
+
|
20
|
+
def entity_name(value)
|
21
|
+
@query_id = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def query(sql_string = nil)
|
25
|
+
sql_string.nil? ? @query : @query = sql_string.strip
|
26
|
+
end
|
27
|
+
|
28
|
+
def server(config = nil)
|
29
|
+
if config.nil?
|
30
|
+
@server ||
|
31
|
+
if (superclass = ancestors[1]).respond_to?(:server)
|
32
|
+
superclass.server
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@server =
|
38
|
+
if config.is_a?(Hash)
|
39
|
+
Server.new(config)
|
40
|
+
else
|
41
|
+
config
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def where(params, dry_run = false)
|
47
|
+
request = server.format_request(query_id, query, params)
|
48
|
+
if dry_run
|
49
|
+
request
|
50
|
+
else
|
51
|
+
data = server.run_query(server.build_request_body([request]))
|
52
|
+
data = data[0] if data.is_a?(Array)
|
53
|
+
Resultset.new(self, data)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_many(accessor_name, options)
|
58
|
+
foreign_class_name =
|
59
|
+
if options[:class_name].present?
|
60
|
+
options[:class_name]
|
61
|
+
else
|
62
|
+
accessor_name.to_s.singularize.camelize
|
63
|
+
end
|
64
|
+
# the query to run to get the data
|
65
|
+
association = -> (this, foreign_entity, join_attributes, dry_run) {
|
66
|
+
foreign_entity.where(Hash[ join_attributes.map do |attr_names|
|
67
|
+
attr_value =
|
68
|
+
if attr_names[1].is_a?(Symbol)
|
69
|
+
this.send(attr_names[1])
|
70
|
+
else
|
71
|
+
attr_names[1]
|
72
|
+
end
|
73
|
+
[ attr_names[0], attr_value ]
|
74
|
+
end ], dry_run)
|
75
|
+
}
|
76
|
+
# get the attributes to define the foreign scope
|
77
|
+
join_attributes = (options[:where] || []).to_a
|
78
|
+
# memoize the associated resultset
|
79
|
+
memoize_var = "@has_many_#{accessor_name}"
|
80
|
+
# define the accessor method
|
81
|
+
define_method(accessor_name) do |dry_run = false|
|
82
|
+
# get the associated entity class
|
83
|
+
foreign_entity = Module.const_get(foreign_class_name)
|
84
|
+
if dry_run
|
85
|
+
association.call(self, foreign_entity, join_attributes, true)
|
86
|
+
else
|
87
|
+
instance_variable_get(memoize_var) ||
|
88
|
+
instance_variable_set(memoize_var,
|
89
|
+
association.call(self, foreign_entity, join_attributes, false))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
# define the setter method
|
93
|
+
define_method("#{accessor_name}=") do |array|
|
94
|
+
# get the associated entity class
|
95
|
+
foreign_entity = Module.const_get(foreign_class_name)
|
96
|
+
instance_variable_set(memoize_var,
|
97
|
+
Resultset.new(foreign_entity, array))
|
98
|
+
end
|
99
|
+
# save the newly created association
|
100
|
+
register_association(accessor_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
def has_one(accessor_name, options)
|
104
|
+
plural_accessor_name = "s_#{accessor_name}".to_s.pluralize
|
105
|
+
class_name = accessor_name.to_s.camelize
|
106
|
+
has_many(plural_accessor_name, { class_name: class_name }.merge(options))
|
107
|
+
define_method(accessor_name) do
|
108
|
+
send(plural_accessor_name).first
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def registered_associations
|
113
|
+
@registered_associations || []
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def register_association(association_name)
|
119
|
+
@registered_associations ||= []
|
120
|
+
@registered_associations << association_name.to_sym
|
121
|
+
end
|
122
|
+
end # class << self
|
123
|
+
|
124
|
+
def get_association_requests
|
125
|
+
self.class.registered_associations.map do |a_name|
|
126
|
+
send(a_name, true)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_associations_data(associations_data)
|
131
|
+
self.class.registered_associations.map.with_index do |a_name, i|
|
132
|
+
send("#{a_name}=", associations_data[i])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_associations
|
137
|
+
self.class.registered_associations.map do |a_name|
|
138
|
+
send(a_name)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def build_associations(max_depth = false)
|
143
|
+
Resultset.new(self.class, [self]).build_associations(max_depth)
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_h
|
147
|
+
@_to_h ||=
|
148
|
+
Hash[ attribute_names.map { |a_name| [a_name, send(a_name)] } ]
|
149
|
+
end
|
150
|
+
|
151
|
+
end # class Entity
|
152
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module SqlcachedClient
|
2
|
+
# Maps recursively hashes into objects with lazy evaluation. For example
|
3
|
+
#
|
4
|
+
# hs = HashStruct.new({
|
5
|
+
# a: ['foo', { a1: [{ a2: 'one' }, 'two', 'three'] }, 'bar'],
|
6
|
+
# b: 'baz',
|
7
|
+
# c: 4,
|
8
|
+
# d: { d1: { d2: { d3: 'hi' } } }
|
9
|
+
# })
|
10
|
+
# # => #<HashStruct:0x0000000f188008>
|
11
|
+
#
|
12
|
+
# hs.b
|
13
|
+
# # => "baz"
|
14
|
+
#
|
15
|
+
# hs.c
|
16
|
+
# # => 4
|
17
|
+
#
|
18
|
+
# hs.a
|
19
|
+
# # => ["foo", #<HashStruct:0x0000000f1dc798>, "bar"]
|
20
|
+
#
|
21
|
+
# hs.a[1].a1
|
22
|
+
# # => [#<HashStruct:0x0000000f275ce0>, "two", "three"]
|
23
|
+
#
|
24
|
+
# hs.a[1].a1[0].a2
|
25
|
+
# # => "one"
|
26
|
+
#
|
27
|
+
# # values are memoized
|
28
|
+
# hs
|
29
|
+
# # => #<HashStruct:0x0000000f188008
|
30
|
+
# # @_a=["foo", #<HashStruct:0x0000000f1dc798 @_a1=[#<HashStruct:0x0000000f275ce0 @_a2="one">, "two", "three"]>, "bar"],
|
31
|
+
# # @_b="baz",
|
32
|
+
# # @_c=4>
|
33
|
+
class HashStruct
|
34
|
+
|
35
|
+
def initialize(hash)
|
36
|
+
hash.each do |key, value|
|
37
|
+
define_singleton_method(key.to_sym, &HashStruct.build(value, key))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
|
43
|
+
# @return [Proc]
|
44
|
+
def build(value, accessor_name = nil)
|
45
|
+
lambda =
|
46
|
+
if value.is_a?(Hash)
|
47
|
+
-> (aself, value) { HashStruct.new(value) }
|
48
|
+
elsif value.is_a?(Array)
|
49
|
+
-> (aself, value) {
|
50
|
+
value.map { |item| aself.instance_eval(&HashStruct.build(item)) }
|
51
|
+
}
|
52
|
+
else
|
53
|
+
-> (aself, value) { value }
|
54
|
+
end
|
55
|
+
if !accessor_name.nil?
|
56
|
+
memoize_v = "@_#{accessor_name}"
|
57
|
+
Proc.new {
|
58
|
+
if instance_variable_defined?(memoize_v)
|
59
|
+
instance_variable_get(memoize_v)
|
60
|
+
else
|
61
|
+
instance_variable_set(memoize_v, lambda.call(self, value))
|
62
|
+
end
|
63
|
+
}
|
64
|
+
else
|
65
|
+
Proc.new { lambda.call(self, value) }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end # class << self
|
69
|
+
end # class HashStruct
|
70
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module SqlcachedClient
|
2
|
+
class Resultset
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :entity_class, :entities, :count
|
6
|
+
|
7
|
+
# @param entity_class [Class]
|
8
|
+
# @param entities [Array]
|
9
|
+
def initialize(entity_class, entities)
|
10
|
+
@entity_class = entity_class
|
11
|
+
@entities = (entities || []).map do |item|
|
12
|
+
if item.is_a?(Hash)
|
13
|
+
entity_class.new(item)
|
14
|
+
elsif item.is_a?(entity_class)
|
15
|
+
item
|
16
|
+
else
|
17
|
+
raise "Cannot handle instances of #{item.class.name}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@count = @entities.size
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
def build_associations(resultsets, server, max_depth, current_depth = 0)
|
26
|
+
if resultsets.any?
|
27
|
+
batch = resultsets.map { |r| r._get_entities_association_requests }
|
28
|
+
if batch.flatten.any?
|
29
|
+
next_batch =
|
30
|
+
server.run_query(
|
31
|
+
server.build_request_body(
|
32
|
+
batch
|
33
|
+
)
|
34
|
+
).map.with_index do |resultset_data, i|
|
35
|
+
resultsets[i]._fill_associations(resultset_data)
|
36
|
+
end.flatten!
|
37
|
+
if !max_depth || current_depth < max_depth
|
38
|
+
build_associations(next_batch, server, max_depth, current_depth + 1)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end # class << self
|
44
|
+
|
45
|
+
def each(&block)
|
46
|
+
block ? entities.each(&block) : entities.each
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](i)
|
50
|
+
entities[i]
|
51
|
+
end
|
52
|
+
|
53
|
+
def uncache
|
54
|
+
# TODO
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_associations(max_depth = false)
|
58
|
+
self.class.build_associations([self], entity_class.server, max_depth)
|
59
|
+
end
|
60
|
+
|
61
|
+
def _fill_associations(data)
|
62
|
+
data.map.with_index do |entity_assoc_data, i|
|
63
|
+
entities[i].set_associations_data(entity_assoc_data)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def _get_entities_association_requests
|
68
|
+
entities.map do |entity|
|
69
|
+
entity.get_association_requests
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module SqlcachedClient
|
6
|
+
class Server
|
7
|
+
attr_reader :host, :port
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@host = config[:host]
|
11
|
+
@port = config[:port]
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def run_query(http_req_body)
|
16
|
+
url = server_url
|
17
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
18
|
+
req = Net::HTTP::Post.new(data_batch_url)
|
19
|
+
req.set_content_type('application/json')
|
20
|
+
req.body = http_req_body.to_json
|
21
|
+
resp = http.request(req)
|
22
|
+
if 'application/json' == resp['Content-Type']
|
23
|
+
resp_body = parse_response_body(JSON.parse(resp.body))
|
24
|
+
else
|
25
|
+
resp_body = resp.body
|
26
|
+
end
|
27
|
+
if 200 == resp.code.to_i
|
28
|
+
resp_body
|
29
|
+
else
|
30
|
+
raise "Got http response #{resp.code} from server - #{resp_body.inspect}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def parse_response_body(body)
|
37
|
+
if body.is_a?(Array)
|
38
|
+
body.map { |item| parse_response_body(item) }
|
39
|
+
elsif body.is_a?(Hash)
|
40
|
+
if (resultset = body['resultset']).is_a?(String)
|
41
|
+
JSON.parse(resultset)
|
42
|
+
else
|
43
|
+
resultset
|
44
|
+
end
|
45
|
+
else
|
46
|
+
body
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def build_request_body(ary)
|
52
|
+
{ batch: ary }
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def format_request(query_id, query_template, params)
|
57
|
+
{
|
58
|
+
queryId: query_id,
|
59
|
+
queryTemplate: query_template,
|
60
|
+
queryParams: params
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def server_url
|
67
|
+
URI("http://#{host}:#{port}")
|
68
|
+
end
|
69
|
+
|
70
|
+
def data_batch_url
|
71
|
+
url = server_url
|
72
|
+
url.path = "/data-batch"
|
73
|
+
url
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sqlcached_client/hash_struct'
|
2
|
+
|
3
|
+
RSpec.describe SqlcachedClient::HashStruct do
|
4
|
+
let(:hash_struct) do
|
5
|
+
SqlcachedClient::HashStruct.new({
|
6
|
+
a: ['foo', { a1: [{ a2: 'one' }, 'two', 'three'] }, 'bar'],
|
7
|
+
b: 'baz',
|
8
|
+
c: 4,
|
9
|
+
d: { d1: { d2: { d3: 'hi' } } }
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should map keys into methods" do
|
14
|
+
[:a, :b, :c, :d].each do |m|
|
15
|
+
expect(hash_struct.respond_to?(m)).to eq(true)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should map recoursively" do
|
20
|
+
ary = hash_struct.a
|
21
|
+
expect(ary[0]).to eq('foo')
|
22
|
+
expect(ary[1].a1[0].a2).to eq('one')
|
23
|
+
expect(hash_struct.d.d1.d2.d3).to eq('hi')
|
24
|
+
expect(hash_struct.c).to eq(4)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sqlcached_client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sqlcached_client"
|
8
|
+
spec.version = SqlcachedClient::VERSION
|
9
|
+
spec.authors = ["Roberto Maestroni"]
|
10
|
+
spec.email = ["r.maestroni@gmail.com"]
|
11
|
+
spec.summary = %q{A Ruby client for sqlcached}
|
12
|
+
spec.description = %q{A Ruby client for sqlcached}
|
13
|
+
spec.homepage = "https://github.com/rmaestroni/sqlcached_client"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
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_dependency "activesupport", "~> 4.2"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqlcached_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roberto Maestroni
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
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: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: A Ruby client for sqlcached
|
70
|
+
email:
|
71
|
+
- r.maestroni@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- lib/sqlcached_client.rb
|
82
|
+
- lib/sqlcached_client/entity.rb
|
83
|
+
- lib/sqlcached_client/hash_struct.rb
|
84
|
+
- lib/sqlcached_client/resultset.rb
|
85
|
+
- lib/sqlcached_client/server.rb
|
86
|
+
- lib/sqlcached_client/version.rb
|
87
|
+
- spec/sqlcached_client/hash_struct_spec.rb
|
88
|
+
- sqlcached_client.gemspec
|
89
|
+
homepage: https://github.com/rmaestroni/sqlcached_client
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.2.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: A Ruby client for sqlcached
|
113
|
+
test_files:
|
114
|
+
- spec/sqlcached_client/hash_struct_spec.rb
|