lhs 19.9.0 → 20.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|