shrek 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/examples/tree_pruning/.gitignore +30 -0
- data/examples/tree_pruning/.rspec +3 -0
- data/examples/tree_pruning/.rubocop.yml +10 -0
- data/examples/tree_pruning/.ruby-version +1 -0
- data/examples/tree_pruning/Gemfile +70 -0
- data/examples/tree_pruning/README.md +83 -0
- data/examples/tree_pruning/Rakefile +8 -0
- data/examples/tree_pruning/app/assets/config/manifest.js +3 -0
- data/examples/tree_pruning/app/assets/images/.keep +0 -0
- data/examples/tree_pruning/app/assets/javascripts/application.js +16 -0
- data/examples/tree_pruning/app/assets/javascripts/cable.js +13 -0
- data/examples/tree_pruning/app/assets/javascripts/channels/.keep +0 -0
- data/examples/tree_pruning/app/assets/stylesheets/application.css +15 -0
- data/examples/tree_pruning/app/channels/application_cable/channel.rb +6 -0
- data/examples/tree_pruning/app/channels/application_cable/connection.rb +6 -0
- data/examples/tree_pruning/app/controllers/application_controller.rb +4 -0
- data/examples/tree_pruning/app/controllers/concerns/.keep +0 -0
- data/examples/tree_pruning/app/controllers/tree_controller.rb +13 -0
- data/examples/tree_pruning/app/helpers/application_helper.rb +4 -0
- data/examples/tree_pruning/app/jobs/application_job.rb +4 -0
- data/examples/tree_pruning/app/lib/layers/external_fetcher.rb +21 -0
- data/examples/tree_pruning/app/lib/layers/parser.rb +11 -0
- data/examples/tree_pruning/app/lib/layers/selector.rb +46 -0
- data/examples/tree_pruning/app/lib/statistics_processor.rb +9 -0
- data/examples/tree_pruning/app/mailers/application_mailer.rb +6 -0
- data/examples/tree_pruning/app/models/application_record.rb +5 -0
- data/examples/tree_pruning/app/models/concerns/.keep +0 -0
- data/examples/tree_pruning/app/views/layouts/application.html.erb +15 -0
- data/examples/tree_pruning/app/views/layouts/mailer.html.erb +13 -0
- data/examples/tree_pruning/app/views/layouts/mailer.text.erb +1 -0
- data/examples/tree_pruning/bin/bundle +5 -0
- data/examples/tree_pruning/bin/rails +11 -0
- data/examples/tree_pruning/bin/rake +11 -0
- data/examples/tree_pruning/bin/setup +38 -0
- data/examples/tree_pruning/bin/spring +18 -0
- data/examples/tree_pruning/bin/update +33 -0
- data/examples/tree_pruning/bin/yarn +11 -0
- data/examples/tree_pruning/config.ru +7 -0
- data/examples/tree_pruning/config/application.rb +21 -0
- data/examples/tree_pruning/config/boot.rb +6 -0
- data/examples/tree_pruning/config/cable.yml +10 -0
- data/examples/tree_pruning/config/credentials.yml.enc +1 -0
- data/examples/tree_pruning/config/database.yml +25 -0
- data/examples/tree_pruning/config/environment.rb +7 -0
- data/examples/tree_pruning/config/environments/development.rb +63 -0
- data/examples/tree_pruning/config/environments/production.rb +96 -0
- data/examples/tree_pruning/config/environments/test.rb +48 -0
- data/examples/tree_pruning/config/initializers/application_controller_renderer.rb +9 -0
- data/examples/tree_pruning/config/initializers/assets.rb +16 -0
- data/examples/tree_pruning/config/initializers/backtrace_silencers.rb +8 -0
- data/examples/tree_pruning/config/initializers/content_security_policy.rb +26 -0
- data/examples/tree_pruning/config/initializers/cookies_serializer.rb +7 -0
- data/examples/tree_pruning/config/initializers/filter_parameter_logging.rb +6 -0
- data/examples/tree_pruning/config/initializers/inflections.rb +17 -0
- data/examples/tree_pruning/config/initializers/mime_types.rb +5 -0
- data/examples/tree_pruning/config/initializers/wrap_parameters.rb +16 -0
- data/examples/tree_pruning/config/locales/en.yml +33 -0
- data/examples/tree_pruning/config/puma.rb +36 -0
- data/examples/tree_pruning/config/routes.rb +6 -0
- data/examples/tree_pruning/config/spring.rb +8 -0
- data/examples/tree_pruning/config/storage.yml +34 -0
- data/examples/tree_pruning/db/seeds.rb +8 -0
- data/examples/tree_pruning/lib/assets/.keep +0 -0
- data/examples/tree_pruning/lib/tasks/.keep +0 -0
- data/examples/tree_pruning/log/.keep +0 -0
- data/examples/tree_pruning/package.json +5 -0
- data/examples/tree_pruning/public/404.html +67 -0
- data/examples/tree_pruning/public/422.html +67 -0
- data/examples/tree_pruning/public/500.html +66 -0
- data/examples/tree_pruning/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/tree_pruning/public/apple-touch-icon.png +0 -0
- data/examples/tree_pruning/public/favicon.ico +0 -0
- data/examples/tree_pruning/public/robots.txt +1 -0
- data/examples/tree_pruning/spec/fixtures/.keep +0 -0
- data/examples/tree_pruning/spec/fixtures/files/.keep +0 -0
- data/examples/tree_pruning/spec/fixtures/files/people_stats.json +2682 -0
- data/examples/tree_pruning/spec/lib/layers/external_fetcher_spec.rb +32 -0
- data/examples/tree_pruning/spec/lib/layers/parser_spec.rb +17 -0
- data/examples/tree_pruning/spec/lib/layers/selector_spec.rb +40 -0
- data/examples/tree_pruning/spec/lib/statistics_processor_spec.rb +24 -0
- data/examples/tree_pruning/spec/rails_helper.rb +59 -0
- data/examples/tree_pruning/spec/spec_helper.rb +96 -0
- data/examples/tree_pruning/spec/support/people_stats.rb +15 -0
- data/examples/tree_pruning/spec/system/root_spec.rb +30 -0
- data/examples/tree_pruning/tmp/.keep +0 -0
- data/examples/tree_pruning/vendor/.keep +0 -0
- data/lib/shrek/runner.rb +5 -1
- data/lib/shrek/version.rb +1 -1
- metadata +88 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '068de42c241b85ca45f4a3b3221c34e706789b5a73ac7b98734dc1d84610fec2'
|
4
|
+
data.tar.gz: 054b17a00cef2897177cfd0a1eda89a3a6adef6ef10b6f2fd58da1b4e4f65b52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94817e382d811bb64006470143a8f267c9aa91bf2fd1080c24b4c2e0d310c585b419b9b68430d827371e524ee5c51087e82495a7bc88d9fa7bd9685876283819
|
7
|
+
data.tar.gz: e492291ac0d33d772bfe61f8f2219f46643939a70ddecedf52b7ff03379f18861406431b4d6218913df68373acc3f369aad5768c473ce99f24bcd1aebdf5cf32
|
data/README.md
CHANGED
@@ -68,9 +68,13 @@ may be used in own classes
|
|
68
68
|
include Shrek
|
69
69
|
end
|
70
70
|
|
71
|
-
Paint.new.use_layers FindPaints, SelectWall, PrepareBrushes
|
71
|
+
Paint.new.use_layers FindPaints, SelectWall, PrepareBrushes,
|
72
|
+
self_return: ->(result) { a }
|
72
73
|
```
|
73
74
|
|
75
|
+
We also are able to make some tuning with returning value with `self_return` option.
|
76
|
+
It use something, which respond_to :call.
|
77
|
+
|
74
78
|
Let's summarize procs and cons of this concept:
|
75
79
|
|
76
80
|
##### Procs
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.bundle
|
9
|
+
|
10
|
+
# Ignore the default SQLite database.
|
11
|
+
/db/*.sqlite3
|
12
|
+
/db/*.sqlite3-journal
|
13
|
+
|
14
|
+
# Ignore all logfiles and tempfiles.
|
15
|
+
/log/*
|
16
|
+
/tmp/*
|
17
|
+
!/log/.keep
|
18
|
+
!/tmp/.keep
|
19
|
+
|
20
|
+
# Ignore uploaded files in development
|
21
|
+
/storage/*
|
22
|
+
|
23
|
+
/node_modules
|
24
|
+
/yarn-error.log
|
25
|
+
|
26
|
+
/public/assets
|
27
|
+
.byebug_history
|
28
|
+
|
29
|
+
# Ignore master key for decrypting credentials and more.
|
30
|
+
/config/master.key
|
@@ -0,0 +1 @@
|
|
1
|
+
2.5.1
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
5
|
+
|
6
|
+
ruby '2.5.1'
|
7
|
+
|
8
|
+
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
9
|
+
gem 'rails', '~> 5.2.0'
|
10
|
+
# Use sqlite3 as the database for Active Record
|
11
|
+
gem 'sqlite3'
|
12
|
+
# Use Puma as the app server
|
13
|
+
gem 'puma', '~> 3.11'
|
14
|
+
# Use SCSS for stylesheets
|
15
|
+
gem 'sass-rails', '~> 5.0'
|
16
|
+
# Use Uglifier as compressor for JavaScript assets
|
17
|
+
gem 'uglifier', '>= 1.3.0'
|
18
|
+
# See https://github.com/rails/execjs#readme for more supported runtimes
|
19
|
+
# gem 'mini_racer', platforms: :ruby
|
20
|
+
|
21
|
+
# Use CoffeeScript for .coffee assets and views
|
22
|
+
gem 'coffee-rails', '~> 4.2'
|
23
|
+
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
|
24
|
+
gem 'turbolinks', '~> 5'
|
25
|
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
|
26
|
+
gem 'jbuilder', '~> 2.5'
|
27
|
+
# Use Redis adapter to run Action Cable in production
|
28
|
+
# gem 'redis', '~> 4.0'
|
29
|
+
# Use ActiveModel has_secure_password
|
30
|
+
# gem 'bcrypt', '~> 3.1.7'
|
31
|
+
|
32
|
+
# Use ActiveStorage variant
|
33
|
+
# gem 'mini_magick', '~> 4.8'
|
34
|
+
|
35
|
+
# Use Capistrano for deployment
|
36
|
+
# gem 'capistrano-rails', group: :development
|
37
|
+
|
38
|
+
# Reduces boot times through caching; required in config/boot.rb
|
39
|
+
gem 'bootsnap', '>= 1.1.0', require: false
|
40
|
+
|
41
|
+
gem 'ice_nine', '~> 0.11'
|
42
|
+
gem 'shrek', '~> 0.2'
|
43
|
+
|
44
|
+
group :development, :test do
|
45
|
+
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
|
46
|
+
gem 'byebug', platforms: %i[mri mingw x64_mingw]
|
47
|
+
gem 'pry-rails', '~> 0.3'
|
48
|
+
gem 'rspec-rails', '~> 3.7'
|
49
|
+
end
|
50
|
+
|
51
|
+
group :development do
|
52
|
+
# Access an interactive console on exception pages or by calling 'console' anywhere in the code.
|
53
|
+
gem 'listen', '>= 3.0.5', '< 3.2'
|
54
|
+
gem 'web-console', '>= 3.3.0'
|
55
|
+
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
|
56
|
+
gem 'spring'
|
57
|
+
gem 'spring-watcher-listen', '~> 2.0.0'
|
58
|
+
end
|
59
|
+
|
60
|
+
group :test do
|
61
|
+
# Adds support for Capybara system testing and selenium driver
|
62
|
+
gem 'capybara', '>= 2.15', '< 4.0'
|
63
|
+
gem 'selenium-webdriver'
|
64
|
+
# Easy installation and use of chromedriver to run system tests with Chrome
|
65
|
+
gem 'chromedriver-helper'
|
66
|
+
gem 'webmock', '~> 3.3'
|
67
|
+
end
|
68
|
+
|
69
|
+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
|
70
|
+
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# The problem
|
2
|
+
|
3
|
+
Imagine you have a tree of various Indicators that track something about a country's population. The client wants to display them, but only a few of them at a time.
|
4
|
+
|
5
|
+
These Indicators are part of a tree, and they’re grouped by Themes, Sub-themes, and Categories. For example, we have an indicator called “Crude death rate”. It resides in the Category "Births per year", which lives inside the Sub-theme “Births and Deaths”, which in turn lives inside the Theme “Demographics”.
|
6
|
+
|
7
|
+
This data comes from a client-provided service, which doesn’t support picking and choosing which things to filter. Because of valid reasons we won’t expound on here, it wouldn’t make sense to add this feature to the upstream service, and it’s on us to build an intermediary service that can do this.
|
8
|
+
|
9
|
+
|
10
|
+
Because we don’t know how to program, this service explodes quite regularly. It’s expected that your solution should retry a few times in case of failure.
|
11
|
+
|
12
|
+
You can find sample input data in the test suite
|
13
|
+
|
14
|
+
## Solution
|
15
|
+
|
16
|
+
You’re to make an API that has one single endpoint, /tree/<name>. It will receive the name of the upstream tree to request, as well as a list of values as GET params, indicator_ids[] to filter for. If you get asked to show an Indicator, you should return the subtree that reaches it. Here's an example URL:
|
17
|
+
|
18
|
+
http://127.0.0.1:5000/tree/input?indicator_ids[]=31&indicator_ids[]=32&indicator_ids[]=1
|
19
|
+
|
20
|
+
Except for filtering out uninteresting Categories, Sub-themes and Themes, you must preserve all the other attributes in the nodes.
|
21
|
+
|
22
|
+
## Potential edge cases
|
23
|
+
|
24
|
+
After an earnest try to maintain service, if the upstream still doesn’t work, return a 500.
|
25
|
+
If the tree you were asked for does not exist, return a 404.
|
26
|
+
|
27
|
+
The upstream server has no schedule for changes. Don’t cache its answers.
|
28
|
+
|
29
|
+
## Things that we’ll pay attention to
|
30
|
+
|
31
|
+
* Code ergonomy (style and readability)
|
32
|
+
* Testing strategy
|
33
|
+
* Resilience to network/upstream problems
|
34
|
+
* Separation of concerns and code structure
|
35
|
+
|
36
|
+
## Visualization of a pruned tree
|
37
|
+
|
38
|
+
In the tree below, when asked for the four indicators in bold (Urban, Male, Female, >30y), you should return a subtree containing only the highlighted nodes.
|
39
|
+
|
40
|
+
| Theme | Sub-Theme | Category | Indicator |
|
41
|
+
|------------- |---------------- |---------------- |-----------------|
|
42
|
+
| `Urban` | `Administrative` | `Area` | Rural |
|
43
|
+
| `Urban` | `Administrative` | `Area` | **Urban** |
|
44
|
+
| `Urban` | `Administrative` | Population | Total |
|
45
|
+
| `Urban` | `Administrative` | Population | Male |
|
46
|
+
| `Urban` | `Administrative` | Population | Female |
|
47
|
+
| Jobs | Labor force | Working population | Total |
|
48
|
+
| Jobs | Unemployment | 15-24 years | Male |
|
49
|
+
| Jobs | Unemployment | 15-24 years | Female |
|
50
|
+
| `Demographics` | `Birth and deaths` | Deaths per year | Natural |
|
51
|
+
| `Demographics` | `Birth and deaths` | Deaths per year | Accidents? |
|
52
|
+
| `Demographics` | `Birth and deaths` | Deaths per year | Murder |
|
53
|
+
| `Demographics` | `Birth and deaths` | `Births per year` | **Male** |
|
54
|
+
| `Demographics` | `Birth and deaths` | `Births per year` | **Female** |
|
55
|
+
| `Demographics` | `Age and sex` | `Age distribution` | < 3y |
|
56
|
+
| `Demographics` | `Age and sex` | `Age distribution` | <18y |
|
57
|
+
| `Demographics` | `Age and sex` | `Age distribution` | <30y |
|
58
|
+
| `Demographics` | `Age and sex` | `Age distribution` | **>30y** |
|
59
|
+
| `Demographics` | `Age and sex` | Sex | Yes |
|
60
|
+
| `Demographics` | `Age and sex` | Sex | No |
|
61
|
+
|
62
|
+
|
63
|
+
The resulting (pruned) tree should be this:
|
64
|
+
|
65
|
+
| Theme | Sub-Theme | Category | Indicator |
|
66
|
+
|------------- |---------------- |---------------- |-----------------|
|
67
|
+
| `Urban` | `Administrative` | `Area` | **Urban** |
|
68
|
+
| `Demographics` | `Birth and deaths` | `Births per year` | **Male** |
|
69
|
+
| `Demographics` | `Birth and deaths` | `Births per year` | **Female** |
|
70
|
+
| `Demographics` | `Age and sex` | `Age distribution` | **>30y** |
|
71
|
+
|
72
|
+
# Result
|
73
|
+
|
74
|
+
Finish endpoint can used with
|
75
|
+
|
76
|
+
```
|
77
|
+
curl -v 'http://127.0.0.1:3000/?indicator_ids\[\]=31&indicator_ids\[\]=32&indicator_ids\[\]=1'
|
78
|
+
```
|
79
|
+
|
80
|
+
In the real world will be good to move all exceptions handling to `ApplicationController`
|
81
|
+
but now I think it is ok as it is.
|
82
|
+
|
83
|
+
I still do not have real endpoint. Use stub file is not right, so I leaved stub uri.
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
4
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
5
|
+
|
6
|
+
require_relative 'config/application'
|
7
|
+
|
8
|
+
Rails.application.load_tasks
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
|
5
|
+
// vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require rails-ujs
|
14
|
+
//= require activestorage
|
15
|
+
//= require turbolinks
|
16
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
|
3
|
+
//
|
4
|
+
//= require action_cable
|
5
|
+
//= require_self
|
6
|
+
//= require_tree ./channels
|
7
|
+
|
8
|
+
(function() {
|
9
|
+
this.App || (this.App = {});
|
10
|
+
|
11
|
+
App.cable = ActionCable.createConsumer();
|
12
|
+
|
13
|
+
}).call(this);
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
|
6
|
+
* vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TreeController < ApplicationController
|
4
|
+
def index
|
5
|
+
render StatisticsProcessor.new.call(permitted_params.to_h.symbolize_keys)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def permitted_params
|
11
|
+
params.permit(sub_theme_ids: [], categorie_ids: [], indicator_ids: [])
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
module Layers
|
5
|
+
class ExternalFetcher < Shrek::Layers
|
6
|
+
def call(uri: 'enter_real_uri_here.stub', path: '/', tries: 3, **options)
|
7
|
+
next_layer.call(response(uri, path), options)
|
8
|
+
rescue StandardError => e
|
9
|
+
tries -= 1
|
10
|
+
retry if tries.positive?
|
11
|
+
{ json: e.message, status: :internal_server_error }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def response(uri, path)
|
17
|
+
Net::HTTP.get_response(uri, path).body
|
18
|
+
# open(Rails.root.join('spec', 'fixtures', 'files', 'people_stats.json')).read
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Layers
|
4
|
+
class Parser < Shrek::Layers
|
5
|
+
def call(body = '', **options)
|
6
|
+
next_layer.call JSON.parse(body), options
|
7
|
+
rescue JSON::ParserError => e
|
8
|
+
{ json: e.message, status: :unprocessable_entity }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Layers
|
4
|
+
module NestedHashFilter
|
5
|
+
refine Hash do
|
6
|
+
def fetch_for(wanted_key, wanted_ids)
|
7
|
+
fetch(wanted_key.to_s, []).delete_if do |wanted|
|
8
|
+
next if Array(wanted_ids).map(&:to_i).include? wanted.fetch('id') { raise JSON::ParserError }
|
9
|
+
block_given? ? yield(wanted) : true
|
10
|
+
end.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
def proceed(**args)
|
14
|
+
return fetch_for(*args.shift) if args.keys.one?
|
15
|
+
fetch_for(*args.shift) { |wrap| wrap.proceed(args) if args.any? }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
using Layers::NestedHashFilter
|
21
|
+
|
22
|
+
class NotFound < StandardError; end
|
23
|
+
|
24
|
+
class Selector < Shrek::Layers
|
25
|
+
def call(data, sub_theme_ids: nil, categorie_ids: nil, indicator_ids: nil, **_options)
|
26
|
+
return { json: data } if Array(sub_theme_ids).empty? &&
|
27
|
+
Array(categorie_ids).empty? &&
|
28
|
+
Array(indicator_ids).empty? && data.any?
|
29
|
+
|
30
|
+
result = data.delete_if do |w|
|
31
|
+
w.proceed(sub_themes: sub_theme_ids, categories: categorie_ids, indicators: indicator_ids)
|
32
|
+
end
|
33
|
+
|
34
|
+
raise(NotFound) if result.empty?
|
35
|
+
{ json: result }
|
36
|
+
rescue NotFound
|
37
|
+
not_found
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def not_found
|
43
|
+
{ json: '', status: :not_found }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|