lhs 24.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.bundler-version +1 -0
- data/.gitignore +39 -0
- data/.rubocop.localch.yml +325 -0
- data/.rubocop.yml +52 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.activesupport4 +5 -0
- data/Gemfile.activesupport5 +4 -0
- data/LICENSE +674 -0
- data/README.md +2836 -0
- data/Rakefile +25 -0
- data/cider-ci.yml +6 -0
- data/cider-ci/bin/bundle +51 -0
- data/cider-ci/bin/ruby_install +8 -0
- data/cider-ci/bin/ruby_version +25 -0
- data/cider-ci/jobs/rspec-activesupport-4.yml +27 -0
- data/cider-ci/jobs/rspec-activesupport-5.yml +26 -0
- data/cider-ci/jobs/rspec-activesupport-latest.yml +24 -0
- data/cider-ci/jobs/rubocop.yml +18 -0
- data/cider-ci/task_components/bundle.yml +22 -0
- data/cider-ci/task_components/rspec.yml +37 -0
- data/cider-ci/task_components/rubocop.yml +29 -0
- data/cider-ci/task_components/ruby.yml +15 -0
- data/friday.yml +2 -0
- data/lhs.gemspec +43 -0
- data/lib/lhs.rb +100 -0
- data/lib/lhs/collection.rb +84 -0
- data/lib/lhs/complex.rb +158 -0
- data/lib/lhs/concerns/autoload_records.rb +55 -0
- data/lib/lhs/concerns/collection/handle_nested.rb +43 -0
- data/lib/lhs/concerns/collection/internal_collection.rb +49 -0
- data/lib/lhs/concerns/configuration.rb +20 -0
- data/lib/lhs/concerns/data/becomes.rb +18 -0
- data/lib/lhs/concerns/data/equality.rb +14 -0
- data/lib/lhs/concerns/data/json.rb +14 -0
- data/lib/lhs/concerns/data/to_hash.rb +14 -0
- data/lib/lhs/concerns/inspect.rb +70 -0
- data/lib/lhs/concerns/is_href.rb +15 -0
- data/lib/lhs/concerns/item/destroy.rb +38 -0
- data/lib/lhs/concerns/item/endpoint_lookup.rb +27 -0
- data/lib/lhs/concerns/item/save.rb +55 -0
- data/lib/lhs/concerns/item/update.rb +50 -0
- data/lib/lhs/concerns/item/validation.rb +61 -0
- data/lib/lhs/concerns/o_auth.rb +25 -0
- data/lib/lhs/concerns/option_blocks.rb +26 -0
- data/lib/lhs/concerns/proxy/accessors.rb +132 -0
- data/lib/lhs/concerns/proxy/create.rb +45 -0
- data/lib/lhs/concerns/proxy/link.rb +25 -0
- data/lib/lhs/concerns/proxy/problems.rb +27 -0
- data/lib/lhs/concerns/record/attribute_assignment.rb +25 -0
- data/lib/lhs/concerns/record/batch.rb +40 -0
- data/lib/lhs/concerns/record/chainable.rb +465 -0
- data/lib/lhs/concerns/record/configuration.rb +103 -0
- data/lib/lhs/concerns/record/create.rb +24 -0
- data/lib/lhs/concerns/record/custom_setters.rb +22 -0
- data/lib/lhs/concerns/record/destroy.rb +18 -0
- data/lib/lhs/concerns/record/endpoints.rb +108 -0
- data/lib/lhs/concerns/record/equality.rb +14 -0
- data/lib/lhs/concerns/record/find.rb +86 -0
- data/lib/lhs/concerns/record/find_by.rb +38 -0
- data/lib/lhs/concerns/record/first.rb +20 -0
- data/lib/lhs/concerns/record/href_for.rb +19 -0
- data/lib/lhs/concerns/record/last.rb +27 -0
- data/lib/lhs/concerns/record/mapping.rb +25 -0
- data/lib/lhs/concerns/record/merge.rb +26 -0
- data/lib/lhs/concerns/record/model.rb +23 -0
- data/lib/lhs/concerns/record/pagination.rb +47 -0
- data/lib/lhs/concerns/record/provider.rb +23 -0
- data/lib/lhs/concerns/record/relations.rb +26 -0
- data/lib/lhs/concerns/record/request.rb +620 -0
- data/lib/lhs/concerns/record/scope.rb +25 -0
- data/lib/lhs/concerns/record/tracing.rb +24 -0
- data/lib/lhs/concerns/record/update.rb +17 -0
- data/lib/lhs/config.rb +24 -0
- data/lib/lhs/data.rb +165 -0
- data/lib/lhs/endpoint.rb +12 -0
- data/lib/lhs/interceptors/auto_oauth/interceptor.rb +33 -0
- data/lib/lhs/interceptors/auto_oauth/thread_registry.rb +18 -0
- 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/item.rb +59 -0
- data/lib/lhs/pagination/base.rb +90 -0
- data/lib/lhs/pagination/link.rb +21 -0
- data/lib/lhs/pagination/offset.rb +22 -0
- data/lib/lhs/pagination/page.rb +18 -0
- data/lib/lhs/pagination/start.rb +22 -0
- data/lib/lhs/problems/base.rb +113 -0
- data/lib/lhs/problems/errors.rb +69 -0
- data/lib/lhs/problems/nested/base.rb +54 -0
- data/lib/lhs/problems/nested/errors.rb +16 -0
- data/lib/lhs/problems/nested/warnings.rb +15 -0
- data/lib/lhs/problems/warnings.rb +24 -0
- data/lib/lhs/proxy.rb +68 -0
- data/lib/lhs/railtie.rb +34 -0
- data/lib/lhs/record.rb +112 -0
- data/lib/lhs/rspec.rb +10 -0
- data/lib/lhs/test/stubbable_records.rb +34 -0
- data/lib/lhs/unprocessable.rb +6 -0
- data/lib/lhs/version.rb +5 -0
- data/script/ci/build.sh +18 -0
- data/spec/auto_oauth_spec.rb +169 -0
- data/spec/autoloading_spec.rb +48 -0
- data/spec/collection/accessors_spec.rb +31 -0
- data/spec/collection/collection_items_spec.rb +44 -0
- data/spec/collection/configurable_spec.rb +43 -0
- data/spec/collection/delegate_spec.rb +21 -0
- data/spec/collection/enumerable_spec.rb +27 -0
- data/spec/collection/href_spec.rb +17 -0
- data/spec/collection/meta_data_spec.rb +57 -0
- data/spec/collection/respond_to_spec.rb +20 -0
- data/spec/collection/to_a_spec.rb +34 -0
- data/spec/collection/to_ary_spec.rb +40 -0
- data/spec/collection/without_object_items_spec.rb +27 -0
- data/spec/complex/reduce_spec.rb +202 -0
- data/spec/concerns/record/request_spec.rb +78 -0
- data/spec/data/collection_spec.rb +56 -0
- data/spec/data/equality_spec.rb +23 -0
- data/spec/data/inspect_spec.rb +88 -0
- data/spec/data/is_item_or_collection_spec.rb +40 -0
- data/spec/data/item_spec.rb +106 -0
- data/spec/data/merge_spec.rb +27 -0
- data/spec/data/parent_spec.rb +39 -0
- data/spec/data/raw_spec.rb +48 -0
- data/spec/data/respond_to_spec.rb +26 -0
- data/spec/data/root_spec.rb +25 -0
- data/spec/data/select_spec.rb +27 -0
- data/spec/data/to_ary_spec.rb +28 -0
- data/spec/data/to_json_spec.rb +68 -0
- data/spec/dummy/Rakefile +8 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +26 -0
- data/spec/dummy/app/controllers/automatic_authentication_controller.rb +29 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +36 -0
- data/spec/dummy/app/controllers/extended_rollbar_controller.rb +10 -0
- data/spec/dummy/app/controllers/option_blocks_controller.rb +15 -0
- data/spec/dummy/app/controllers/request_cycle_cache_controller.rb +27 -0
- data/spec/dummy/app/helpers/application_helper.rb +4 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/dummy_customer.rb +6 -0
- data/spec/dummy/app/models/dummy_record.rb +6 -0
- data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
- data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
- data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
- data/spec/dummy/app/models/dummy_user.rb +6 -0
- data/spec/dummy/app/models/providers/customer_system.rb +7 -0
- data/spec/dummy/app/models/providers/internal_services.rb +7 -0
- data/spec/dummy/app/views/error_handling_with_chains/error.html.erb +1 -0
- data/spec/dummy/app/views/error_handling_with_chains/show.html.erb +3 -0
- data/spec/dummy/app/views/form_for.html.erb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +5 -0
- data/spec/dummy/bin/rails +6 -0
- data/spec/dummy/bin/rake +6 -0
- data/spec/dummy/config.ru +6 -0
- data/spec/dummy/config/application.rb +16 -0
- data/spec/dummy/config/boot.rb +7 -0
- data/spec/dummy/config/environment.rb +7 -0
- data/spec/dummy/config/environments/development.rb +36 -0
- data/spec/dummy/config/environments/production.rb +77 -0
- data/spec/dummy/config/environments/test.rb +40 -0
- data/spec/dummy/config/initializers/assets.rb +10 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
- data/spec/dummy/config/initializers/inflections.rb +18 -0
- data/spec/dummy/config/initializers/mime_types.rb +6 -0
- data/spec/dummy/config/initializers/rollbar.rb +9 -0
- data/spec/dummy/config/initializers/session_store.rb +5 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +27 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/endpoint/for_url_spec.rb +27 -0
- data/spec/extended_rollbar_spec.rb +67 -0
- data/spec/item/access_errors_spec.rb +33 -0
- data/spec/item/accessors_spec.rb +21 -0
- data/spec/item/add_error_spec.rb +21 -0
- data/spec/item/becomes_spec.rb +38 -0
- data/spec/item/blacklisted_keywords_spec.rb +30 -0
- data/spec/item/delegate_spec.rb +32 -0
- data/spec/item/destroy_spec.rb +113 -0
- data/spec/item/dig_spec.rb +29 -0
- data/spec/item/error_codes_spec.rb +55 -0
- data/spec/item/errors_spec.rb +324 -0
- data/spec/item/fetch_spec.rb +39 -0
- data/spec/item/getter_spec.rb +24 -0
- data/spec/item/internal_data_structure_spec.rb +37 -0
- data/spec/item/map_spec.rb +46 -0
- data/spec/item/nested_errors_spec.rb +28 -0
- data/spec/item/partial_update_spec.rb +170 -0
- data/spec/item/respond_to_spec.rb +31 -0
- data/spec/item/save_spec.rb +115 -0
- data/spec/item/setter_spec.rb +44 -0
- data/spec/item/translate_errors_spec.rb +257 -0
- data/spec/item/update_spec.rb +161 -0
- data/spec/item/validation_spec.rb +131 -0
- data/spec/item/warning_codes_spec.rb +55 -0
- data/spec/item/warnings_spec.rb +52 -0
- data/spec/option_blocks/ensure_reset_between_requests_spec.rb +23 -0
- data/spec/option_blocks/main_spec.rb +55 -0
- data/spec/pagination/link/current_page_spec.rb +19 -0
- data/spec/pagination/link/pages_left_spec.rb +36 -0
- data/spec/pagination/link/parallel_spec.rb +19 -0
- data/spec/pagination/link/total_spec.rb +46 -0
- data/spec/pagination/offset/pages_left_spec.rb +26 -0
- data/spec/pagination/parameters_spec.rb +61 -0
- data/spec/proxy/create_sub_resource_spec.rb +182 -0
- data/spec/proxy/load_spec.rb +75 -0
- data/spec/proxy/record_identification_spec.rb +35 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/record/all_spec.rb +133 -0
- data/spec/record/attribute_assignment_spec.rb +28 -0
- data/spec/record/build_spec.rb +26 -0
- data/spec/record/cast_nested_data_spec.rb +78 -0
- data/spec/record/create_spec.rb +160 -0
- data/spec/record/creation_failed_spec.rb +55 -0
- data/spec/record/custom_setters_spec.rb +45 -0
- data/spec/record/definitions_spec.rb +29 -0
- data/spec/record/destroy_spec.rb +38 -0
- data/spec/record/dig_configuration_spec.rb +75 -0
- data/spec/record/dup_spec.rb +20 -0
- data/spec/record/endpoint_inheritance_spec.rb +65 -0
- data/spec/record/endpoint_options_spec.rb +52 -0
- data/spec/record/endpoint_priorities_spec.rb +26 -0
- data/spec/record/endpoints_spec.rb +96 -0
- data/spec/record/equality_spec.rb +27 -0
- data/spec/record/error_handling_integration_spec.rb +25 -0
- data/spec/record/error_handling_spec.rb +40 -0
- data/spec/record/expanded_spec.rb +69 -0
- data/spec/record/fetch_spec.rb +41 -0
- data/spec/record/find_by_chains_spec.rb +21 -0
- data/spec/record/find_by_spec.rb +76 -0
- data/spec/record/find_each_spec.rb +57 -0
- data/spec/record/find_in_batches_spec.rb +122 -0
- data/spec/record/find_in_parallel_spec.rb +67 -0
- data/spec/record/find_spec.rb +104 -0
- data/spec/record/first_spec.rb +39 -0
- data/spec/record/force_merge_spec.rb +56 -0
- data/spec/record/handle_includes_errors_spec.rb +32 -0
- data/spec/record/has_many_spec.rb +120 -0
- data/spec/record/has_one_spec.rb +116 -0
- data/spec/record/href_for_spec.rb +25 -0
- data/spec/record/ignore_errors_spec.rb +139 -0
- data/spec/record/immutable_chains_spec.rb +22 -0
- data/spec/record/includes_first_page_spec.rb +737 -0
- data/spec/record/includes_spec.rb +693 -0
- data/spec/record/includes_warning_spec.rb +46 -0
- data/spec/record/item_key_spec.rb +81 -0
- data/spec/record/items_created_key_configuration_spec.rb +37 -0
- data/spec/record/last_spec.rb +68 -0
- data/spec/record/loading_twice_spec.rb +19 -0
- data/spec/record/mapping_spec.rb +102 -0
- data/spec/record/model_name_spec.rb +17 -0
- data/spec/record/new_spec.rb +106 -0
- data/spec/record/options_getter_spec.rb +26 -0
- data/spec/record/options_spec.rb +164 -0
- data/spec/record/paginatable_collection_spec.rb +360 -0
- data/spec/record/pagination_chain_spec.rb +101 -0
- data/spec/record/pagination_links_spec.rb +72 -0
- data/spec/record/pagination_spec.rb +71 -0
- data/spec/record/persisted_spec.rb +52 -0
- data/spec/record/provider_spec.rb +41 -0
- data/spec/record/references_spec.rb +53 -0
- data/spec/record/relation_caching_spec.rb +121 -0
- data/spec/record/reload_by_id_spec.rb +43 -0
- data/spec/record/reload_spec.rb +65 -0
- data/spec/record/request_spec.rb +90 -0
- data/spec/record/save_spec.rb +40 -0
- data/spec/record/scope_chains_spec.rb +39 -0
- data/spec/record/select_spec.rb +17 -0
- data/spec/record/to_ary_spec.rb +65 -0
- data/spec/record/to_hash_spec.rb +22 -0
- data/spec/record/to_json_spec.rb +22 -0
- data/spec/record/tracing_spec.rb +154 -0
- data/spec/record/update_spec.rb +62 -0
- data/spec/record/where_chains_spec.rb +57 -0
- data/spec/record/where_spec.rb +62 -0
- data/spec/record/where_values_hash_spec.rb +32 -0
- data/spec/request_cycle_cache_spec.rb +106 -0
- data/spec/require_lhs_spec.rb +9 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/stubs/all_spec.rb +72 -0
- data/spec/support/fixtures/json/feedback.json +11 -0
- data/spec/support/fixtures/json/feedbacks.json +174 -0
- data/spec/support/fixtures/json/localina_content_ad.json +23 -0
- data/spec/support/load_json.rb +5 -0
- data/spec/support/request_cycle_cache.rb +10 -0
- data/spec/support/reset.rb +67 -0
- data/spec/views/form_for_spec.rb +20 -0
- metadata +776 -0
|
@@ -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/item.rb
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# An item is a concrete record.
|
|
4
|
+
# It can be part of another proxy like collection.
|
|
5
|
+
class LHS::Item < LHS::Proxy
|
|
6
|
+
|
|
7
|
+
autoload :Destroy,
|
|
8
|
+
'lhs/concerns/item/destroy'
|
|
9
|
+
autoload :Save,
|
|
10
|
+
'lhs/concerns/item/save'
|
|
11
|
+
autoload :Update,
|
|
12
|
+
'lhs/concerns/item/update'
|
|
13
|
+
autoload :Validation,
|
|
14
|
+
'lhs/concerns/item/validation'
|
|
15
|
+
|
|
16
|
+
include Create
|
|
17
|
+
include Destroy
|
|
18
|
+
include Save
|
|
19
|
+
include Update
|
|
20
|
+
include Validation
|
|
21
|
+
|
|
22
|
+
delegate :map, :present?, :blank?, :empty?, to: :_raw, allow_nil: true
|
|
23
|
+
delegate :_raw, to: :_data
|
|
24
|
+
|
|
25
|
+
def collection?
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def item?
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def respond_to?(sym, include_all = false)
|
|
34
|
+
if sym == :to_ary
|
|
35
|
+
false
|
|
36
|
+
else
|
|
37
|
+
super(sym, include_all)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
protected
|
|
42
|
+
|
|
43
|
+
def method_missing(name, *args, &_block)
|
|
44
|
+
return set(name, args) if name.to_s[/=$/]
|
|
45
|
+
get(name, *args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def respond_to_missing?(name, _include_all = false)
|
|
49
|
+
# We accept every message that does not belong to set of keywords
|
|
50
|
+
!BLACKLISTED_KEYWORDS.include?(name.to_s)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def unwrap_nested_item
|
|
54
|
+
return _data unless _record.item_key
|
|
55
|
+
nested_data = _data.dig(*_record.item_key)
|
|
56
|
+
return _data unless nested_data
|
|
57
|
+
LHS::Data.new(nested_data, _data._parent, _record, _data._request, _data._endpoint)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
|
4
|
+
|
|
5
|
+
# Pagination is used to navigate paginateable collections
|
|
6
|
+
module LHS::Pagination
|
|
7
|
+
class Base
|
|
8
|
+
|
|
9
|
+
DEFAULT_LIMIT = 100
|
|
10
|
+
|
|
11
|
+
delegate :_record, to: :data
|
|
12
|
+
attr_accessor :data
|
|
13
|
+
|
|
14
|
+
def initialize(data)
|
|
15
|
+
self.data = data
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def total
|
|
19
|
+
data._raw.dig(*_record.total_key) || 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# as standard in Rails' ActiveRecord count is not summing up, but using the number provided from data source
|
|
23
|
+
alias count total
|
|
24
|
+
|
|
25
|
+
def limit
|
|
26
|
+
data._raw.dig(*_record.limit_key(:body)) || DEFAULT_LIMIT
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def offset
|
|
30
|
+
data._raw.dig(*_record.pagination_key(:body)) || self.class::DEFAULT_OFFSET
|
|
31
|
+
end
|
|
32
|
+
alias start offset
|
|
33
|
+
|
|
34
|
+
def pages_left
|
|
35
|
+
total_pages - current_page
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def pages_left?
|
|
39
|
+
pages_left > 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def next_offset(_step = 1)
|
|
43
|
+
raise 'to be implemented in subclass'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def current_page
|
|
47
|
+
# should be implemented in subclass (optional)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def first_page
|
|
51
|
+
1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def last_page
|
|
55
|
+
total_pages
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parallel?
|
|
59
|
+
true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def next?
|
|
63
|
+
data._raw[:next].present?
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def previous?
|
|
67
|
+
data._raw[:previous].present?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def prev_page
|
|
71
|
+
current_page - 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def next_page
|
|
75
|
+
current_page + 1
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def limit_value
|
|
79
|
+
limit
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def total_pages
|
|
83
|
+
(total.to_f / limit).ceil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.page_to_offset(page, _limit)
|
|
87
|
+
page.to_i
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHS::Pagination::Link < LHS::Pagination::Base
|
|
4
|
+
def total
|
|
5
|
+
data._raw.dig(*_record.items_key).count || 0
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
alias count total
|
|
9
|
+
|
|
10
|
+
def pages_left
|
|
11
|
+
pages_left? ? 1 : 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pages_left?
|
|
15
|
+
data._raw[:next].present?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parallel?
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHS::Pagination::Offset < LHS::Pagination::Base
|
|
4
|
+
|
|
5
|
+
DEFAULT_OFFSET = 0
|
|
6
|
+
|
|
7
|
+
def current_page
|
|
8
|
+
(offset + limit) / limit
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def next_offset(step = 1)
|
|
12
|
+
self.class.next_offset(offset, limit, step)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.page_to_offset(page, limit = DEFAULT_LIMIT)
|
|
16
|
+
(page.to_i - 1) * limit.to_i
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.next_offset(offset, limit, step = 1)
|
|
20
|
+
offset.to_i + limit.to_i * step.to_i
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHS::Pagination::Page < LHS::Pagination::Base
|
|
4
|
+
|
|
5
|
+
DEFAULT_OFFSET = 1
|
|
6
|
+
|
|
7
|
+
def current_page
|
|
8
|
+
offset
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def next_offset(step = 1)
|
|
12
|
+
self.class.next_offset(current_page, limit, step)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.next_offset(current_page, _limit, step = 1)
|
|
16
|
+
current_page.to_i + step.to_i
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class LHS::Pagination::Start < LHS::Pagination::Base
|
|
4
|
+
|
|
5
|
+
DEFAULT_OFFSET = 1
|
|
6
|
+
|
|
7
|
+
def current_page
|
|
8
|
+
(offset + limit - 1) / limit
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def next_offset(step = 1)
|
|
12
|
+
self.class.next_offset(offset, limit, step)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.page_to_offset(page, limit = DEFAULT_LIMIT)
|
|
16
|
+
(page.to_i - 1) * limit.to_i + 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.next_offset(offset, limit, step = 1)
|
|
20
|
+
offset.to_i + limit.to_i * step.to_i
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/core_ext/module'
|
|
4
|
+
require 'active_support/core_ext/hash'
|
|
5
|
+
|
|
6
|
+
# Like ActiveModel::Errors
|
|
7
|
+
module LHS::Problems
|
|
8
|
+
class Base
|
|
9
|
+
include Enumerable
|
|
10
|
+
|
|
11
|
+
attr_reader :raw, :messages, :codes, :record
|
|
12
|
+
|
|
13
|
+
def include?(attribute)
|
|
14
|
+
messages[attribute].present?
|
|
15
|
+
end
|
|
16
|
+
alias has_key? include?
|
|
17
|
+
alias key? include?
|
|
18
|
+
|
|
19
|
+
def add(attribute, message = :invalid, options = {})
|
|
20
|
+
self[attribute]
|
|
21
|
+
messages[attribute] << generate_message(attribute, message, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get(key)
|
|
25
|
+
messages[key]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set(key, message)
|
|
29
|
+
return if message.blank?
|
|
30
|
+
messages[key] = [generate_message(key, message)]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
delegate :delete, to: :messages
|
|
34
|
+
|
|
35
|
+
def [](attribute)
|
|
36
|
+
get(attribute.to_sym) || messages[attribute] = []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def []=(attribute, message)
|
|
40
|
+
self[attribute] << generate_message(attribute, message)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def each
|
|
44
|
+
if messages.is_a?(Hash)
|
|
45
|
+
messages.each_key do |attribute|
|
|
46
|
+
self[attribute].each { |message| yield attribute, message }
|
|
47
|
+
end
|
|
48
|
+
elsif messages.is_a?(Array)
|
|
49
|
+
messages.each { |message| yield message }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def size
|
|
54
|
+
values.flatten.size
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def clear
|
|
58
|
+
@raw = nil
|
|
59
|
+
@messages.clear
|
|
60
|
+
@codes.clear
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
delegate :values, to: :messages
|
|
64
|
+
|
|
65
|
+
delegate :keys, to: :messages
|
|
66
|
+
|
|
67
|
+
def count
|
|
68
|
+
to_a.size
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def empty?
|
|
72
|
+
all? { |_k, v| v&.empty? && !v.is_a?(String) }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def add_error(messages, key, value)
|
|
78
|
+
key = key.to_sym
|
|
79
|
+
codes[key] ||= []
|
|
80
|
+
codes[key].push(value)
|
|
81
|
+
messages[key] ||= []
|
|
82
|
+
messages[key].push(generate_message(key, value))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def generate_message(attribute, message, _options = {})
|
|
86
|
+
problem_type = self.class.name.demodulize.downcase
|
|
87
|
+
find_translated_message(attribute, message, problem_type) || message
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def find_translated_message(attribute, message, problem_type)
|
|
91
|
+
normalized_attribute = attribute.to_s.underscore.gsub(/\.[\d+\.]/, '')
|
|
92
|
+
normalized_message = message.to_s.underscore
|
|
93
|
+
messages = []
|
|
94
|
+
messages = messages_for_record(normalized_attribute, normalized_message, problem_type) if record
|
|
95
|
+
messages.concat([
|
|
96
|
+
['lhs', problem_type, 'messages', normalized_message],
|
|
97
|
+
['lhs', problem_type, 'attributes', normalized_attribute, normalized_message],
|
|
98
|
+
['lhs', problem_type, 'fallback_message']
|
|
99
|
+
]).detect do |path|
|
|
100
|
+
key = path.join('.')
|
|
101
|
+
return I18n.translate(key) if I18n.exists?(key)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def messages_for_record(normalized_attribute, normalized_message, problem_type)
|
|
106
|
+
record_name = record.model_name.name.underscore
|
|
107
|
+
[
|
|
108
|
+
['lhs', problem_type, 'records', record_name, 'attributes', normalized_attribute, normalized_message],
|
|
109
|
+
['lhs', problem_type, 'records', record_name, normalized_message]
|
|
110
|
+
]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LHS::Problems
|
|
4
|
+
class Errors < Base
|
|
5
|
+
|
|
6
|
+
attr_reader :status_code, :message
|
|
7
|
+
|
|
8
|
+
def initialize(response = nil, record = nil)
|
|
9
|
+
@raw = response.body if response
|
|
10
|
+
@record = record
|
|
11
|
+
@codes = {}.with_indifferent_access
|
|
12
|
+
@messages = messages_from_response(response).with_indifferent_access
|
|
13
|
+
@message = message_from_response(response)
|
|
14
|
+
@status_code = response.code if response
|
|
15
|
+
rescue JSON::ParserError
|
|
16
|
+
@messages = (messages || {}).with_indifferent_access
|
|
17
|
+
@codes = (codes || {}).with_indifferent_access
|
|
18
|
+
@message = 'parse error'
|
|
19
|
+
add_error(@messages, 'body', 'parse error')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def parse_messages(json)
|
|
25
|
+
messages = {}
|
|
26
|
+
fields_to_errors(json, messages) if json['fields']
|
|
27
|
+
field_errors_to_errors(json, messages) if json['field_errors']
|
|
28
|
+
fallback_errors(json, messages) if messages.empty? && !json['fields'] && !json['field_errors']
|
|
29
|
+
messages
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def fallback_errors(json, messages)
|
|
33
|
+
if json.present?
|
|
34
|
+
json.each do |key, value|
|
|
35
|
+
add_error(messages, key, value)
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
add_error(messages, 'unknown', 'error')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def field_errors_to_errors(json, messages)
|
|
43
|
+
json['field_errors'].each do |field_error|
|
|
44
|
+
add_error(messages, field_error['path'].join('.').to_sym, field_error['code'])
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def fields_to_errors(json, messages)
|
|
49
|
+
json['fields'].each do |field|
|
|
50
|
+
field['details'].each do |detail|
|
|
51
|
+
add_error(messages, field['name'].to_sym, detail['code'])
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def messages_from_response(response = nil)
|
|
57
|
+
return {} if !response || !response.body.is_a?(String) || response.body.length.zero?
|
|
58
|
+
json = JSON.parse(response.body)
|
|
59
|
+
parse_messages(json)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def message_from_response(response = nil)
|
|
63
|
+
return if response.blank?
|
|
64
|
+
raise JSON::ParserError if response.body.blank?
|
|
65
|
+
json = JSON.parse(response.body)
|
|
66
|
+
json['message']
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LHS::Problems
|
|
4
|
+
module Nested
|
|
5
|
+
module Base
|
|
6
|
+
# Filters base errors by scope
|
|
7
|
+
# and reduces key by given scope name;
|
|
8
|
+
# returns plain array if end of tree is reached
|
|
9
|
+
def nest(messages, scope = nil)
|
|
10
|
+
scope = translate_rails_to_api_scope(scope)
|
|
11
|
+
return messages unless scope
|
|
12
|
+
messages = messages.select do |key, _|
|
|
13
|
+
key.match(/^#{scope}/)
|
|
14
|
+
end
|
|
15
|
+
# if only one key and this key has no dots, exit with plain
|
|
16
|
+
if reached_leaf?(messages)
|
|
17
|
+
messages.first[1]
|
|
18
|
+
else
|
|
19
|
+
remove_scope(messages, scope)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Identifies if the end of nested errors tree is reached
|
|
24
|
+
def reached_leaf?(messages)
|
|
25
|
+
messages.keys.length == 1 &&
|
|
26
|
+
!messages.first[0].match(/\./)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Removes scope from given messages' key
|
|
30
|
+
def remove_scope(messages, scope)
|
|
31
|
+
messages.each_with_object({}) do |element, hash|
|
|
32
|
+
key = element[0].to_s.gsub(/^#{scope}\./, '')
|
|
33
|
+
hash[key.to_sym] = element[1]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Translates rails like accessors for collections
|
|
38
|
+
# like first, second, last to api error paths
|
|
39
|
+
def translate_rails_to_api_scope(scope)
|
|
40
|
+
case scope
|
|
41
|
+
when :first
|
|
42
|
+
0
|
|
43
|
+
when :second
|
|
44
|
+
1
|
|
45
|
+
when :last
|
|
46
|
+
return values.length - 1 if messages.present?
|
|
47
|
+
0
|
|
48
|
+
else
|
|
49
|
+
scope
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|