sqlcached_client 0.0.2 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 76ca46c57afc585a8a3ba673e64992b765534fde
4
- data.tar.gz: 2be70c7d54517dd4a3d3bedb833572592b3bfea0
3
+ metadata.gz: 30b7e7df7003436bc67762203e5e3fdd982be9b9
4
+ data.tar.gz: e9fbb528788728392c7b5a6b879a38230beafd11
5
5
  SHA512:
6
- metadata.gz: 6f797a555a1f56561da3a56c535ddd8f0822e6636cfa5d3b2bc648cff9e99f51cc0d8e215c1aca398ba381e5ed87b5f24f64b5cebd59ddec6b688fa475aef895
7
- data.tar.gz: cfa1fa922a25c58a327361e0561b7fd5d4391562f4f125ac32cd16bb1a7de6252b2db9655767843847ae448f6550567152f74fea1000e498b6dba11776bae0a1
6
+ metadata.gz: 084112afa0b779ff0772ef3fcdbe43e12e3d5fbeea51dc7b177d5dfef29d0a3cf37cc9df665493d1c00450b96d77ed8fa77088ff74bf5999f539cdf4f33986ec
7
+ data.tar.gz: cd72f5a608e867d7defdcadfa37b42757bb022af05273d853cb472d343f1614bbfd117613bc1b2bbdb5a3f93e6d4a2ad6723d3edaaf0183d1ca3c4e4459b9a20
@@ -0,0 +1,61 @@
1
+ require 'singleton'
2
+ require 'arel'
3
+ require 'active_record'
4
+ require 'nulldb'
5
+
6
+ module SqlcachedClient
7
+ module Arel
8
+
9
+ # Builds a SQL query executing the Arel statements in the given block.
10
+ # @param tables_map [Hash] in the form of
11
+ # { :t1 => [:par1, :par2], :t2 => :par3, :t3 => nil }
12
+ # @param arel_block [Proc]
13
+ # @return [Arel] an object that responds to 'to_sql'
14
+ def build_arel(tables_map, arel_block)
15
+ table_names = tables_map.keys
16
+ # attributes of this struct returns Arel tables named as the attribute
17
+ context = Struct.new(*table_names).new(
18
+ *table_names.map do |t_name|
19
+ ArelWrapper.arel_module::Table.new(t_name)
20
+ end
21
+ )
22
+ # build an Arel object evaluating the block if any
23
+ arel_q =
24
+ if arel_block
25
+ context.instance_eval(&arel_block)
26
+ else
27
+ # no block given, add the default SELECT *
28
+ context.send(tables_map.keys.first).project(
29
+ ArelWrapper.arel_module.sql('*'))
30
+ end
31
+ # add the 'where' conditions passed as parameters (values in tables_map)
32
+ tables_map.inject(arel_q) do |query_acc, item|
33
+ t_name, parameters = item
34
+ table = context.send(t_name)
35
+ parameters ||= []
36
+ parameters = [parameters] if !parameters.respond_to?(:inject)
37
+ parameters.inject(query_acc) do |arel, param|
38
+ arel.where(table[param].eq("{{ #{param} }}"))
39
+ end
40
+ end
41
+ end # method build_arel
42
+ end # module Arel
43
+
44
+ private
45
+
46
+ class ArelWrapper
47
+ include Singleton
48
+
49
+ def initialize
50
+ ::Arel::Table.engine = ::ActiveRecord::Base.establish_connection(
51
+ adapter: :nulldb)
52
+ end
53
+
54
+ class << self
55
+ def arel_module
56
+ instance
57
+ ::Arel
58
+ end
59
+ end
60
+ end # class ArelWrapper
61
+ end
@@ -1,16 +1,17 @@
1
- require 'sqlcached_client/hash_struct'
2
1
  require 'sqlcached_client/resultset'
3
2
  require 'sqlcached_client/server'
3
+ require 'sqlcached_client/arel'
4
4
 
5
5
  module SqlcachedClient
6
- class Entity < HashStruct
6
+ class Entity
7
+ extend Arel
7
8
 
8
- attr_reader :attribute_names
9
+ attr_reader :attributes
9
10
 
10
11
  # @param attributes [Hash]
11
12
  def initialize(attributes)
12
- @attribute_names = attributes.keys
13
- super(attributes)
13
+ @attributes = attributes
14
+ self.class.define_readers(attributes.keys)
14
15
  end
15
16
 
16
17
 
@@ -24,8 +25,22 @@ module SqlcachedClient
24
25
 
25
26
  # Sets the query of this entity if a parameter is provided, otherwise
26
27
  # returns the value previously set.
27
- def query(sql_string = nil)
28
- sql_string.nil? ? @query : @query = sql_string.strip
28
+ def query(*args, &block)
29
+ if args.empty?
30
+ @query
31
+ else
32
+ if args[0].is_a?(String)
33
+ @query = args[0].strip
34
+ else
35
+ @query = build_arel(
36
+ args.inject({}) do |acc, param|
37
+ acc.merge(
38
+ param.is_a?(Hash) ? param : Hash[ [[param, nil]] ]
39
+ )
40
+ end,
41
+ block).to_sql
42
+ end
43
+ end
29
44
  end
30
45
 
31
46
  # Configures the server of this entity if a parameter is provided,
@@ -56,7 +71,7 @@ module SqlcachedClient
56
71
  # Runs the entity query with the provided parameters
57
72
  # @return [Resultset]
58
73
  def where(params, dry_run = false)
59
- request = server.format_request(query_id, query, params)
74
+ request = server.format_request(query_id, query, params, cache)
60
75
  if dry_run
61
76
  request
62
77
  else
@@ -143,6 +158,39 @@ module SqlcachedClient
143
158
  @registered_associations || []
144
159
  end
145
160
 
161
+ # Define the readers for the attribute names specified
162
+ # @param attr_names [Array]
163
+ def define_readers(attr_names)
164
+ if @_readers_defined.nil?
165
+ attr_names.each do |attr_name|
166
+ if method_defined?(attr_name)
167
+ raise "Cannot define accessor: #{attr_name}"
168
+ else
169
+ define_method(attr_name) do
170
+ attributes[attr_name]
171
+ end
172
+ end
173
+ end
174
+ @_readers_defined = true
175
+ end
176
+ end
177
+
178
+ # Configures the caching timing if a parameter is provided, otherwise
179
+ # returns the value set in the current class or in a superclass.
180
+ # Default value is true.
181
+ def cache(seconds = nil)
182
+ if seconds.nil?
183
+ @cache ||
184
+ if (superclass = ancestors[1]).respond_to?(:cache)
185
+ superclass.cache
186
+ else
187
+ true
188
+ end
189
+ else
190
+ @cache = seconds
191
+ end
192
+ end
193
+
146
194
  private
147
195
 
148
196
  def register_association(association_name)
@@ -174,8 +222,7 @@ module SqlcachedClient
174
222
  end
175
223
 
176
224
  def to_h
177
- @_to_h ||=
178
- Hash[ attribute_names.map { |a_name| [a_name, send(a_name)] } ]
225
+ attributes
179
226
  end
180
227
 
181
228
  end # class Entity
@@ -50,11 +50,12 @@ module SqlcachedClient
50
50
  end
51
51
 
52
52
 
53
- def format_request(query_id, query_template, params)
53
+ def format_request(query_id, query_template, params, cache)
54
54
  {
55
55
  queryId: query_id,
56
56
  queryTemplate: query_template,
57
- queryParams: params
57
+ queryParams: params,
58
+ cache: cache
58
59
  }
59
60
  end
60
61
 
@@ -1,3 +1,3 @@
1
1
  module SqlcachedClient
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -5,8 +5,16 @@ describe SqlcachedClient::Entity do
5
5
 
6
6
  describe :initialize do
7
7
  it "should record the attribute names" do
8
- e = SqlcachedClient::Entity.new({ foo: 'bar', baz: 'biz' })
9
- expect(e.attribute_names).to eq([:foo, :baz])
8
+ h = { foo: 'bar', baz: 'biz' }
9
+ e = Class.new(SqlcachedClient::Entity).new(h)
10
+ expect(e.attributes).to eq(h)
11
+ end
12
+
13
+ it "should define readers methods named as attributes.keys" do
14
+ entity_class = Class.new(SqlcachedClient::Entity)
15
+ entity = entity_class.new(foo: 'bar', baz: 'biz')
16
+ expect(entity.foo).to eq('bar')
17
+ expect(entity.baz).to eq('biz')
10
18
  end
11
19
  end
12
20
 
@@ -93,7 +101,7 @@ describe SqlcachedClient::Entity do
93
101
  context "if dry_run" do
94
102
  it "should return the request that would be sent to the server" do
95
103
  entity_class.server(double(format_request: "this is the request"))
96
- expect(entity_class.server).to receive(:format_request).with("foo", "bar", { baz: "biz" })
104
+ expect(entity_class.server).to receive(:format_request).with("foo", "bar", { baz: "biz" }, true)
97
105
  expect(entity_class.where({ baz: "biz" }, true)).to eq("this is the request")
98
106
  end
99
107
  end
@@ -106,7 +114,7 @@ describe SqlcachedClient::Entity do
106
114
  session: [[{ key: "value" }], 2, 3]
107
115
  ))
108
116
  expect(entity_class.server).to receive(:format_request).with(
109
- "foo", "bar", { baz: "biz" })
117
+ "foo", "bar", { baz: "biz" }, true)
110
118
  expect(entity_class.where({ baz: "biz" })).to be_instance_of(
111
119
  SqlcachedClient::Resultset)
112
120
  end
@@ -145,6 +153,11 @@ describe SqlcachedClient::Entity do
145
153
 
146
154
 
147
155
  describe :to_h do
148
- pending
156
+ it "should return attributes" do
157
+ entity_class = Class.new(SqlcachedClient::Entity)
158
+ h = { foo: 'bar', baz: 'biz' }
159
+ entity = entity_class.new(h)
160
+ expect(entity.to_h).to eq(h)
161
+ end
149
162
  end
150
163
  end
@@ -1,5 +1,4 @@
1
1
  require 'sqlcached_client/resultset'
2
- require 'sqlcached_client/hash_struct'
3
2
 
4
3
  describe SqlcachedClient::Resultset do
5
4
 
@@ -12,9 +11,9 @@ describe SqlcachedClient::Resultset do
12
11
 
13
12
  context "when passed entities are hashes" do
14
13
  it "should map them to instances of the entity class provided" do
15
- r = SqlcachedClient::Resultset.new(SqlcachedClient::HashStruct,
14
+ r = SqlcachedClient::Resultset.new(SqlcachedClient::Entity,
16
15
  [{ foo: 'bar' }] * 3)
17
- expect(r.entities[0]).to be_instance_of(SqlcachedClient::HashStruct)
16
+ expect(r.entities[0]).to be_instance_of(SqlcachedClient::Entity)
18
17
  end
19
18
  end
20
19
 
@@ -22,10 +22,11 @@ describe SqlcachedClient::Server do
22
22
 
23
23
  describe :format_request do
24
24
  it "should be an hash with id, template, params keys" do
25
- expect(server.format_request("foo", "bar", "baz")).to eq({
25
+ expect(server.format_request("foo", "bar", "baz", "cache")).to eq({
26
26
  queryId: "foo",
27
27
  queryTemplate: "bar",
28
- queryParams: "baz"
28
+ queryParams: "baz",
29
+ cache: "cache"
29
30
  })
30
31
  end
31
32
  end
@@ -19,6 +19,9 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "activesupport", "~> 4.2"
22
+ spec.add_dependency "arel", "~> 6.0"
23
+ spec.add_dependency "activerecord", "~> 4.2"
24
+ spec.add_dependency "activerecord-nulldb-adapter", "~> 0.3"
22
25
 
23
26
  spec.add_development_dependency "bundler", "~> 1.6"
24
27
  spec.add_development_dependency "rake"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqlcached_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roberto Maestroni
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-07 00:00:00.000000000 Z
11
+ date: 2015-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,6 +24,48 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: arel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord-nulldb-adapter
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.3'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: bundler
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -79,13 +121,12 @@ files:
79
121
  - README.md
80
122
  - Rakefile
81
123
  - lib/sqlcached_client.rb
124
+ - lib/sqlcached_client/arel.rb
82
125
  - lib/sqlcached_client/entity.rb
83
- - lib/sqlcached_client/hash_struct.rb
84
126
  - lib/sqlcached_client/resultset.rb
85
127
  - lib/sqlcached_client/server.rb
86
128
  - lib/sqlcached_client/version.rb
87
129
  - spec/sqlcached_client/entity_spec.rb
88
- - spec/sqlcached_client/hash_struct_spec.rb
89
130
  - spec/sqlcached_client/resultset_spec.rb
90
131
  - spec/sqlcached_client/server_spec.rb
91
132
  - sqlcached_client.gemspec
@@ -115,6 +156,5 @@ specification_version: 4
115
156
  summary: A Ruby client for sqlcached
116
157
  test_files:
117
158
  - spec/sqlcached_client/entity_spec.rb
118
- - spec/sqlcached_client/hash_struct_spec.rb
119
159
  - spec/sqlcached_client/resultset_spec.rb
120
160
  - spec/sqlcached_client/server_spec.rb
@@ -1,70 +0,0 @@
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
@@ -1,26 +0,0 @@
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