determinator-context 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +63 -0
- data/.github/workflows/codeql-analysis.yml +49 -0
- data/.github/workflows/codeql-complete.yml +58 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +45 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +83 -0
- data/README.md +77 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/determinator-context.gemspec +27 -0
- data/lib/determinator/context/actors.rb +103 -0
- data/lib/determinator/context/helpers.rb +37 -0
- data/lib/determinator/context/resolver.rb +26 -0
- data/lib/determinator/context/version.rb +5 -0
- data/lib/determinator/context.rb +11 -0
- data/lib/determinator/models/base.rb +46 -0
- data/lib/determinator/models/common/city.rb +13 -0
- data/lib/determinator/models/common/country.rb +13 -0
- data/lib/determinator/models/common/drn.rb +10 -0
- data/lib/determinator/models/common/neighborhood.rb +12 -0
- data/lib/determinator/models/common/zone.rb +13 -0
- data/lib/determinator/models/customer.rb +12 -0
- data/lib/determinator/models/request.rb +29 -0
- data/lib/determinator/models/restaurant.rb +18 -0
- data/lib/determinator/models/rider.rb +15 -0
- data/lib/determinator/models/types.rb +9 -0
- data/lib/determinator/models.rb +14 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d189ccc035413e3bbf5706ecee72c50228e9637ff985ca08de82f8b5f9221103
|
4
|
+
data.tar.gz: 706b55dfb757e4041b50715d06b071737147ba44fb099c69437182a7e32c4426
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 71aa0e2777a927f0e841e0b78722257955cfcb170dcb403447738d030692629115ac0bbf0a184aeb32aaf0b49db495490bab6fdb289b81e00875580ff1f12bf7
|
7
|
+
data.tar.gz: ba87b44ce8cd10363834bfdea75d7f78c36729bd2828723cf49eea742cbb6f9d883f9f6485ecfa8f40036b623bbc601452ea2569c42acc2b94e6f43cf4066daa
|
@@ -0,0 +1,63 @@
|
|
1
|
+
global_dockerhub_login: &global_dockerhub_login
|
2
|
+
run:
|
3
|
+
name: Authenticate with hub.docker.com - DockerHub
|
4
|
+
command: docker login -u $GLOBAL_DOCKERHUB_USERNAME -p $GLOBAL_DOCKERHUB_PASSWORD
|
5
|
+
global_context: &global_context
|
6
|
+
context:
|
7
|
+
- org-global
|
8
|
+
global_remote_docker: &global_remote_docker
|
9
|
+
version: 19.03.13
|
10
|
+
global_dockerhub_auth: &global_dockerhub_auth
|
11
|
+
auth:
|
12
|
+
username: $GLOBAL_DOCKERHUB_USERNAME
|
13
|
+
password: $GLOBAL_DOCKERHUB_PASSWORD
|
14
|
+
version: 2
|
15
|
+
jobs:
|
16
|
+
build_2.6:
|
17
|
+
docker:
|
18
|
+
- image: circleci/ruby:2.6
|
19
|
+
<<: *global_dockerhub_auth
|
20
|
+
steps:
|
21
|
+
- checkout
|
22
|
+
|
23
|
+
- run:
|
24
|
+
name: Install bundler
|
25
|
+
command: gem install bundler
|
26
|
+
|
27
|
+
- run:
|
28
|
+
name: Bundle Install
|
29
|
+
command: bundle install
|
30
|
+
|
31
|
+
- run:
|
32
|
+
name: Run rspec
|
33
|
+
command: |
|
34
|
+
bundle exec rspec --format documentation
|
35
|
+
|
36
|
+
build_2.7:
|
37
|
+
docker:
|
38
|
+
- image: circleci/ruby:2.7
|
39
|
+
<<: *global_dockerhub_auth
|
40
|
+
steps:
|
41
|
+
- checkout
|
42
|
+
|
43
|
+
- run:
|
44
|
+
name: Install bundler
|
45
|
+
command: gem install bundler
|
46
|
+
|
47
|
+
- run:
|
48
|
+
name: Bundle Install
|
49
|
+
command: bundle install
|
50
|
+
|
51
|
+
- run:
|
52
|
+
name: Run rspec
|
53
|
+
command: |
|
54
|
+
bundle exec rspec --format documentation
|
55
|
+
|
56
|
+
workflows:
|
57
|
+
version: 2
|
58
|
+
test:
|
59
|
+
jobs:
|
60
|
+
- build_2.6
|
61
|
+
|
62
|
+
- build_2.7
|
63
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
name: "CodeQL - Minimal incremental analysis"
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- "master" # Change this to the branch to default branch
|
7
|
+
- "!ignore/branch" # Ignore CodeQL scan for these branches
|
8
|
+
- "!test/*" # Ignore CodeQL scan for these branches
|
9
|
+
pull_request:
|
10
|
+
branches:
|
11
|
+
- "master" # Change this to the branch to default branch
|
12
|
+
paths-ignore:
|
13
|
+
- '**/*.md'
|
14
|
+
- '**/*.txt'
|
15
|
+
# If your project is not actively developed, consider scheduling CodeQL scans
|
16
|
+
#schedule:
|
17
|
+
# - cron: '44 22 * * 5' # Run CodeQL scan every Friday at 10:44 PM UTC
|
18
|
+
|
19
|
+
jobs:
|
20
|
+
analyze:
|
21
|
+
name: Analyze
|
22
|
+
runs-on: ubuntu-latest
|
23
|
+
timeout-minutes: 30 # Set timeout to 30 minutes; Change if your project takes longer to scan
|
24
|
+
permissions:
|
25
|
+
actions: read
|
26
|
+
contents: read
|
27
|
+
security-events: write
|
28
|
+
|
29
|
+
strategy:
|
30
|
+
fail-fast: false
|
31
|
+
matrix:
|
32
|
+
language: [ 'ruby' ]
|
33
|
+
|
34
|
+
steps:
|
35
|
+
- name: Checkout repository
|
36
|
+
uses: actions/checkout@v3
|
37
|
+
|
38
|
+
# Initializes the CodeQL tools for scanning.
|
39
|
+
- name: Initialize CodeQL
|
40
|
+
uses: github/codeql-action/init@v2
|
41
|
+
with:
|
42
|
+
languages: ${{ matrix.language }}
|
43
|
+
# queries: security-extended,security-and-quality
|
44
|
+
# debug: true # Only use this for debugging. It will increase the runtime of the action and take up storage
|
45
|
+
|
46
|
+
- name: Perform CodeQL Analysis
|
47
|
+
uses: github/codeql-action/analyze@v2
|
48
|
+
with:
|
49
|
+
category: "/language:${{matrix.language}}"
|
@@ -0,0 +1,58 @@
|
|
1
|
+
name: "CodeQL - Complete analysis"
|
2
|
+
|
3
|
+
on:
|
4
|
+
schedule:
|
5
|
+
- cron: "44 23 12 * *" # Run CodeQL scan on a day of every month at 11:44 PM UTC
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
analyze:
|
9
|
+
name: Analyze
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
timeout-minutes: 30 # Set timeout to 30 minutes; Change if your project takes longer to scan
|
12
|
+
permissions:
|
13
|
+
actions: read
|
14
|
+
contents: read
|
15
|
+
security-events: write
|
16
|
+
|
17
|
+
strategy:
|
18
|
+
fail-fast: false
|
19
|
+
matrix:
|
20
|
+
language: ["ruby"]
|
21
|
+
|
22
|
+
steps:
|
23
|
+
- name: Checkout repository
|
24
|
+
uses: actions/checkout@v3
|
25
|
+
|
26
|
+
# This step will try to find a Dockerfile in the repository and extract the Ruby version from it.
|
27
|
+
# If you don't use Docker, you can remove this step and add the Ruby version directly to the
|
28
|
+
# ruby-version parameter in the `ruby/setup-ruby` step below.
|
29
|
+
- name: Find Ruby version in Dockerfile
|
30
|
+
id: find-ruby-version-in-dockerfile
|
31
|
+
run: |
|
32
|
+
ruby_version=$(find . -name Dockerfile -exec sed -En 's/^FROM ruby:([0-9.]+)(.*)/\1/p' {} \; | head -1)
|
33
|
+
if [ -z "$ruby_version" ]; then
|
34
|
+
echo "No Dockerfile found, using default Ruby version"
|
35
|
+
ruby_version="2.7"
|
36
|
+
else
|
37
|
+
echo "Found Dockerfile, using Ruby version $ruby_version"
|
38
|
+
fi
|
39
|
+
echo USE_RUBY_VERSION=$ruby_version >> $GITHUB_OUTPUT
|
40
|
+
- uses: ruby/setup-ruby@v1
|
41
|
+
with:
|
42
|
+
ruby-version: ${{ steps.find-ruby-version-in-dockerfile.outputs.USE_RUBY_VERSION }} # The version of Ruby to use
|
43
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
44
|
+
#env:
|
45
|
+
# BUNDLE_GEMFILE: ./path/to/Gemfile # Change this to the path to your Gemfile if not in root
|
46
|
+
|
47
|
+
# Initializes the CodeQL tools for scanning.
|
48
|
+
- name: Initialize CodeQL
|
49
|
+
uses: github/codeql-action/init@v2
|
50
|
+
with:
|
51
|
+
languages: ${{ matrix.language }}
|
52
|
+
# queries: security-extended,security-and-quality
|
53
|
+
# debug: true # Only use this for debugging. It will increase the runtime of the action and take up storage
|
54
|
+
|
55
|
+
- name: Perform CodeQL Analysis
|
56
|
+
uses: github/codeql-action/analyze@v2
|
57
|
+
with:
|
58
|
+
category: "/language:${{matrix.language}}"
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# 0.1.10
|
2
|
+
|
3
|
+
- Add DRNs to main actors
|
4
|
+
|
5
|
+
# 0.1.9
|
6
|
+
|
7
|
+
- Add `with` to override model attributes
|
8
|
+
|
9
|
+
# 0.1.8
|
10
|
+
|
11
|
+
- Fail gracefully if property is missing
|
12
|
+
|
13
|
+
# 0.1.7
|
14
|
+
|
15
|
+
- Bugfix: handle missing features correctly
|
16
|
+
|
17
|
+
# 0.1.6
|
18
|
+
|
19
|
+
- Remove error if the feature is not structured and error tracking
|
20
|
+
|
21
|
+
# 0.1.5
|
22
|
+
|
23
|
+
- Feature: add `with` method to clone actors
|
24
|
+
|
25
|
+
# 0.1.4
|
26
|
+
|
27
|
+
- Bugfix: allow passing nil values to actors
|
28
|
+
|
29
|
+
# 0.1.3
|
30
|
+
|
31
|
+
- Call `determinator_actor` helper block in instance context
|
32
|
+
- Add `bot` to platforms list.
|
33
|
+
|
34
|
+
# 0.1.2
|
35
|
+
|
36
|
+
- Fix dependencies
|
37
|
+
|
38
|
+
# 0.1.1
|
39
|
+
|
40
|
+
- Add Determinator::Context::Actors.elements
|
41
|
+
|
42
|
+
|
43
|
+
# 0.1.0
|
44
|
+
|
45
|
+
- Initial functionality
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
determinator-context (0.1.11)
|
5
|
+
determinator (>= 2.5.4)
|
6
|
+
dry-struct (~> 1.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
byebug (11.1.3)
|
12
|
+
concurrent-ruby (1.1.10)
|
13
|
+
determinator (2.9.1)
|
14
|
+
faraday
|
15
|
+
semantic (~> 1.6)
|
16
|
+
diff-lcs (1.3)
|
17
|
+
dry-container (0.10.0)
|
18
|
+
concurrent-ruby (~> 1.0)
|
19
|
+
dry-core (0.8.0)
|
20
|
+
concurrent-ruby (~> 1.0)
|
21
|
+
dry-inflector (0.3.0)
|
22
|
+
dry-logic (1.2.0)
|
23
|
+
concurrent-ruby (~> 1.0)
|
24
|
+
dry-core (~> 0.5, >= 0.5)
|
25
|
+
dry-struct (1.4.0)
|
26
|
+
dry-core (~> 0.5, >= 0.5)
|
27
|
+
dry-types (~> 1.5)
|
28
|
+
ice_nine (~> 0.11)
|
29
|
+
dry-types (1.5.1)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
dry-container (~> 0.3)
|
32
|
+
dry-core (~> 0.5, >= 0.5)
|
33
|
+
dry-inflector (~> 0.1, >= 0.1.2)
|
34
|
+
dry-logic (~> 1.0, >= 1.0.2)
|
35
|
+
faraday (1.8.0)
|
36
|
+
faraday-em_http (~> 1.0)
|
37
|
+
faraday-em_synchrony (~> 1.0)
|
38
|
+
faraday-excon (~> 1.1)
|
39
|
+
faraday-httpclient (~> 1.0.1)
|
40
|
+
faraday-net_http (~> 1.0)
|
41
|
+
faraday-net_http_persistent (~> 1.1)
|
42
|
+
faraday-patron (~> 1.0)
|
43
|
+
faraday-rack (~> 1.0)
|
44
|
+
multipart-post (>= 1.2, < 3)
|
45
|
+
ruby2_keywords (>= 0.0.4)
|
46
|
+
faraday-em_http (1.0.0)
|
47
|
+
faraday-em_synchrony (1.0.0)
|
48
|
+
faraday-excon (1.1.0)
|
49
|
+
faraday-httpclient (1.0.1)
|
50
|
+
faraday-net_http (1.0.1)
|
51
|
+
faraday-net_http_persistent (1.2.0)
|
52
|
+
faraday-patron (1.0.0)
|
53
|
+
faraday-rack (1.0.0)
|
54
|
+
ice_nine (0.11.2)
|
55
|
+
multipart-post (2.2.3)
|
56
|
+
rake (12.3.3)
|
57
|
+
rspec (3.9.0)
|
58
|
+
rspec-core (~> 3.9.0)
|
59
|
+
rspec-expectations (~> 3.9.0)
|
60
|
+
rspec-mocks (~> 3.9.0)
|
61
|
+
rspec-core (3.9.2)
|
62
|
+
rspec-support (~> 3.9.3)
|
63
|
+
rspec-expectations (3.9.2)
|
64
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
65
|
+
rspec-support (~> 3.9.0)
|
66
|
+
rspec-mocks (3.9.1)
|
67
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
68
|
+
rspec-support (~> 3.9.0)
|
69
|
+
rspec-support (3.9.3)
|
70
|
+
ruby2_keywords (0.0.5)
|
71
|
+
semantic (1.6.1)
|
72
|
+
|
73
|
+
PLATFORMS
|
74
|
+
ruby
|
75
|
+
|
76
|
+
DEPENDENCIES
|
77
|
+
byebug
|
78
|
+
determinator-context!
|
79
|
+
rake (~> 12.0)
|
80
|
+
rspec (~> 3.0)
|
81
|
+
|
82
|
+
BUNDLED WITH
|
83
|
+
2.1.4
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Determinator Context
|
2
|
+
|
3
|
+
This is a gem to manage Determinator context objects.
|
4
|
+
|
5
|
+
It allows you to define the actors that will be determinated upon in a single place in the controller,
|
6
|
+
where they can be tested; then, the ID to be determinated upon are decided either by pointing to an attribute
|
7
|
+
in code, or with a structured setting in the feature itself.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
source "https://8Sshw-M7Dp0iGmkGphMxS4s7BCCuI@gem.fury.io/deliveroo/" do
|
15
|
+
gem 'determinator-context'
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
The simplest way to set up a context is to use the included helper in your controllers. For example:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class ApplicationController < ActionController::Base
|
30
|
+
include Determinator::Context::Helpers
|
31
|
+
|
32
|
+
determinator_actor(:request) do
|
33
|
+
Determinator::Models::Request.new(
|
34
|
+
uid: 'abc', customer: {guid: 'foo', sticky_guid: 'bar', session_guid: nil}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
determinator_actor(:customer) do
|
39
|
+
next nil unless current_user.present?
|
40
|
+
|
41
|
+
Determinator::Models::Customer.new(
|
42
|
+
id: current_user.id,
|
43
|
+
email: current_user.email,
|
44
|
+
employee: current_user.employee
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class MenuController < ApplicationController
|
50
|
+
include Determinator::Context::Helpers
|
51
|
+
|
52
|
+
determinator_actor(:restaurant) do
|
53
|
+
# If 'to_determinator' is a method on the model
|
54
|
+
# which returns the constructed object
|
55
|
+
restaurant.to_determinator
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
Then, if the feature has a `structured_bucket` set, you can just use the determinator context to determinate:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
determinator_context.which_variant('test_feature')
|
65
|
+
```
|
66
|
+
|
67
|
+
If the feature is not structured, or for some reason you want to override the structured bucket, you can do:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
determinator_context.using('request.customer.guid').which_variant('test_feature')
|
71
|
+
```
|
72
|
+
|
73
|
+
## Development
|
74
|
+
|
75
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
76
|
+
|
77
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to GemFury.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "determinator/context"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'lib/determinator/context/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "determinator-context"
|
5
|
+
spec.version = Determinator::Context::VERSION
|
6
|
+
spec.authors = ["Ivan Pirlik"]
|
7
|
+
spec.email = ["ivan.pirlik@deliveroo.co.uk"]
|
8
|
+
|
9
|
+
spec.summary = %q{Context objects for Determinator}
|
10
|
+
spec.description = %q{Helpers to construct Determinator actors.}
|
11
|
+
spec.homepage = "https://github.com/deliveroo/determinator-context-rb"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
# Specify which files should be added to the gem when it is released.
|
15
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
16
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "byebug", "~> 11.0"
|
24
|
+
|
25
|
+
spec.add_dependency "determinator", ">= 2.5.4"
|
26
|
+
spec.add_dependency "dry-struct", "~> 1.0"
|
27
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative 'resolver'
|
2
|
+
|
3
|
+
module Determinator
|
4
|
+
module Context
|
5
|
+
class Actors
|
6
|
+
KEYS = {
|
7
|
+
request: Models::Request,
|
8
|
+
customer: Models::Customer,
|
9
|
+
restaurant: Models::Restaurant,
|
10
|
+
rider: Models::Rider
|
11
|
+
}
|
12
|
+
|
13
|
+
attr_reader :id_path
|
14
|
+
|
15
|
+
def self.elements
|
16
|
+
KEYS.map{ |k, v| v.collect_elements("#{k}.") }.flatten(1).to_h
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(controller, actors={})
|
20
|
+
@controller = controller
|
21
|
+
@actors = {}
|
22
|
+
actors.each { |k, v| self[k] = v}
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](name)
|
26
|
+
actors[name]
|
27
|
+
end
|
28
|
+
|
29
|
+
def []=(name, actor)
|
30
|
+
@params = nil # clean cached params
|
31
|
+
|
32
|
+
if actors[name]
|
33
|
+
raise Error.new("#{name} is already set")
|
34
|
+
end
|
35
|
+
if KEYS[name].nil?
|
36
|
+
raise Error.new("#{name} is not an allowed actor")
|
37
|
+
end
|
38
|
+
|
39
|
+
return if actor.nil?
|
40
|
+
|
41
|
+
unless actor.is_a?(KEYS[name])
|
42
|
+
raise Error.new("#{name} should be of type #{KEYS[name]}")
|
43
|
+
end
|
44
|
+
actors[name] = actor
|
45
|
+
end
|
46
|
+
|
47
|
+
def has?(name)
|
48
|
+
actors.key?(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def using(dotted_path)
|
52
|
+
Resolver.new(self, controller, dotted_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get(dotted_path)
|
56
|
+
return unless dotted_path
|
57
|
+
parts = dotted_path.split('.').map(&:to_sym)
|
58
|
+
parts.reduce(actors) { |curr, part| curr ? curr[part] : nil }
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_params
|
62
|
+
@params ||= flatten_hash(actors.transform_values(&:to_h))
|
63
|
+
end
|
64
|
+
|
65
|
+
def which_variant(feature_name)
|
66
|
+
retrieve_resolver(feature_name)&.which_variant(feature_name) || false
|
67
|
+
end
|
68
|
+
|
69
|
+
def feature_flag_on?(feature_name)
|
70
|
+
retrieve_resolver(feature_name)&.feature_flag_on?(feature_name) || false
|
71
|
+
end
|
72
|
+
|
73
|
+
def with(new_actors={})
|
74
|
+
self.class.new(controller, actors.merge(new_actors))
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
attr_reader :controller, :actors
|
80
|
+
|
81
|
+
def retrieve_resolver(feature_name)
|
82
|
+
feature = controller.retrieve(feature_name)
|
83
|
+
if feature.nil? || feature.is_a?(Determinator::ErrorResponse) || feature.is_a?(Determinator::MissingResponse)
|
84
|
+
Determinator.notice_missing_feature(feature_name)
|
85
|
+
return
|
86
|
+
end
|
87
|
+
Resolver.new(self, controller, feature.structured_bucket, feature: feature)
|
88
|
+
end
|
89
|
+
|
90
|
+
def flatten_hash(hash)
|
91
|
+
hash.each_with_object({}) do |(k, v), h|
|
92
|
+
if v.is_a? Hash
|
93
|
+
flatten_hash(v).map do |h_k, h_v|
|
94
|
+
h["#{k}.#{h_k}"] = h_v
|
95
|
+
end
|
96
|
+
else
|
97
|
+
h[k.to_s] = v
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Determinator
|
2
|
+
module Context
|
3
|
+
module Helpers
|
4
|
+
module ClassMethods
|
5
|
+
def determinator_actors
|
6
|
+
if superclass.respond_to?(:determinator_actors)
|
7
|
+
superclass.determinator_actors.merge(@determinator_actors || {})
|
8
|
+
else
|
9
|
+
@determinator_actors
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def determinator_actor(name, &block)
|
14
|
+
@determinator_actors ||= {}
|
15
|
+
@determinator_actors[name] = block
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.included(c)
|
20
|
+
c.extend(ClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
def determinator_context
|
24
|
+
@determinator_context ||= construct_determinator_actors
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def construct_determinator_actors
|
30
|
+
Determinator::Context::Actors.new(
|
31
|
+
Determinator.instance,
|
32
|
+
self.class.determinator_actors.map{ |k, v| [k, instance_eval(&v)] }.to_h
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Determinator
|
2
|
+
module Context
|
3
|
+
class Resolver
|
4
|
+
attr_reader :actors, :id_path
|
5
|
+
|
6
|
+
def initialize(actors, controller, id_path, feature: nil)
|
7
|
+
@actors = actors
|
8
|
+
@controller = controller
|
9
|
+
@id_path = id_path
|
10
|
+
@feature = feature
|
11
|
+
end
|
12
|
+
|
13
|
+
def which_variant(feature_name)
|
14
|
+
controller.which_variant(feature_name, id: actors.get(id_path), properties: actors.to_params, feature: feature)
|
15
|
+
end
|
16
|
+
|
17
|
+
def feature_flag_on?(feature_name)
|
18
|
+
controller.feature_flag_on?(feature_name, id: actors.get(id_path), properties: actors.to_params, feature: feature)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :controller, :feature
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'dry-struct'
|
2
|
+
|
3
|
+
module Determinator
|
4
|
+
module Models
|
5
|
+
ARGS = [:descr]
|
6
|
+
|
7
|
+
Element = Struct.new(:type, :description)
|
8
|
+
|
9
|
+
class Base < Dry::Struct
|
10
|
+
class << self
|
11
|
+
attr_reader :elements
|
12
|
+
|
13
|
+
def attribute(name, type, args={})
|
14
|
+
super(name, type)
|
15
|
+
element(name.to_s.chomp('?').to_sym, type, args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute?(name, type, args={})
|
19
|
+
super(name, type)
|
20
|
+
end
|
21
|
+
|
22
|
+
def element(name, type, args={})
|
23
|
+
if (args.keys - ARGS).length > 0
|
24
|
+
raise "Unrecognized arguments #{(args.keys - ARGS).join(', ')}"
|
25
|
+
end
|
26
|
+
@elements ||= {}
|
27
|
+
@elements[name] = Element.new(type, args[:descr])
|
28
|
+
end
|
29
|
+
|
30
|
+
def collect_elements(prefix='')
|
31
|
+
@elements.map do |k, v|
|
32
|
+
if v.type.respond_to?(:collect_elements)
|
33
|
+
v.type.collect_elements("#{prefix}#{k}.")
|
34
|
+
else
|
35
|
+
[["#{prefix}#{k}", v]]
|
36
|
+
end
|
37
|
+
end.flatten(1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def with(attributes={})
|
42
|
+
self.class.new(attributes.merge(to_h))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'drn'
|
2
|
+
|
3
|
+
module Determinator
|
4
|
+
module Models
|
5
|
+
module Common
|
6
|
+
class City < Base
|
7
|
+
attribute :id, Types::Integer
|
8
|
+
attribute? :drn, DRN
|
9
|
+
attribute :uname, Types::String, descr: 'The unique name (lower case, with dashes)'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'drn'
|
2
|
+
|
3
|
+
module Determinator
|
4
|
+
module Models
|
5
|
+
module Common
|
6
|
+
class Country < Base
|
7
|
+
attribute :id, Types::Integer
|
8
|
+
attribute? :drn, DRN
|
9
|
+
attribute :tld, Types::String, descr: 'The top-level domain for the country'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'common/drn'
|
2
|
+
|
3
|
+
module Determinator
|
4
|
+
module Models
|
5
|
+
class Customer < Base
|
6
|
+
attribute? :drn, Common::DRN
|
7
|
+
attribute :id, Types::Integer, descr: 'The Orderweb ID of the customer (user)'
|
8
|
+
attribute? :email, Types::String.optional
|
9
|
+
attribute :employee, Types::Bool, descr: 'Whether the customer is a Deliveroo employee'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative 'common/country'
|
2
|
+
require_relative 'common/city'
|
3
|
+
require_relative 'common/zone'
|
4
|
+
|
5
|
+
module Determinator
|
6
|
+
module Models
|
7
|
+
class Request < Base
|
8
|
+
attribute :uid, Types::String, descr: 'A unique identifier of the request'
|
9
|
+
attribute? :country, Common::Country
|
10
|
+
attribute? :city, Common::City
|
11
|
+
attribute? :zone, Common::Zone
|
12
|
+
attribute? :platform, Types::String.constrained(
|
13
|
+
included_in: ['bot', 'web', 'ios', 'android', 'signature-api']
|
14
|
+
), descr: "Which platform the request is coming from. Can be 'web', 'ios', 'android' or 'bot'."
|
15
|
+
attribute? :white_label_brand, Types::String,
|
16
|
+
descr: 'The name of the white-label brand the request is coming from, if any'
|
17
|
+
attribute? :app_version, Types::String, descr: 'Version of the Android or IOS app'
|
18
|
+
attribute? :device_os, Types::String, descr: 'Version of the Device OS'
|
19
|
+
attribute? :customer, Determinator.model {
|
20
|
+
attribute :guid, Types::String,
|
21
|
+
descr: 'Identifies the device. Also known as roo_guid or anonymous_id'
|
22
|
+
attribute :session_guid, Types::String.optional,
|
23
|
+
descr: 'Identifies a user session. Has different behaviours across platforms, so use with care'
|
24
|
+
attribute :sticky_guid, Types::String.optional,
|
25
|
+
descr: 'Identifies the user across logouts. Beware of edge cases (see go/track)'
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'common/drn'
|
2
|
+
require_relative 'common/country'
|
3
|
+
require_relative 'common/city'
|
4
|
+
require_relative 'common/neighborhood'
|
5
|
+
require_relative 'common/zone'
|
6
|
+
|
7
|
+
module Determinator
|
8
|
+
module Models
|
9
|
+
class Restaurant < Base
|
10
|
+
attribute? :drn, Common::DRN
|
11
|
+
attribute? :id, Types::Integer, descr: 'The Orderweb id of the restaurant'
|
12
|
+
attribute :country, Common::Country
|
13
|
+
attribute :city, Common::City
|
14
|
+
attribute :neighborhood, Common::Neighborhood
|
15
|
+
attribute :zone, Common::Zone
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'common/drn'
|
2
|
+
require_relative 'common/country'
|
3
|
+
require_relative 'common/zone'
|
4
|
+
|
5
|
+
module Determinator
|
6
|
+
module Models
|
7
|
+
class Rider < Base
|
8
|
+
attribute? :drn, Common::DRN
|
9
|
+
attribute :id, Types::Integer, descr: 'The Orderweb id of the rider'
|
10
|
+
attribute :uuid, Types::String
|
11
|
+
attribute :zone, Common::Zone
|
12
|
+
attribute :country, Common::Country
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Determinator
|
2
|
+
def self.model(&block)
|
3
|
+
Class.new(Determinator::Models::Base) do
|
4
|
+
class_eval(&block)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'determinator/models/types'
|
10
|
+
require 'determinator/models/base'
|
11
|
+
require 'determinator/models/customer'
|
12
|
+
require 'determinator/models/restaurant'
|
13
|
+
require 'determinator/models/request'
|
14
|
+
require 'determinator/models/rider'
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: determinator-context
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.11
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ivan Pirlik
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: byebug
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '11.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '11.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: determinator
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.5.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.5.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-struct
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: Helpers to construct Determinator actors.
|
56
|
+
email:
|
57
|
+
- ivan.pirlik@deliveroo.co.uk
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".circleci/config.yml"
|
63
|
+
- ".github/workflows/codeql-analysis.yml"
|
64
|
+
- ".github/workflows/codeql-complete.yml"
|
65
|
+
- ".gitignore"
|
66
|
+
- ".rspec"
|
67
|
+
- CHANGELOG.md
|
68
|
+
- Gemfile
|
69
|
+
- Gemfile.lock
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/setup
|
74
|
+
- determinator-context.gemspec
|
75
|
+
- lib/determinator/context.rb
|
76
|
+
- lib/determinator/context/actors.rb
|
77
|
+
- lib/determinator/context/helpers.rb
|
78
|
+
- lib/determinator/context/resolver.rb
|
79
|
+
- lib/determinator/context/version.rb
|
80
|
+
- lib/determinator/models.rb
|
81
|
+
- lib/determinator/models/base.rb
|
82
|
+
- lib/determinator/models/common/city.rb
|
83
|
+
- lib/determinator/models/common/country.rb
|
84
|
+
- lib/determinator/models/common/drn.rb
|
85
|
+
- lib/determinator/models/common/neighborhood.rb
|
86
|
+
- lib/determinator/models/common/zone.rb
|
87
|
+
- lib/determinator/models/customer.rb
|
88
|
+
- lib/determinator/models/request.rb
|
89
|
+
- lib/determinator/models/restaurant.rb
|
90
|
+
- lib/determinator/models/rider.rb
|
91
|
+
- lib/determinator/models/types.rb
|
92
|
+
homepage: https://github.com/deliveroo/determinator-context-rb
|
93
|
+
licenses: []
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.3.0
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.1.6
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Context objects for Determinator
|
114
|
+
test_files: []
|