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