lhs 4.2.1 → 5.0.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: 97ecd71fe1e08636cbe1a790d4bd8c0787facbdd
4
- data.tar.gz: 932f5f517996f854e619f12dbaaea58f21205c20
3
+ metadata.gz: c11e58cb09f9ff88f5fcc1fe3c89709482fc4089
4
+ data.tar.gz: b37486d8daa8d33ddd1556f3ce5e02f637d78b54
5
5
  SHA512:
6
- metadata.gz: b1768124ad016dd853334bd431d267cf45857b68d2964695b4ce0f0475f516bb01d40b3c137a4b2d93fb8d7868ccd29a830e6401953c5a4a979769feb47cd22d
7
- data.tar.gz: b6351fc5cfee078fc8c3f64b911548e10ab72a197650f4838a666286715764a457bec28d5710229882553050bfcd84342aad3b4160fb42730adcd0d29cda4212
6
+ metadata.gz: 8a6fb56d82bb2f1807f60685b74f83226fd3a8c99b1727353e2ac6888b6491febef33c5be0d9e281eed67ddf5d657609b389a4b222150f790e3ec079e618add5
7
+ data.tar.gz: 821ac2f5ef3c9bd221937243c33634ba5ad4032311bc4f54a9db276a3b3d9ddf3414085749a389b9d4a15b0edcaae36786b53564098e5d7e94b22b5e852fde8f
data/README.md CHANGED
@@ -66,6 +66,60 @@ This uses the `:datastore/v2/feedbacks` endpoint, cause `:campaign_id` was not p
66
66
 
67
67
  Uses the `:datastore/v2/content-ads/:campaign_id/feedbacks` endpoint.
68
68
 
69
+ ## Chaining where statements
70
+
71
+ LHS supports chaining where statements.
72
+ That allows you to chain multiple where-queries:
73
+
74
+ ```ruby
75
+ class Record < LHS::Record
76
+ endpoint 'records/'
77
+ endpoint 'records/:id'
78
+ end
79
+
80
+ records = Record.where(color: 'blue')
81
+ ...
82
+ records.where(available: true).each do |record|
83
+ ...
84
+ end
85
+ ```
86
+ The example would fetch records with the following parameters: `{color: blue, available: true}`.
87
+
88
+ ## Where values hash
89
+
90
+ Returns a hash of where conditions.
91
+ Common to use in tests, as where queries are not performing any HTTP-requests when no data is accessed.
92
+
93
+ ```ruby
94
+ records = Record.where(color: 'blue').where(available: true).where(color: 'red')
95
+
96
+ expect(
97
+ records
98
+ ).to have_requested(:get, %r{records/})
99
+ .with(query: hash_including(color: 'blue', available: true))
100
+ # will fail as no http request is made (no data requested)
101
+
102
+ expect(
103
+ records.where_values_hash
104
+ ).to eq {color: 'red', available: true}
105
+ ```
106
+
107
+ ## Scopes: Reuse where statements
108
+
109
+ In order to make common where statements reusable you can organise them in scopes:
110
+
111
+ ```ruby
112
+ class Record < LHS::Record
113
+ endpoint 'records/'
114
+ endpoint 'records/:id'
115
+ scope :blue, -> { where(color: 'blue') }
116
+ scope :available, ->(state) { where(available: state) }
117
+ end
118
+
119
+ records = Record.blue.available(true)
120
+ The example would fetch records with the following parameters: `{color: blue, visible: true}`.
121
+ ```
122
+
69
123
  ## Find single records
70
124
 
71
125
  `find` finds a unique record by uniqe identifier (usualy id).
@@ -0,0 +1,23 @@
1
+ require 'active_support'
2
+
3
+ class LHS::Record
4
+
5
+ # Scopes allow you to reuse common where queries
6
+ module Scope
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def scope(name, block)
11
+ scopes[name] = block
12
+ define_singleton_method(name) do |*args|
13
+ block.call(*args)
14
+ end
15
+ end
16
+
17
+ def scopes
18
+ @scopes ||= {}
19
+ @scopes
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,11 +5,60 @@ class LHS::Record
5
5
  module Where
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ class WhereChain
9
+
10
+ # Instance exec is required for scope chains
11
+ delegated_methods = Object.instance_methods - [:instance_exec]
12
+ delegate(*delegated_methods, to: :resolve)
13
+
14
+ def initialize(record, parameters)
15
+ @record = record
16
+ @chain = [parameters].compact
17
+ end
18
+
19
+ def where(parameters)
20
+ @chain += [parameters].compact
21
+ self
22
+ end
23
+
24
+ # Returns a hash of where conditions
25
+ def where_values_hash
26
+ merged_parameters
27
+ end
28
+
29
+ protected
30
+
31
+ def method_missing(name, *args, &block)
32
+ scope = @record.scopes[name]
33
+ return instance_exec(*args, &scope) if scope
34
+ resolve.send(name, *args, &block)
35
+ end
36
+
37
+ def respond_to_missing?(name, include_all = false)
38
+ @record.scopes[name] ||
39
+ resolve.respond_to?(name, include_all)
40
+ end
41
+
42
+ def resolve
43
+ @resolved ||= @record.new(
44
+ @record.request(params: merged_parameters)
45
+ )
46
+ end
47
+
48
+ private
49
+
50
+ def merged_parameters
51
+ merged_parameters = {}
52
+ @chain.each do |parameter|
53
+ merged_parameters.deep_merge!(parameter)
54
+ end
55
+ merged_parameters
56
+ end
57
+ end
58
+
8
59
  module ClassMethods
9
- # Used to query data from the service.
10
- def where(params = {})
11
- data = request(params: params)
12
- data._record.new(data)
60
+ def where(parameters = nil)
61
+ WhereChain.new(self, parameters)
13
62
  end
14
63
  end
15
64
  end
@@ -12,6 +12,7 @@ class LHS::Record
12
12
  include Mapping
13
13
  include Model
14
14
  include Includes
15
+ include Scope
15
16
  include Request
16
17
  include Where
17
18
  include Pagination
@@ -1,3 +1,3 @@
1
1
  module LHS
2
- VERSION = "4.2.1"
2
+ VERSION = "5.0.0"
3
3
  end
@@ -0,0 +1,37 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Record do
4
+ let(:datastore) do
5
+ 'http://datastore/v2'
6
+ end
7
+
8
+ let(:response) do
9
+ { body: [{ name: 'Steve' }] }
10
+ end
11
+
12
+ before(:each) do
13
+ LHC.config.placeholder('datastore', datastore)
14
+ class Record < LHS::Record
15
+ endpoint ':datastore/records/'
16
+ scope :blue, -> { where(color: 'blue') }
17
+ scope :available, -> { where(availalbe: 'true') }
18
+ scope :limited_to, ->(limit) { where(limit: limit) }
19
+ end
20
+ end
21
+
22
+ context 'scope chains' do
23
+ it 'allows chaining multiple scopes' do
24
+ stub_request(:get, "http://datastore/v2/records/?availalbe=true&color=blue&limit=20").to_return(response)
25
+ expect(
26
+ Record.blue.available.limited_to(20).first.name
27
+ ).to eq 'Steve'
28
+ end
29
+
30
+ it 'allows to chain multiple scopes when first one has arguments' do
31
+ stub_request(:get, "http://datastore/v2/records/?availalbe=true&color=blue&limit=20").to_return(response)
32
+ expect(
33
+ Record.limited_to(20).blue.available.first.name
34
+ ).to eq 'Steve'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,55 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Record do
4
+ let(:datastore) do
5
+ 'http://datastore/v2'
6
+ end
7
+
8
+ let(:response) do
9
+ { body: [{ name: 'Steve' }] }
10
+ end
11
+
12
+ before(:each) do
13
+ LHC.config.placeholder('datastore', datastore)
14
+ class Record < LHS::Record
15
+ endpoint ':datastore/records/'
16
+
17
+ def uppercase_name
18
+ name.upcase
19
+ end
20
+ end
21
+ end
22
+
23
+ context 'where chains' do
24
+ before(:each) do
25
+ stub_request(:get, "http://datastore/v2/records/?available=true&color=blue&range=%3E26")
26
+ .to_return(response)
27
+ end
28
+
29
+ let(:records) { Record.where(color: 'blue').where(range: '>26').where(available: true) }
30
+
31
+ it 'allows chaining where statements' do
32
+ expect(records.class).to eq Record
33
+ expect(records._raw).to eq [{ name: 'Steve' }]
34
+ expect(records.first.uppercase_name).to eq 'STEVE'
35
+ end
36
+
37
+ it 'resolves triggered by method missing' do
38
+ expect(records._raw).to eq [{ name: 'Steve' }]
39
+ expect(
40
+ Record.where(color: 'blue').where(range: '>26', available: true).first.name
41
+ ).to eq 'Steve'
42
+ end
43
+ end
44
+
45
+ context 'multiple parameters' do
46
+ before(:each) do
47
+ stub_request(:get, "http://datastore/v2/records/?parameter=last").to_return(response)
48
+ end
49
+
50
+ it 'takes the last value for chains with same name parameters' do
51
+ records = Record.where(parameter: 'first').where(parameter: 'last')
52
+ records.first
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ require 'rails_helper'
2
+
3
+ describe LHS::Record do
4
+ let(:datastore) do
5
+ 'http://datastore/v2'
6
+ end
7
+
8
+ let(:response) do
9
+ { body: [{ name: 'Steve' }] }
10
+ end
11
+
12
+ before(:each) do
13
+ LHC.config.placeholder('datastore', datastore)
14
+ class Record < LHS::Record
15
+ endpoint ':datastore/records/'
16
+ end
17
+ end
18
+
19
+ context 'where values hash' do
20
+ it 'provides the hash or where parameters that have been requested' do
21
+ stub_request(:get, "http://datastore/v2/records/?available=true&color=blue").to_return(response)
22
+ expect(
23
+ Record.where(available: true).where(color: 'blue').where_values_hash
24
+ ).to eq(available: true, color: 'blue')
25
+ expect(
26
+ Record.where(available: true, color: 'red').where(color: 'blue').where_values_hash
27
+ ).to eq(available: true, color: 'blue')
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lhs
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/local-ch/lhs/graphs/contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-20 00:00:00.000000000 Z
11
+ date: 2016-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lhc
@@ -197,6 +197,7 @@ files:
197
197
  - lib/lhs/concerns/record/model.rb
198
198
  - lib/lhs/concerns/record/pagination.rb
199
199
  - lib/lhs/concerns/record/request.rb
200
+ - lib/lhs/concerns/record/scope.rb
200
201
  - lib/lhs/concerns/record/where.rb
201
202
  - lib/lhs/data.rb
202
203
  - lib/lhs/endpoint.rb
@@ -298,9 +299,12 @@ files:
298
299
  - spec/record/persisted_spec.rb
299
300
  - spec/record/request_spec.rb
300
301
  - spec/record/save_spec.rb
302
+ - spec/record/scope_chains_spec.rb
301
303
  - spec/record/select_spec.rb
302
304
  - spec/record/to_json_spec.rb
305
+ - spec/record/where_chains_spec.rb
303
306
  - spec/record/where_spec.rb
307
+ - spec/record/where_values_hash_spec.rb
304
308
  - spec/spec_helper.rb
305
309
  - spec/support/cleanup_configuration.rb
306
310
  - spec/support/cleanup_endpoints.rb
@@ -330,7 +334,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
330
334
  requirements:
331
335
  - Ruby >= 1.9.2
332
336
  rubyforge_project:
333
- rubygems_version: 2.4.8
337
+ rubygems_version: 2.2.2
334
338
  signing_key:
335
339
  specification_version: 4
336
340
  summary: Rails gem providing an easy, active-record-like interface for http json services
@@ -425,9 +429,12 @@ test_files:
425
429
  - spec/record/persisted_spec.rb
426
430
  - spec/record/request_spec.rb
427
431
  - spec/record/save_spec.rb
432
+ - spec/record/scope_chains_spec.rb
428
433
  - spec/record/select_spec.rb
429
434
  - spec/record/to_json_spec.rb
435
+ - spec/record/where_chains_spec.rb
430
436
  - spec/record/where_spec.rb
437
+ - spec/record/where_values_hash_spec.rb
431
438
  - spec/spec_helper.rb
432
439
  - spec/support/cleanup_configuration.rb
433
440
  - spec/support/cleanup_endpoints.rb