lhs 19.9.0 → 20.1.4
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 +4 -4
- data/Gemfile +0 -9
- data/README.md +74 -5
- data/lhs.gemspec +3 -0
- data/lib/lhs.rb +18 -0
- data/lib/lhs/concerns/option_blocks.rb +2 -1
- data/lib/lhs/concerns/record/request.rb +4 -4
- data/lib/lhs/interceptors/extended_rollbar/handler.rb +40 -0
- data/lib/lhs/interceptors/extended_rollbar/interceptor.rb +20 -0
- data/lib/lhs/interceptors/extended_rollbar/thread_registry.rb +19 -0
- data/lib/lhs/interceptors/request_cycle_cache/interceptor.rb +41 -0
- data/lib/lhs/interceptors/request_cycle_cache/thread_registry.rb +18 -0
- data/lib/lhs/railtie.rb +8 -1
- data/lib/lhs/record.rb +0 -8
- data/lib/lhs/rspec.rb +19 -0
- data/lib/lhs/test/stub.rb +29 -0
- data/lib/lhs/version.rb +1 -1
- data/spec/dummy/app/controllers/extended_rollbar_controller.rb +10 -0
- data/spec/dummy/config/initializers/rollbar.rb +9 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/extended_rollbar_spec.rb +67 -0
- data/spec/rails_helper.rb +2 -0
- data/spec/request_cycle_cache_spec.rb +4 -4
- data/spec/stubs/all_spec.rb +49 -0
- metadata +60 -7
- data/lib/lhs/concerns/record/request_cycle_cache/interceptor.rb +0 -40
- data/lib/lhs/concerns/record/request_cycle_cache/request_cycle_thread_registry.rb +0 -15
- data/lib/lhs/test/request_cycle_cache_helper.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90bb5680db8b584ee9597cf6e3029014f05a56704de09cecb8f4b9788ff0bbdf
|
4
|
+
data.tar.gz: 1403e9844367ef3cc13c2987368d219b12db90700178b26bfacba1f3690346f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c8c37a17da7d96fb7f397425dcf74440e3a3d3a562eecf142992546b58c07cefa7527166b8ba26131e3e025ca823b3d78c3f98a1d8cb0c974394e9887b623c6
|
7
|
+
data.tar.gz: 187cf1be11baf4d8c32cb9521e4eeb283152b5b026b06e67d2e548deb649c36957fc6fa91b2d5d577e45de90382faf4fed80dd999cdfad161ae647753df28a94
|
data/Gemfile
CHANGED
@@ -1,13 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
source 'https://rubygems.org/'
|
4
|
-
|
5
|
-
# Declare your gem's dependencies in lhs.gemspec.
|
6
|
-
# Bundler will treat runtime dependencies like base dependencies, and
|
7
|
-
# development dependencies will be added by default to the :development group.
|
8
4
|
gemspec
|
9
|
-
|
10
|
-
# Declare any dependencies that are still in development here instead of in
|
11
|
-
# your gemspec. These might include edge Rails or gems from your path or
|
12
|
-
# Git. Remember to move these dependencies to your gemspec before releasing
|
13
|
-
# your gem to rubygems.org.
|
data/README.md
CHANGED
@@ -119,6 +119,7 @@ record.review # "Lunch was great
|
|
119
119
|
* [Record setters](#record-setters)
|
120
120
|
* [Record getters](#record-getters)
|
121
121
|
* [Include linked resources (hyperlinks and hypermedia)](#include-linked-resources-hyperlinks-and-hypermedia)
|
122
|
+
* [Generate links from parameters](#generate-links-from-parameters)
|
122
123
|
* [Ensure the whole linked collection is included: includes_all](#ensure-the-whole-linked-collection-is-included-includes_all)
|
123
124
|
* [Include the first linked page or single item is included: include](#include-the-first-linked-page-or-single-item-is-included-include)
|
124
125
|
* [Include various levels of linked data](#include-various-levels-of-linked-data)
|
@@ -136,8 +137,11 @@ record.review # "Lunch was great
|
|
136
137
|
* [Disable request cycle cache](#disable-request-cycle-cache)
|
137
138
|
* [Option Blocks](#option-blocks)
|
138
139
|
* [Request tracing](#request-tracing)
|
140
|
+
* [Extended Rollbar Logging](#extended-rollbar-logging)
|
139
141
|
* [Testing with LHS](#testing-with-lhs)
|
140
|
-
* [Test helper
|
142
|
+
* [Test helper](#test-helper)
|
143
|
+
* [Stub](#stub)
|
144
|
+
* [Stub All](#stub-all)
|
141
145
|
* [Test query chains](#test-query-chains)
|
142
146
|
* [By explicitly resolving the chain: fetch](#by-explicitly-resolving-the-chain-fetch)
|
143
147
|
* [Without resolving the chain: where_values_hash](#without-resolving-the-chain-where_values_hash)
|
@@ -1627,6 +1631,15 @@ POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'name': 'Starbuck
|
|
1627
1631
|
|
1628
1632
|
-> See [record validation](#record-validation) for how to handle validation errors when updating records.
|
1629
1633
|
|
1634
|
+
You can also pass explicit request options to `update`, by passing two explicit hashes:
|
1635
|
+
|
1636
|
+
```ruby
|
1637
|
+
# app/controllers/some_controller.rb
|
1638
|
+
|
1639
|
+
record.update({ recommended: true }, { method: 'put' })
|
1640
|
+
|
1641
|
+
```
|
1642
|
+
|
1630
1643
|
##### partial_update
|
1631
1644
|
|
1632
1645
|
`partial_update` updates just the provided parameters.
|
@@ -1658,6 +1671,15 @@ POST https://service.example.com/records/1z-5r1fkaj { body: "{ 'name': 'Starbuck
|
|
1658
1671
|
|
1659
1672
|
-> See [record validation](#record-validation) for how to handle validation errors when updating records.
|
1660
1673
|
|
1674
|
+
You can also pass explicit request options to `partial_update`, by passing two explicit hashes:
|
1675
|
+
|
1676
|
+
```ruby
|
1677
|
+
# app/controllers/some_controller.rb
|
1678
|
+
|
1679
|
+
record.partial_update({ recommended: true }, { method: 'put' })
|
1680
|
+
|
1681
|
+
```
|
1682
|
+
|
1661
1683
|
#### Endpoint url parameter injection during record creation/change
|
1662
1684
|
|
1663
1685
|
LHS injects parameters provided to `create`, `update`, `partial_update`, `save` etc. into an endpoint's URL when matching:
|
@@ -2443,6 +2465,26 @@ code.places
|
|
2443
2465
|
}
|
2444
2466
|
```
|
2445
2467
|
|
2468
|
+
## Extended Rollbar Logging
|
2469
|
+
|
2470
|
+
In order to log all requests/responses prior to an exception reported by Rollbar in addition to the exception itself, use the `LHS::ExtendedRollbar` interceptor in combination with the rollbar processor/handler:
|
2471
|
+
|
2472
|
+
```ruby
|
2473
|
+
# config/initializers/lhc.rb
|
2474
|
+
|
2475
|
+
LHC.configure do |config|
|
2476
|
+
config.interceptors = [LHS::ExtendedRollbar]
|
2477
|
+
end
|
2478
|
+
```
|
2479
|
+
|
2480
|
+
```ruby
|
2481
|
+
# config/initializers/rollbar.rb
|
2482
|
+
|
2483
|
+
Rollbar.configure do |config|
|
2484
|
+
config.before_process << LHS::Interceptors::ExtendedRollbar::Handler.init
|
2485
|
+
end
|
2486
|
+
```
|
2487
|
+
|
2446
2488
|
## Testing with LHS
|
2447
2489
|
|
2448
2490
|
**Best practice in regards of testing applications using LHS, is to let LHS fetch your records, actually perform HTTP requests and [WebMock](https://github.com/bblimke/webmock) to stub/mock those http requests/responses.**
|
@@ -2480,17 +2522,44 @@ it 'displays contracts' do
|
|
2480
2522
|
end
|
2481
2523
|
```
|
2482
2524
|
|
2483
|
-
### Test helper
|
2525
|
+
### Test helper
|
2484
2526
|
|
2485
|
-
In order to
|
2527
|
+
In order to load LHS test helpers into your tests, add the following to your spec helper:
|
2486
2528
|
|
2487
2529
|
```ruby
|
2488
2530
|
# spec/spec_helper.rb
|
2489
2531
|
|
2490
|
-
require 'lhs/
|
2532
|
+
require 'lhs/rspec'
|
2491
2533
|
```
|
2492
2534
|
|
2493
|
-
This will
|
2535
|
+
This e.g. will prevent running into caching issues during your tests, when (request cycle cache)[#request-cycle-cache] is enabled.
|
2536
|
+
It will initialize a MemoryStore cache for LHC::Caching interceptor and resets the cache before every test.
|
2537
|
+
|
2538
|
+
#### Stub
|
2539
|
+
|
2540
|
+
LHS offers stub helpers that simplify stubbing https request to your apis.
|
2541
|
+
|
2542
|
+
##### Stub All
|
2543
|
+
|
2544
|
+
`LHS.stub.all(url, items, additional_options)`
|
2545
|
+
|
2546
|
+
```ruby
|
2547
|
+
# your_spec.rb
|
2548
|
+
|
2549
|
+
before do
|
2550
|
+
LHS.stub.all(
|
2551
|
+
'https://records',
|
2552
|
+
200.times.map{ |index| { name: "Item #{index}" } },
|
2553
|
+
headers: {
|
2554
|
+
'Authorization' => 'Bearer 123'
|
2555
|
+
}
|
2556
|
+
)
|
2557
|
+
end
|
2558
|
+
```
|
2559
|
+
```
|
2560
|
+
GET https://records?limit=100
|
2561
|
+
GET https://records?limit=100&offset=100
|
2562
|
+
```
|
2494
2563
|
|
2495
2564
|
### Test query chains
|
2496
2565
|
|
data/lhs.gemspec
CHANGED
@@ -25,15 +25,18 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_dependency 'activemodel'
|
26
26
|
s.add_dependency 'activesupport', '>= 4.2.11'
|
27
27
|
s.add_dependency 'lhc', '~> 10.2'
|
28
|
+
s.add_dependency 'local_uri'
|
28
29
|
|
29
30
|
s.add_development_dependency 'capybara'
|
30
31
|
s.add_development_dependency 'json', '>= 1.8.2'
|
31
32
|
s.add_development_dependency 'pry'
|
32
33
|
s.add_development_dependency 'pry-byebug'
|
33
34
|
s.add_development_dependency 'rails', '>= 4.2.11'
|
35
|
+
s.add_development_dependency 'rollbar'
|
34
36
|
s.add_development_dependency 'rspec-rails', '>= 3.7.0'
|
35
37
|
s.add_development_dependency 'rubocop', '~> 0.57.1'
|
36
38
|
s.add_development_dependency 'rubocop-rspec', '~> 1.26.0'
|
39
|
+
s.add_development_dependency 'sprockets', '< 4'
|
37
40
|
s.add_development_dependency 'webmock'
|
38
41
|
|
39
42
|
s.license = 'GPL-3'
|
data/lib/lhs.rb
CHANGED
@@ -15,10 +15,28 @@ module LHS
|
|
15
15
|
'lhs/config'
|
16
16
|
autoload :Data,
|
17
17
|
'lhs/data'
|
18
|
+
autoload :ExtendedRollbar,
|
19
|
+
'lhs/interceptors/extended_rollbar/interceptor'
|
18
20
|
autoload :Endpoint,
|
19
21
|
'lhs/endpoint'
|
20
22
|
autoload :Inspect,
|
21
23
|
'lhs/concerns/inspect'
|
24
|
+
module Interceptors
|
25
|
+
module RequestCycleCache
|
26
|
+
autoload :ThreadRegistry,
|
27
|
+
'lhs/interceptors/request_cycle_cache/thread_registry'
|
28
|
+
autoload :Interceptor,
|
29
|
+
'lhs/interceptors/request_cycle_cache/interceptor'
|
30
|
+
end
|
31
|
+
module ExtendedRollbar
|
32
|
+
autoload :ThreadRegistry,
|
33
|
+
'lhs/interceptors/extended_rollbar/thread_registry'
|
34
|
+
autoload :Interceptor,
|
35
|
+
'lhs/interceptors/extended_rollbar/interceptor'
|
36
|
+
autoload :Handler,
|
37
|
+
'lhs/interceptors/extended_rollbar/handler'
|
38
|
+
end
|
39
|
+
end
|
22
40
|
autoload :IsHref,
|
23
41
|
'lhs/concerns/is_href'
|
24
42
|
autoload :Item,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_support'
|
4
|
+
require 'active_support/per_thread_registry'
|
4
5
|
|
5
6
|
module LHS
|
6
7
|
module OptionBlocks
|
@@ -8,7 +9,7 @@ module LHS
|
|
8
9
|
|
9
10
|
class CurrentOptionBlock
|
10
11
|
# Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
|
11
|
-
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support
|
12
|
+
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v4.
|
12
13
|
extend ActiveSupport::PerThreadRegistry
|
13
14
|
attr_accessor :options
|
14
15
|
end
|
@@ -509,16 +509,16 @@ class LHS::Record
|
|
509
509
|
options
|
510
510
|
end
|
511
511
|
|
512
|
-
# Injects options into request, that enable the
|
512
|
+
# Injects options into request, that enable the request cycle cache interceptor
|
513
513
|
def inject_request_cycle_cache!(options)
|
514
514
|
return unless LHS.config.request_cycle_cache_enabled
|
515
515
|
interceptors = options[:interceptors] || LHC.config.interceptors
|
516
516
|
if interceptors.include?(LHC::Caching)
|
517
|
-
# Ensure
|
518
|
-
interceptors = interceptors.unshift(LHS::
|
517
|
+
# Ensure interceptor is prepend
|
518
|
+
interceptors = interceptors.unshift(LHS::Interceptors::RequestCycleCache::Interceptor)
|
519
519
|
options[:interceptors] = interceptors
|
520
520
|
else
|
521
|
-
warn("[WARNING] Can't enable
|
521
|
+
warn("[WARNING] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured (see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor)!")
|
522
522
|
end
|
523
523
|
end
|
524
524
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LHS
|
4
|
+
module Interceptors
|
5
|
+
module ExtendedRollbar
|
6
|
+
class Handler
|
7
|
+
|
8
|
+
def self.init
|
9
|
+
proc do |options|
|
10
|
+
# as handlers cant influence what actually is reported to rollbar
|
11
|
+
# this just makes sure that Rollbar is already loaded when this class is loaded,
|
12
|
+
# so that we can extend rollbar loging
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ExtendedLogging
|
17
|
+
def log(level, *args)
|
18
|
+
args[2] = {} if args[2].nil?
|
19
|
+
args[2][:lhs] = LHS::Interceptors::ExtendedRollbar::ThreadRegistry.log.map do |entry|
|
20
|
+
{
|
21
|
+
request: entry[:request].options,
|
22
|
+
response: {
|
23
|
+
code: entry[:response].code,
|
24
|
+
body: entry[:response].body
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end.to_json
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module ::Rollbar
|
33
|
+
class Notifier
|
34
|
+
prepend LHS::Interceptors::ExtendedRollbar::Handler::ExtendedLogging
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module LHS
|
6
|
+
module Interceptors
|
7
|
+
module ExtendedRollbar
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class Interceptor < LHC::Interceptor
|
11
|
+
def after_response
|
12
|
+
return unless LHS::Interceptors::ExtendedRollbar::ThreadRegistry.log
|
13
|
+
LHS::Interceptors::ExtendedRollbar::ThreadRegistry.log.push(request: request, response: response)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
const_set('ExtendedRollbar', LHS::Interceptors::ExtendedRollbar::Interceptor)
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/per_thread_registry'
|
5
|
+
|
6
|
+
module LHS
|
7
|
+
module Interceptors
|
8
|
+
module ExtendedRollbar
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
class ThreadRegistry
|
12
|
+
# Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
|
13
|
+
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v4.
|
14
|
+
extend ActiveSupport::PerThreadRegistry
|
15
|
+
attr_accessor :log
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module LHS
|
6
|
+
module Interceptors
|
7
|
+
module RequestCycleCache
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class Interceptor < LHC::Interceptor
|
11
|
+
|
12
|
+
VERSION = 1
|
13
|
+
CACHED_METHODS = [:get].freeze
|
14
|
+
|
15
|
+
def before_request
|
16
|
+
request.options = {
|
17
|
+
cache: {
|
18
|
+
expires_in: 5.minutes,
|
19
|
+
race_condition_ttl: 5.seconds,
|
20
|
+
key: cache_key_for(request),
|
21
|
+
methods: CACHED_METHODS,
|
22
|
+
use: LHS.config.request_cycle_cache
|
23
|
+
}
|
24
|
+
}.merge(request.options)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def cache_key_for(request)
|
30
|
+
[
|
31
|
+
"LHS_REQUEST_CYCLE_CACHE(v#{VERSION})",
|
32
|
+
request.method.upcase,
|
33
|
+
[request.url, request.params.presence].compact.join('?'),
|
34
|
+
"REQUEST=#{LHS::Interceptors::RequestCycleCache::ThreadRegistry.request_id}",
|
35
|
+
"HEADERS=#{request.headers.hash}"
|
36
|
+
].join(' ')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/per_thread_registry'
|
5
|
+
|
6
|
+
module LHS
|
7
|
+
module Interceptors
|
8
|
+
module RequestCycleCache
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
class ThreadRegistry
|
11
|
+
# Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
|
12
|
+
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v4.
|
13
|
+
extend ActiveSupport::PerThreadRegistry
|
14
|
+
attr_accessor :request_id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/lhs/railtie.rb
CHANGED
@@ -8,6 +8,7 @@ module LHS
|
|
8
8
|
def initialize
|
9
9
|
prepare_lhs_request_cycle_cache
|
10
10
|
reset_option_blocks
|
11
|
+
reset_extended_rollbar_request_logs
|
11
12
|
super
|
12
13
|
end
|
13
14
|
|
@@ -15,12 +16,18 @@ module LHS
|
|
15
16
|
|
16
17
|
def prepare_lhs_request_cycle_cache
|
17
18
|
return unless LHS.config.request_cycle_cache_enabled
|
18
|
-
LHS::
|
19
|
+
LHS::Interceptors::RequestCycleCache::ThreadRegistry.request_id = [Time.now.to_f, request.object_id].join('#')
|
19
20
|
end
|
20
21
|
|
21
22
|
def reset_option_blocks
|
22
23
|
LHS::OptionBlocks::CurrentOptionBlock.options = nil
|
23
24
|
end
|
25
|
+
|
26
|
+
def reset_extended_rollbar_request_logs
|
27
|
+
return unless defined?(::Rollbar)
|
28
|
+
return unless LHC.config.interceptors.include?(LHS::Interceptors::ExtendedRollbar::Interceptor)
|
29
|
+
LHS::Interceptors::ExtendedRollbar::ThreadRegistry.log = []
|
30
|
+
end
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
data/lib/lhs/record.rb
CHANGED
@@ -48,13 +48,6 @@ class LHS::Record
|
|
48
48
|
autoload :AttributeAssignment,
|
49
49
|
'lhs/concerns/record/attribute_assignment'
|
50
50
|
|
51
|
-
module RequestCycleCache
|
52
|
-
autoload :RequestCycleThreadRegistry,
|
53
|
-
'lhs/concerns/record/request_cycle_cache/request_cycle_thread_registry'
|
54
|
-
autoload :Interceptor,
|
55
|
-
'lhs/concerns/record/request_cycle_cache/interceptor'
|
56
|
-
end
|
57
|
-
|
58
51
|
include Batch
|
59
52
|
include Chainable
|
60
53
|
include Configuration
|
@@ -77,7 +70,6 @@ class LHS::Record
|
|
77
70
|
include Provider
|
78
71
|
include Request
|
79
72
|
include Relations
|
80
|
-
include RequestCycleCache
|
81
73
|
include Scope
|
82
74
|
include Tracing
|
83
75
|
include AttributeAssignment
|
data/lib/lhs/rspec.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'lhs'
|
4
|
+
require 'lhs/test/stub'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.before(:each) do
|
8
|
+
LHS.config.request_cycle_cache.clear
|
9
|
+
end
|
10
|
+
|
11
|
+
config.before(:all) do
|
12
|
+
|
13
|
+
module LHS
|
14
|
+
def self.stub
|
15
|
+
LHS::Test::Stub
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'local_uri'
|
4
|
+
require 'webmock'
|
5
|
+
module LHS
|
6
|
+
module Test
|
7
|
+
class Stub
|
8
|
+
extend WebMock::API
|
9
|
+
DEFAULT_LIMIT = LHS::Pagination::Base::DEFAULT_LIMIT
|
10
|
+
|
11
|
+
def self.all(url, items, options = {})
|
12
|
+
items.each_slice(DEFAULT_LIMIT).with_index do |(*batch), index|
|
13
|
+
uri = LocalUri::URI.new(url)
|
14
|
+
uri.query.merge!(limit: DEFAULT_LIMIT)
|
15
|
+
uri.query.merge!(offset: DEFAULT_LIMIT * index) unless index.zero?
|
16
|
+
request_stub = stub_request(:get, uri.to_s)
|
17
|
+
request_stub.with(options) if options.present?
|
18
|
+
request_stub.to_return(
|
19
|
+
body: {
|
20
|
+
items: batch,
|
21
|
+
offset: index * DEFAULT_LIMIT,
|
22
|
+
total: items.length
|
23
|
+
}.to_json
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/lhs/version.rb
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ExtendedRollbarController < ApplicationController
|
4
|
+
|
5
|
+
def extended_rollbar
|
6
|
+
Record.where(color: 'blue').fetch
|
7
|
+
Record.where(color: 'red').fetch
|
8
|
+
raise "Let's see if rollbar logs information about what kind of requests where made around here!"
|
9
|
+
end
|
10
|
+
end
|
data/spec/dummy/config/routes.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
describe 'Extended Rollbar', type: :request do
|
6
|
+
let!(:records_request_1) do
|
7
|
+
stub_request(:get, "http://datastore/v2/records?color=blue").to_return(body: ['blue'].to_json)
|
8
|
+
end
|
9
|
+
|
10
|
+
let!(:records_request_2) do
|
11
|
+
stub_request(:get, "http://datastore/v2/records?color=red").to_return(body: ['red'].to_json)
|
12
|
+
end
|
13
|
+
|
14
|
+
let!(:rollbar_request) do
|
15
|
+
stub_request(:post, "https://api.rollbar.com/api/1/item/")
|
16
|
+
.with do |request|
|
17
|
+
json = JSON.parse request.body
|
18
|
+
message = "Let's see if rollbar logs information about what kind of requests where made around here!"
|
19
|
+
extra = {
|
20
|
+
lhs: [
|
21
|
+
{
|
22
|
+
request: {
|
23
|
+
params: { color: 'blue' },
|
24
|
+
url: 'http://datastore/v2/records',
|
25
|
+
headers: {
|
26
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
27
|
+
'Accept' => 'application/json,application/vnd.api+json',
|
28
|
+
'Accept-Charset' => 'utf-8'
|
29
|
+
}
|
30
|
+
},
|
31
|
+
response: { code: 200, body: '["blue"]' }
|
32
|
+
}, {
|
33
|
+
request: {
|
34
|
+
params: { color: 'red' },
|
35
|
+
url: 'http://datastore/v2/records',
|
36
|
+
headers: {
|
37
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
38
|
+
'Accept' => 'application/json,application/vnd.api+json',
|
39
|
+
'Accept-Charset' => 'utf-8'
|
40
|
+
}
|
41
|
+
},
|
42
|
+
response: { code: 200, body: '["red"]' }
|
43
|
+
}
|
44
|
+
].to_json
|
45
|
+
}
|
46
|
+
json['access_token'] == '12345' &&
|
47
|
+
json['data']['level'] == 'error' &&
|
48
|
+
json['data']['body']['trace']['exception']['message'] == message &&
|
49
|
+
json['data']['body']['trace']['extra'].to_json == extra.to_json
|
50
|
+
end
|
51
|
+
.to_return(status: 200)
|
52
|
+
end
|
53
|
+
|
54
|
+
before do
|
55
|
+
LHC.configure do |config|
|
56
|
+
config.interceptors = [LHS::ExtendedRollbar]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'extends default rollbar logging by adding information about the requests made during a request/response cycle',
|
61
|
+
dummy_models: true, extended_rollbar: true do
|
62
|
+
get '/extended_rollbar'
|
63
|
+
expect(records_request_1).to have_been_requested
|
64
|
+
expect(records_request_2).to have_been_requested
|
65
|
+
expect(rollbar_request).to have_been_requested
|
66
|
+
end
|
67
|
+
end
|
data/spec/rails_helper.rb
CHANGED
@@ -37,7 +37,7 @@ describe 'Request Cycle Cache', type: :request do
|
|
37
37
|
expect(lambda do
|
38
38
|
get '/request_cycle_cache/no_caching_interceptor'
|
39
39
|
end).to output(
|
40
|
-
%r{\[WARNING\] Can't enable
|
40
|
+
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor\)!}
|
41
41
|
).to_stderr
|
42
42
|
expect(request).to have_been_made.times(2)
|
43
43
|
end
|
@@ -52,11 +52,11 @@ describe 'Request Cycle Cache', type: :request do
|
|
52
52
|
it 'sets different uniq request ids as base for request cycle caching for different requests',
|
53
53
|
dummy_models: true, request_cycle_cache: true do
|
54
54
|
get '/request_cycle_cache/simple'
|
55
|
-
first_request_id = LHS::
|
55
|
+
first_request_id = LHS::Interceptors::RequestCycleCache::ThreadRegistry.request_id
|
56
56
|
second_request_id = nil
|
57
57
|
thread = Thread.new do
|
58
58
|
get '/request_cycle_cache/simple'
|
59
|
-
second_request_id = LHS::
|
59
|
+
second_request_id = LHS::Interceptors::RequestCycleCache::ThreadRegistry.request_id
|
60
60
|
end
|
61
61
|
thread.join
|
62
62
|
expect(first_request_id).not_to be_nil
|
@@ -70,7 +70,7 @@ describe 'Request Cycle Cache', type: :request do
|
|
70
70
|
expect(lambda do
|
71
71
|
get '/request_cycle_cache/no_caching_interceptor'
|
72
72
|
end).not_to output(
|
73
|
-
%r{\[WARNING\] Can't enable
|
73
|
+
%r{\[WARNING\] Can't enable request cycle cache as LHC::Caching interceptor is not enabled/configured \(see https://github.com/local-ch/lhc/blob/master/docs/interceptors/caching.md#caching-interceptor\)!}
|
74
74
|
).to_stderr
|
75
75
|
expect(request).to have_been_made.times(2)
|
76
76
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
require 'lhs/rspec'
|
5
|
+
|
6
|
+
describe LHS do
|
7
|
+
|
8
|
+
before do
|
9
|
+
class Record < LHS::Record
|
10
|
+
endpoint 'https://records'
|
11
|
+
end
|
12
|
+
|
13
|
+
LHS.stub.all(
|
14
|
+
'https://records',
|
15
|
+
200.times.map { |index| { name: "Item #{index}" } },
|
16
|
+
headers: {
|
17
|
+
'Authorization' => 'Bearer 123'
|
18
|
+
}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'stubs all requests' do
|
23
|
+
records = Record.options(headers: { 'Authorization' => 'Bearer 123' }).all.fetch
|
24
|
+
expect(records.count).to eq 200
|
25
|
+
expect(records.length).to eq 200
|
26
|
+
expect(records.first.name).to eq 'Item 0'
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'without conditions' do
|
30
|
+
|
31
|
+
before do
|
32
|
+
class Record < LHS::Record
|
33
|
+
endpoint 'https://records'
|
34
|
+
end
|
35
|
+
|
36
|
+
LHS.stub.all(
|
37
|
+
'https://records',
|
38
|
+
200.times.map { |index| { name: "Item #{index}" } }
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'stubs all requests without a webmock "with"' do
|
43
|
+
records = Record.all.fetch
|
44
|
+
expect(records.count).to eq 200
|
45
|
+
expect(records.length).to eq 200
|
46
|
+
expect(records.first.name).to eq 'Item 0'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
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
|
+
version: 20.1.4
|
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: 2019-
|
11
|
+
date: 2019-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: local_uri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: capybara
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +136,20 @@ dependencies:
|
|
122
136
|
- - ">="
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: 4.2.11
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rollbar
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
125
153
|
- !ruby/object:Gem::Dependency
|
126
154
|
name: rspec-rails
|
127
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +192,20 @@ dependencies:
|
|
164
192
|
- - "~>"
|
165
193
|
- !ruby/object:Gem::Version
|
166
194
|
version: 1.26.0
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: sprockets
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "<"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '4'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "<"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '4'
|
167
209
|
- !ruby/object:Gem::Dependency
|
168
210
|
name: webmock
|
169
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -261,13 +303,16 @@ files:
|
|
261
303
|
- lib/lhs/concerns/record/provider.rb
|
262
304
|
- lib/lhs/concerns/record/relations.rb
|
263
305
|
- lib/lhs/concerns/record/request.rb
|
264
|
-
- lib/lhs/concerns/record/request_cycle_cache/interceptor.rb
|
265
|
-
- lib/lhs/concerns/record/request_cycle_cache/request_cycle_thread_registry.rb
|
266
306
|
- lib/lhs/concerns/record/scope.rb
|
267
307
|
- lib/lhs/concerns/record/tracing.rb
|
268
308
|
- lib/lhs/config.rb
|
269
309
|
- lib/lhs/data.rb
|
270
310
|
- lib/lhs/endpoint.rb
|
311
|
+
- lib/lhs/interceptors/extended_rollbar/handler.rb
|
312
|
+
- lib/lhs/interceptors/extended_rollbar/interceptor.rb
|
313
|
+
- lib/lhs/interceptors/extended_rollbar/thread_registry.rb
|
314
|
+
- lib/lhs/interceptors/request_cycle_cache/interceptor.rb
|
315
|
+
- lib/lhs/interceptors/request_cycle_cache/thread_registry.rb
|
271
316
|
- lib/lhs/item.rb
|
272
317
|
- lib/lhs/pagination/base.rb
|
273
318
|
- lib/lhs/pagination/link.rb
|
@@ -283,7 +328,8 @@ files:
|
|
283
328
|
- lib/lhs/proxy.rb
|
284
329
|
- lib/lhs/railtie.rb
|
285
330
|
- lib/lhs/record.rb
|
286
|
-
- lib/lhs/
|
331
|
+
- lib/lhs/rspec.rb
|
332
|
+
- lib/lhs/test/stub.rb
|
287
333
|
- lib/lhs/unprocessable.rb
|
288
334
|
- lib/lhs/version.rb
|
289
335
|
- script/ci/build.sh
|
@@ -322,6 +368,7 @@ files:
|
|
322
368
|
- spec/dummy/app/controllers/application_controller.rb
|
323
369
|
- spec/dummy/app/controllers/concerns/.keep
|
324
370
|
- spec/dummy/app/controllers/error_handling_with_chains_controller.rb
|
371
|
+
- spec/dummy/app/controllers/extended_rollbar_controller.rb
|
325
372
|
- spec/dummy/app/controllers/option_blocks_controller.rb
|
326
373
|
- spec/dummy/app/controllers/request_cycle_cache_controller.rb
|
327
374
|
- spec/dummy/app/helpers/application_helper.rb
|
@@ -350,6 +397,7 @@ files:
|
|
350
397
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
351
398
|
- spec/dummy/config/initializers/inflections.rb
|
352
399
|
- spec/dummy/config/initializers/mime_types.rb
|
400
|
+
- spec/dummy/config/initializers/rollbar.rb
|
353
401
|
- spec/dummy/config/initializers/session_store.rb
|
354
402
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
355
403
|
- spec/dummy/config/locales/en.yml
|
@@ -362,6 +410,7 @@ files:
|
|
362
410
|
- spec/dummy/public/500.html
|
363
411
|
- spec/dummy/public/favicon.ico
|
364
412
|
- spec/endpoint/for_url_spec.rb
|
413
|
+
- spec/extended_rollbar_spec.rb
|
365
414
|
- spec/item/access_errors_spec.rb
|
366
415
|
- spec/item/accessors_spec.rb
|
367
416
|
- spec/item/add_error_spec.rb
|
@@ -467,6 +516,7 @@ files:
|
|
467
516
|
- spec/request_cycle_cache_spec.rb
|
468
517
|
- spec/require_lhs_spec.rb
|
469
518
|
- spec/spec_helper.rb
|
519
|
+
- spec/stubs/all_spec.rb
|
470
520
|
- spec/support/fixtures/json/feedback.json
|
471
521
|
- spec/support/fixtures/json/feedbacks.json
|
472
522
|
- spec/support/fixtures/json/localina_content_ad.json
|
@@ -494,8 +544,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
494
544
|
version: '0'
|
495
545
|
requirements:
|
496
546
|
- Ruby >= 2.3.0
|
497
|
-
|
498
|
-
rubygems_version: 2.7.8
|
547
|
+
rubygems_version: 3.0.6
|
499
548
|
signing_key:
|
500
549
|
specification_version: 4
|
501
550
|
summary: 'REST services accelerator: Rails gem providing an easy, active-record-like
|
@@ -535,6 +584,7 @@ test_files:
|
|
535
584
|
- spec/dummy/app/controllers/application_controller.rb
|
536
585
|
- spec/dummy/app/controllers/concerns/.keep
|
537
586
|
- spec/dummy/app/controllers/error_handling_with_chains_controller.rb
|
587
|
+
- spec/dummy/app/controllers/extended_rollbar_controller.rb
|
538
588
|
- spec/dummy/app/controllers/option_blocks_controller.rb
|
539
589
|
- spec/dummy/app/controllers/request_cycle_cache_controller.rb
|
540
590
|
- spec/dummy/app/helpers/application_helper.rb
|
@@ -563,6 +613,7 @@ test_files:
|
|
563
613
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
564
614
|
- spec/dummy/config/initializers/inflections.rb
|
565
615
|
- spec/dummy/config/initializers/mime_types.rb
|
616
|
+
- spec/dummy/config/initializers/rollbar.rb
|
566
617
|
- spec/dummy/config/initializers/session_store.rb
|
567
618
|
- spec/dummy/config/initializers/wrap_parameters.rb
|
568
619
|
- spec/dummy/config/locales/en.yml
|
@@ -575,6 +626,7 @@ test_files:
|
|
575
626
|
- spec/dummy/public/500.html
|
576
627
|
- spec/dummy/public/favicon.ico
|
577
628
|
- spec/endpoint/for_url_spec.rb
|
629
|
+
- spec/extended_rollbar_spec.rb
|
578
630
|
- spec/item/access_errors_spec.rb
|
579
631
|
- spec/item/accessors_spec.rb
|
580
632
|
- spec/item/add_error_spec.rb
|
@@ -680,6 +732,7 @@ test_files:
|
|
680
732
|
- spec/request_cycle_cache_spec.rb
|
681
733
|
- spec/require_lhs_spec.rb
|
682
734
|
- spec/spec_helper.rb
|
735
|
+
- spec/stubs/all_spec.rb
|
683
736
|
- spec/support/fixtures/json/feedback.json
|
684
737
|
- spec/support/fixtures/json/feedbacks.json
|
685
738
|
- spec/support/fixtures/json/localina_content_ad.json
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support'
|
4
|
-
|
5
|
-
class LHS::Record
|
6
|
-
|
7
|
-
module RequestCycleCache
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
class Interceptor < LHC::Interceptor
|
11
|
-
|
12
|
-
VERSION = 1
|
13
|
-
CACHED_METHODS = [:get].freeze
|
14
|
-
|
15
|
-
def before_request
|
16
|
-
request.options = request.options.merge({
|
17
|
-
cache: {
|
18
|
-
expires_in: 5.minutes,
|
19
|
-
race_condition_ttl: 5.seconds,
|
20
|
-
key: cache_key_for(request),
|
21
|
-
methods: CACHED_METHODS,
|
22
|
-
use: LHS.config.request_cycle_cache
|
23
|
-
}
|
24
|
-
}.merge(request.options))
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def cache_key_for(request)
|
30
|
-
[
|
31
|
-
"LHS_REQUEST_CYCLE_CACHE(v#{VERSION})",
|
32
|
-
request.method.upcase,
|
33
|
-
[request.url, request.params.presence].compact.join('?'),
|
34
|
-
"REQUEST=#{LHS::Record::RequestCycleCache::RequestCycleThreadRegistry.request_id}",
|
35
|
-
"HEADERS=#{request.headers.hash}"
|
36
|
-
].join(' ')
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'active_support'
|
4
|
-
|
5
|
-
class LHS::Record
|
6
|
-
|
7
|
-
module RequestCycleCache
|
8
|
-
class RequestCycleThreadRegistry
|
9
|
-
# Using ActiveSupports PerThreadRegistry to be able to support Active Support v4.
|
10
|
-
# Will switch to thread_mattr_accessor (which comes with Activesupport) when we dropping support for Active Support v5.
|
11
|
-
extend ActiveSupport::PerThreadRegistry
|
12
|
-
attr_accessor :request_id
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|