dhs 1.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.
Files changed (301) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rubocop.yml +27 -0
  3. data/.github/workflows/test.yml +27 -0
  4. data/.gitignore +39 -0
  5. data/.rubocop.yml +186 -0
  6. data/.ruby-version +1 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +674 -0
  9. data/README.md +2807 -0
  10. data/Rakefile +26 -0
  11. data/dhs.gemspec +44 -0
  12. data/docs/accessing-data.png +0 -0
  13. data/lib/dhs.rb +67 -0
  14. data/lib/dhs/collection.rb +84 -0
  15. data/lib/dhs/complex.rb +158 -0
  16. data/lib/dhs/concerns/autoload_records.rb +57 -0
  17. data/lib/dhs/concerns/collection/handle_nested.rb +43 -0
  18. data/lib/dhs/concerns/collection/internal_collection.rb +74 -0
  19. data/lib/dhs/concerns/configuration.rb +20 -0
  20. data/lib/dhs/concerns/data/becomes.rb +18 -0
  21. data/lib/dhs/concerns/data/equality.rb +14 -0
  22. data/lib/dhs/concerns/data/extend.rb +87 -0
  23. data/lib/dhs/concerns/data/json.rb +14 -0
  24. data/lib/dhs/concerns/data/to_hash.rb +14 -0
  25. data/lib/dhs/concerns/inspect.rb +70 -0
  26. data/lib/dhs/concerns/is_href.rb +15 -0
  27. data/lib/dhs/concerns/item/destroy.rb +38 -0
  28. data/lib/dhs/concerns/item/endpoint_lookup.rb +27 -0
  29. data/lib/dhs/concerns/item/save.rb +55 -0
  30. data/lib/dhs/concerns/item/update.rb +50 -0
  31. data/lib/dhs/concerns/item/validation.rb +61 -0
  32. data/lib/dhs/concerns/o_auth.rb +25 -0
  33. data/lib/dhs/concerns/option_blocks.rb +26 -0
  34. data/lib/dhs/concerns/proxy/accessors.rb +132 -0
  35. data/lib/dhs/concerns/proxy/create.rb +45 -0
  36. data/lib/dhs/concerns/proxy/link.rb +25 -0
  37. data/lib/dhs/concerns/proxy/problems.rb +27 -0
  38. data/lib/dhs/concerns/record/attribute_assignment.rb +25 -0
  39. data/lib/dhs/concerns/record/batch.rb +40 -0
  40. data/lib/dhs/concerns/record/chainable.rb +465 -0
  41. data/lib/dhs/concerns/record/configuration.rb +103 -0
  42. data/lib/dhs/concerns/record/create.rb +24 -0
  43. data/lib/dhs/concerns/record/custom_setters.rb +22 -0
  44. data/lib/dhs/concerns/record/destroy.rb +18 -0
  45. data/lib/dhs/concerns/record/endpoints.rb +108 -0
  46. data/lib/dhs/concerns/record/equality.rb +14 -0
  47. data/lib/dhs/concerns/record/find.rb +86 -0
  48. data/lib/dhs/concerns/record/find_by.rb +38 -0
  49. data/lib/dhs/concerns/record/first.rb +20 -0
  50. data/lib/dhs/concerns/record/href_for.rb +19 -0
  51. data/lib/dhs/concerns/record/last.rb +27 -0
  52. data/lib/dhs/concerns/record/mapping.rb +25 -0
  53. data/lib/dhs/concerns/record/merge.rb +26 -0
  54. data/lib/dhs/concerns/record/model.rb +23 -0
  55. data/lib/dhs/concerns/record/pagination.rb +49 -0
  56. data/lib/dhs/concerns/record/provider.rb +23 -0
  57. data/lib/dhs/concerns/record/relations.rb +26 -0
  58. data/lib/dhs/concerns/record/request.rb +581 -0
  59. data/lib/dhs/concerns/record/scope.rb +25 -0
  60. data/lib/dhs/concerns/record/tracing.rb +24 -0
  61. data/lib/dhs/concerns/record/update.rb +17 -0
  62. data/lib/dhs/config.rb +24 -0
  63. data/lib/dhs/data.rb +180 -0
  64. data/lib/dhs/endpoint.rb +12 -0
  65. data/lib/dhs/interceptors/auto_oauth/interceptor.rb +33 -0
  66. data/lib/dhs/interceptors/auto_oauth/thread_registry.rb +18 -0
  67. data/lib/dhs/interceptors/extended_rollbar/handler.rb +40 -0
  68. data/lib/dhs/interceptors/extended_rollbar/interceptor.rb +20 -0
  69. data/lib/dhs/interceptors/extended_rollbar/thread_registry.rb +19 -0
  70. data/lib/dhs/interceptors/request_cycle_cache/interceptor.rb +41 -0
  71. data/lib/dhs/interceptors/request_cycle_cache/thread_registry.rb +18 -0
  72. data/lib/dhs/item.rb +59 -0
  73. data/lib/dhs/pagination/base.rb +90 -0
  74. data/lib/dhs/pagination/link.rb +21 -0
  75. data/lib/dhs/pagination/offset.rb +22 -0
  76. data/lib/dhs/pagination/page.rb +18 -0
  77. data/lib/dhs/pagination/start.rb +22 -0
  78. data/lib/dhs/pagination/total_pages.rb +9 -0
  79. data/lib/dhs/problems/base.rb +113 -0
  80. data/lib/dhs/problems/errors.rb +69 -0
  81. data/lib/dhs/problems/nested/base.rb +54 -0
  82. data/lib/dhs/problems/nested/errors.rb +16 -0
  83. data/lib/dhs/problems/nested/warnings.rb +15 -0
  84. data/lib/dhs/problems/warnings.rb +24 -0
  85. data/lib/dhs/proxy.rb +69 -0
  86. data/lib/dhs/railtie.rb +34 -0
  87. data/lib/dhs/record.rb +112 -0
  88. data/lib/dhs/rspec.rb +10 -0
  89. data/lib/dhs/test/stubbable_records.rb +34 -0
  90. data/lib/dhs/unprocessable.rb +6 -0
  91. data/lib/dhs/version.rb +5 -0
  92. data/script/ci/build.sh +18 -0
  93. data/spec/auto_oauth_spec.rb +163 -0
  94. data/spec/autoloading_spec.rb +45 -0
  95. data/spec/collection/accessors_spec.rb +31 -0
  96. data/spec/collection/collection_items_spec.rb +44 -0
  97. data/spec/collection/configurable_spec.rb +43 -0
  98. data/spec/collection/delegate_spec.rb +21 -0
  99. data/spec/collection/enumerable_spec.rb +27 -0
  100. data/spec/collection/href_spec.rb +17 -0
  101. data/spec/collection/meta_data_spec.rb +58 -0
  102. data/spec/collection/respond_to_spec.rb +20 -0
  103. data/spec/collection/to_a_spec.rb +34 -0
  104. data/spec/collection/to_ary_spec.rb +40 -0
  105. data/spec/collection/without_object_items_spec.rb +27 -0
  106. data/spec/complex/reduce_spec.rb +202 -0
  107. data/spec/concerns/record/request_spec.rb +78 -0
  108. data/spec/data/collection_spec.rb +56 -0
  109. data/spec/data/equality_spec.rb +23 -0
  110. data/spec/data/inspect_spec.rb +88 -0
  111. data/spec/data/is_item_or_collection_spec.rb +40 -0
  112. data/spec/data/item_spec.rb +106 -0
  113. data/spec/data/merge_spec.rb +27 -0
  114. data/spec/data/parent_spec.rb +39 -0
  115. data/spec/data/raw_spec.rb +48 -0
  116. data/spec/data/respond_to_spec.rb +26 -0
  117. data/spec/data/root_spec.rb +25 -0
  118. data/spec/data/select_spec.rb +27 -0
  119. data/spec/data/to_ary_spec.rb +28 -0
  120. data/spec/data/to_json_spec.rb +68 -0
  121. data/spec/dummy/Rakefile +8 -0
  122. data/spec/dummy/app/assets/images/.keep +0 -0
  123. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  124. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  125. data/spec/dummy/app/controllers/application_controller.rb +26 -0
  126. data/spec/dummy/app/controllers/automatic_authentication_controller.rb +29 -0
  127. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  128. data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +36 -0
  129. data/spec/dummy/app/controllers/extended_rollbar_controller.rb +10 -0
  130. data/spec/dummy/app/controllers/option_blocks_controller.rb +15 -0
  131. data/spec/dummy/app/controllers/request_cycle_cache_controller.rb +27 -0
  132. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  133. data/spec/dummy/app/mailers/.keep +0 -0
  134. data/spec/dummy/app/models/.keep +0 -0
  135. data/spec/dummy/app/models/concerns/.keep +0 -0
  136. data/spec/dummy/app/models/concerns/dummy_customer/some_concern.rb +9 -0
  137. data/spec/dummy/app/models/dummy_customer.rb +7 -0
  138. data/spec/dummy/app/models/dummy_record.rb +6 -0
  139. data/spec/dummy/app/models/dummy_record_with_auto_oauth_provider.rb +6 -0
  140. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
  141. data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
  142. data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
  143. data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
  144. data/spec/dummy/app/models/dummy_user.rb +6 -0
  145. data/spec/dummy/app/models/providers/customer_system.rb +7 -0
  146. data/spec/dummy/app/models/providers/internal_services.rb +7 -0
  147. data/spec/dummy/app/views/error_handling_with_chains/error.html.erb +1 -0
  148. data/spec/dummy/app/views/error_handling_with_chains/show.html.erb +3 -0
  149. data/spec/dummy/app/views/form_for.html.erb +5 -0
  150. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  151. data/spec/dummy/bin/bundle +5 -0
  152. data/spec/dummy/bin/rails +6 -0
  153. data/spec/dummy/bin/rake +6 -0
  154. data/spec/dummy/config.ru +6 -0
  155. data/spec/dummy/config/application.rb +16 -0
  156. data/spec/dummy/config/boot.rb +7 -0
  157. data/spec/dummy/config/environment.rb +7 -0
  158. data/spec/dummy/config/environments/development.rb +36 -0
  159. data/spec/dummy/config/environments/production.rb +77 -0
  160. data/spec/dummy/config/environments/test.rb +40 -0
  161. data/spec/dummy/config/initializers/assets.rb +10 -0
  162. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  163. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  164. data/spec/dummy/config/initializers/dhs.rb +5 -0
  165. data/spec/dummy/config/initializers/filter_parameter_logging.rb +6 -0
  166. data/spec/dummy/config/initializers/inflections.rb +18 -0
  167. data/spec/dummy/config/initializers/mime_types.rb +6 -0
  168. data/spec/dummy/config/initializers/rollbar.rb +9 -0
  169. data/spec/dummy/config/initializers/session_store.rb +5 -0
  170. data/spec/dummy/config/initializers/wrap_parameters.rb +11 -0
  171. data/spec/dummy/config/locales/en.yml +23 -0
  172. data/spec/dummy/config/routes.rb +27 -0
  173. data/spec/dummy/config/secrets.yml +22 -0
  174. data/spec/dummy/lib/assets/.keep +0 -0
  175. data/spec/dummy/public/404.html +67 -0
  176. data/spec/dummy/public/422.html +67 -0
  177. data/spec/dummy/public/500.html +66 -0
  178. data/spec/dummy/public/favicon.ico +0 -0
  179. data/spec/endpoint/for_url_spec.rb +27 -0
  180. data/spec/extended_rollbar_spec.rb +67 -0
  181. data/spec/item/access_errors_spec.rb +31 -0
  182. data/spec/item/accessors_spec.rb +21 -0
  183. data/spec/item/add_error_spec.rb +21 -0
  184. data/spec/item/becomes_spec.rb +38 -0
  185. data/spec/item/blacklisted_keywords_spec.rb +28 -0
  186. data/spec/item/delegate_spec.rb +32 -0
  187. data/spec/item/destroy_spec.rb +113 -0
  188. data/spec/item/dig_spec.rb +29 -0
  189. data/spec/item/error_codes_spec.rb +55 -0
  190. data/spec/item/errors_spec.rb +324 -0
  191. data/spec/item/fetch_spec.rb +39 -0
  192. data/spec/item/getter_spec.rb +24 -0
  193. data/spec/item/internal_data_structure_spec.rb +37 -0
  194. data/spec/item/map_spec.rb +46 -0
  195. data/spec/item/nested_errors_spec.rb +27 -0
  196. data/spec/item/partial_update_spec.rb +168 -0
  197. data/spec/item/respond_to_spec.rb +31 -0
  198. data/spec/item/save_spec.rb +115 -0
  199. data/spec/item/setter_spec.rb +44 -0
  200. data/spec/item/translate_errors_spec.rb +257 -0
  201. data/spec/item/update_spec.rb +161 -0
  202. data/spec/item/validation_spec.rb +131 -0
  203. data/spec/item/warning_codes_spec.rb +55 -0
  204. data/spec/item/warnings_spec.rb +51 -0
  205. data/spec/option_blocks/ensure_reset_between_requests_spec.rb +23 -0
  206. data/spec/option_blocks/main_spec.rb +54 -0
  207. data/spec/pagination/link/current_page_spec.rb +19 -0
  208. data/spec/pagination/link/pages_left_spec.rb +36 -0
  209. data/spec/pagination/link/parallel_spec.rb +19 -0
  210. data/spec/pagination/link/total_spec.rb +45 -0
  211. data/spec/pagination/offset/pages_left_spec.rb +26 -0
  212. data/spec/pagination/parameters_spec.rb +59 -0
  213. data/spec/pagination/total_pages_spec.rb +51 -0
  214. data/spec/proxy/create_sub_resource_spec.rb +182 -0
  215. data/spec/proxy/load_spec.rb +75 -0
  216. data/spec/proxy/record_identification_spec.rb +35 -0
  217. data/spec/rails_helper.rb +13 -0
  218. data/spec/record/all_spec.rb +133 -0
  219. data/spec/record/attribute_assignment_spec.rb +28 -0
  220. data/spec/record/build_spec.rb +26 -0
  221. data/spec/record/cast_nested_data_spec.rb +80 -0
  222. data/spec/record/compact_spec.rb +93 -0
  223. data/spec/record/create_spec.rb +160 -0
  224. data/spec/record/creation_failed_spec.rb +55 -0
  225. data/spec/record/custom_setters_spec.rb +42 -0
  226. data/spec/record/definitions_spec.rb +29 -0
  227. data/spec/record/destroy_spec.rb +38 -0
  228. data/spec/record/dig_configuration_spec.rb +75 -0
  229. data/spec/record/dup_spec.rb +20 -0
  230. data/spec/record/endpoint_inheritance_spec.rb +65 -0
  231. data/spec/record/endpoint_options_spec.rb +51 -0
  232. data/spec/record/endpoint_priorities_spec.rb +24 -0
  233. data/spec/record/endpoints_spec.rb +96 -0
  234. data/spec/record/equality_spec.rb +27 -0
  235. data/spec/record/error_handling_integration_spec.rb +25 -0
  236. data/spec/record/error_handling_spec.rb +40 -0
  237. data/spec/record/expanded_spec.rb +69 -0
  238. data/spec/record/fetch_spec.rb +40 -0
  239. data/spec/record/find_by_chains_spec.rb +21 -0
  240. data/spec/record/find_by_spec.rb +76 -0
  241. data/spec/record/find_each_spec.rb +57 -0
  242. data/spec/record/find_in_batches_spec.rb +122 -0
  243. data/spec/record/find_in_parallel_spec.rb +67 -0
  244. data/spec/record/find_spec.rb +103 -0
  245. data/spec/record/first_spec.rb +39 -0
  246. data/spec/record/force_merge_spec.rb +55 -0
  247. data/spec/record/handle_includes_errors_spec.rb +33 -0
  248. data/spec/record/has_many_spec.rb +118 -0
  249. data/spec/record/has_one_spec.rb +114 -0
  250. data/spec/record/href_for_spec.rb +24 -0
  251. data/spec/record/ignore_errors_spec.rb +137 -0
  252. data/spec/record/immutable_chains_spec.rb +22 -0
  253. data/spec/record/includes_after_expansion_spec.rb +70 -0
  254. data/spec/record/includes_expanded_spec.rb +37 -0
  255. data/spec/record/includes_first_page_spec.rb +738 -0
  256. data/spec/record/includes_missing_spec.rb +57 -0
  257. data/spec/record/includes_spec.rb +690 -0
  258. data/spec/record/includes_warning_spec.rb +46 -0
  259. data/spec/record/item_key_spec.rb +81 -0
  260. data/spec/record/items_created_key_configuration_spec.rb +37 -0
  261. data/spec/record/last_spec.rb +64 -0
  262. data/spec/record/loading_twice_spec.rb +19 -0
  263. data/spec/record/mapping_spec.rb +103 -0
  264. data/spec/record/model_name_spec.rb +17 -0
  265. data/spec/record/new_spec.rb +106 -0
  266. data/spec/record/options_getter_spec.rb +25 -0
  267. data/spec/record/options_spec.rb +164 -0
  268. data/spec/record/paginatable_collection_spec.rb +360 -0
  269. data/spec/record/pagination_chain_spec.rb +101 -0
  270. data/spec/record/pagination_links_spec.rb +72 -0
  271. data/spec/record/pagination_spec.rb +71 -0
  272. data/spec/record/persisted_spec.rb +52 -0
  273. data/spec/record/provider_spec.rb +40 -0
  274. data/spec/record/references_spec.rb +95 -0
  275. data/spec/record/relation_caching_spec.rb +120 -0
  276. data/spec/record/reload_by_id_spec.rb +43 -0
  277. data/spec/record/reload_spec.rb +64 -0
  278. data/spec/record/request_spec.rb +90 -0
  279. data/spec/record/save_spec.rb +40 -0
  280. data/spec/record/scope_chains_spec.rb +39 -0
  281. data/spec/record/select_spec.rb +17 -0
  282. data/spec/record/to_ary_spec.rb +65 -0
  283. data/spec/record/to_hash_spec.rb +22 -0
  284. data/spec/record/to_json_spec.rb +22 -0
  285. data/spec/record/tracing_spec.rb +149 -0
  286. data/spec/record/update_spec.rb +61 -0
  287. data/spec/record/where_chains_spec.rb +57 -0
  288. data/spec/record/where_spec.rb +62 -0
  289. data/spec/record/where_values_hash_spec.rb +32 -0
  290. data/spec/request_cycle_cache_spec.rb +106 -0
  291. data/spec/require_dhs_spec.rb +9 -0
  292. data/spec/spec_helper.rb +6 -0
  293. data/spec/stubs/all_spec.rb +69 -0
  294. data/spec/support/fixtures/json/feedback.json +11 -0
  295. data/spec/support/fixtures/json/feedbacks.json +174 -0
  296. data/spec/support/fixtures/json/localina_content_ad.json +23 -0
  297. data/spec/support/load_json.rb +5 -0
  298. data/spec/support/request_cycle_cache.rb +10 -0
  299. data/spec/support/reset.rb +67 -0
  300. data/spec/views/form_for_spec.rb +20 -0
  301. metadata +783 -0
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ class DHS::Record
6
+
7
+ # Scopes allow you to reuse common where queries
8
+ module Scope
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+ def scope(name, block)
13
+ scopes[name] = block
14
+ define_singleton_method(name) do |*args|
15
+ block.call(*args)
16
+ end
17
+ end
18
+
19
+ def scopes
20
+ @scopes ||= {}
21
+ @scopes
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ class DHS::Record
6
+
7
+ module Tracing
8
+ extend ActiveSupport::Concern
9
+
10
+ module ClassMethods
11
+ # Needs to be called directly from the first method (level) within DHS
12
+ def trace!(options = {})
13
+ return options unless DHS.config.trace
14
+
15
+ (options || {}).tap do |options|
16
+ source = caller.detect do |source|
17
+ !source.match?(%r{/lib/dhs}) && !source.match?(%r{internal\:})
18
+ end
19
+ options[:source] = source
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ class DHS::Record
6
+
7
+ module Update
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class <<self
12
+ alias_method :update, :create
13
+ alias_method :update!, :create!
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/dhs/config.rb ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ class DHS::Config
6
+ include Singleton
7
+
8
+ attr_accessor :request_cycle_cache_enabled, :request_cycle_cache, :trace, :auto_oauth
9
+
10
+ def initialize
11
+ self.request_cycle_cache_enabled ||= true
12
+ self.trace ||= false
13
+ if defined?(ActiveSupport::Cache::MemoryStore)
14
+ self.request_cycle_cache ||= ActiveSupport::Cache::MemoryStore.new
15
+ end
16
+ end
17
+
18
+ def reset
19
+ self.request_cycle_cache_enabled = nil
20
+ self.trace = nil
21
+ self.request_cycle_cache = nil
22
+ initialize
23
+ end
24
+ end
data/lib/dhs/data.rb ADDED
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Data provides functionalities to accesses information
4
+ class DHS::Data
5
+ autoload :Becomes,
6
+ 'dhs/concerns/data/becomes'
7
+ autoload :Equality,
8
+ 'dhs/concerns/data/equality'
9
+ autoload :Extend,
10
+ 'dhs/concerns/data/extend'
11
+ autoload :Json,
12
+ 'dhs/concerns/data/json'
13
+ autoload :ToHash,
14
+ 'dhs/concerns/data/to_hash'
15
+
16
+ include Becomes
17
+ include Equality
18
+ include Extend
19
+ include Json
20
+ include ToHash
21
+ include DHS::Inspect
22
+
23
+ delegate :instance_methods, :items_key, :limit_key, :total_key, :pagination_key, to: :class
24
+
25
+ # prevent clashing with attributes of underlying data
26
+ attr_accessor :_proxy, :_parent, :_record, :_request, :_endpoint
27
+ attr_reader :_raw
28
+
29
+ def initialize(input, parent = nil, record = nil, request = nil, endpoint = nil)
30
+ self._raw = raw_from_input(input)
31
+ self._parent = parent
32
+ self._record = record
33
+ self._proxy = proxy_from_input(input)
34
+ self._request = request
35
+ self._endpoint = endpoint
36
+ preserve_input_requests!(input)
37
+ end
38
+
39
+ # merging data
40
+ # e.g. when loading remote data via link
41
+ def merge_raw!(data)
42
+ return false if data.blank? || !data._raw.is_a?(Hash)
43
+ _raw.merge! data._raw
44
+ end
45
+
46
+ # Unwraps data for certain use cases
47
+ # like items_created_key for CREATE, UPDATED etc.
48
+ # like item_key for GET etc.
49
+ def unwrap(usecase)
50
+ nested_path = record.send(usecase) if record
51
+ return DHS::Data.new(dig(*nested_path) || _raw, nil, self.class) if nested_path
52
+ self
53
+ end
54
+
55
+ def _root
56
+ root = self
57
+ root = root._parent while root&._parent
58
+ root
59
+ end
60
+
61
+ def parent
62
+ if _parent&._record
63
+ _parent._record.new(_parent, false)
64
+ else
65
+ _parent
66
+ end
67
+ end
68
+
69
+ def class
70
+ _record || _root._record
71
+ end
72
+
73
+ # enforce internal data structure to have deep symbolized keys
74
+ def _raw=(raw)
75
+ raw.to_hash.deep_symbolize_keys! if raw&.respond_to?(:to_hash)
76
+ @_raw = raw
77
+ end
78
+
79
+ def root_item?
80
+ root_item == self
81
+ end
82
+
83
+ def collection?
84
+ _proxy.is_a? DHS::Collection
85
+ end
86
+
87
+ def item?
88
+ _proxy.is_a? DHS::Item
89
+ end
90
+
91
+ protected
92
+
93
+ def method_missing(name, *args, **keyword_args, &block)
94
+ _proxy.send(name, *args, **keyword_args, &block)
95
+ end
96
+
97
+ def respond_to_missing?(name, include_all = false)
98
+ (root_item? && instance_methods.include?(name)) ||
99
+ _proxy.respond_to?(name, include_all)
100
+ end
101
+
102
+ private
103
+
104
+ def preserve_input_requests!(input)
105
+ if input.is_a?(DHS::Data)
106
+ _request = input._request if _request.nil?
107
+ elsif input.is_a?(Array) && input.first.is_a?(DHS::Data)
108
+ input.each_with_index do |item, index|
109
+ next if item.nil?
110
+ self[index]._request = item._request
111
+ end
112
+ end
113
+ end
114
+
115
+ def collection_proxy?(input)
116
+ (input.is_a?(Hash) && DHS::Collection.access(input: input, record: _record)) ||
117
+ input.is_a?(Array) ||
118
+ _raw.is_a?(Array)
119
+ end
120
+
121
+ def root_item
122
+ return if _proxy.class != DHS::Item
123
+ root = root_item = self
124
+ loop do
125
+ root = root._parent
126
+ root_item = root if root && root._proxy.is_a?(DHS::Item)
127
+ unless root&._parent
128
+ break
129
+ end
130
+ end
131
+ root_item
132
+ end
133
+
134
+ def root?
135
+ _root == self
136
+ end
137
+
138
+ def proxy_from_input(input)
139
+ if input.is_a? DHS::Proxy
140
+ input
141
+ elsif collection_proxy?(raw_from_input(input))
142
+ DHS::Collection.new(self)
143
+ else
144
+ DHS::Item.new(self)
145
+ end
146
+ end
147
+
148
+ def raw_from_input(input)
149
+ if json?(input)
150
+ raw_from_json_string(input)
151
+ elsif defined?(input._raw)
152
+ input._raw
153
+ elsif defined?(input._data)
154
+ input._data._raw
155
+ else
156
+ raw_from_anything_else(input)
157
+ end
158
+ end
159
+
160
+ def json?(input)
161
+ input.is_a?(String) && !input.empty? && !!input.match(/^("|\[|'|\{)/)
162
+ end
163
+
164
+ def raw_from_json_string(input)
165
+ json = JSON.parse(input)
166
+ if json.is_a?(Hash)
167
+ json.deep_symbolize_keys
168
+ elsif json.is_a?(Array)
169
+ json.map { |item| item.is_a?(Hash) ? item.deep_symbolize_keys : item }
170
+ else
171
+ json
172
+ end
173
+ end
174
+
175
+ def raw_from_anything_else(input)
176
+ input = input.to_hash if input.class != Hash && input.respond_to?(:to_hash)
177
+ input.deep_symbolize_keys! if input.is_a?(Hash)
178
+ input
179
+ end
180
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An endpoint is used as source to fetch objects
4
+ class DHS::Endpoint
5
+
6
+ def self.for_url(url)
7
+ template, record = DHS::Record::Endpoints.all.dup.detect do |template, _record|
8
+ DHC::Endpoint.match?(url, template)
9
+ end
10
+ record&.endpoints&.detect { |endpoint| endpoint.url == template }
11
+ end
12
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module DHS
6
+ module Interceptors
7
+ module AutoOauth
8
+ extend ActiveSupport::Concern
9
+
10
+ class Interceptor < DHC::Interceptor
11
+
12
+ def before_request
13
+ request.options[:auth] = { bearer: token }
14
+ end
15
+
16
+ def tokens
17
+ @tokens ||= DHS::Interceptors::AutoOauth::ThreadRegistry.access_token
18
+ end
19
+
20
+ def token
21
+ if tokens.is_a?(Hash)
22
+ tokens.dig(
23
+ request.options[:oauth] ||
24
+ request.options[:record]&.auto_oauth
25
+ )
26
+ else
27
+ tokens
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ 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 DHS
7
+ module Interceptors
8
+ module AutoOauth
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 :access_token
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DHS
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][:dhs] = DHS::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 DHS::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 DHS
6
+ module Interceptors
7
+ module ExtendedRollbar
8
+ extend ActiveSupport::Concern
9
+
10
+ class Interceptor < DHC::Interceptor
11
+ def after_response
12
+ return unless DHS::Interceptors::ExtendedRollbar::ThreadRegistry.log
13
+ DHS::Interceptors::ExtendedRollbar::ThreadRegistry.log.push(request: request, response: response)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ const_set('ExtendedRollbar', DHS::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 DHS
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 DHS
6
+ module Interceptors
7
+ module RequestCycleCache
8
+ extend ActiveSupport::Concern
9
+
10
+ class Interceptor < DHC::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: DHS.config.request_cycle_cache
23
+ }
24
+ }.merge(request.options)
25
+ end
26
+
27
+ private
28
+
29
+ def cache_key_for(request)
30
+ [
31
+ "DHS_REQUEST_CYCLE_CACHE(v#{VERSION})",
32
+ request.method.upcase,
33
+ [request.url, request.params.presence].compact.join('?'),
34
+ "REQUEST=#{DHS::Interceptors::RequestCycleCache::ThreadRegistry.request_id}",
35
+ "HEADERS=#{request.headers.hash}"
36
+ ].join(' ')
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end