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,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'includes warning' do
7
+ before do
8
+ class Customer < DHS::Record
9
+ endpoint 'http://datastore/customers/{id}'
10
+ end
11
+ end
12
+
13
+ let!(:customer_request) do
14
+ stub_request(:get, 'http://datastore/customers/1')
15
+ .to_return(
16
+ body: {
17
+ contracts: { href: 'http://datastore/customers/1/contracts' }
18
+ }.to_json
19
+ )
20
+ end
21
+
22
+ let!(:contracts_request) do
23
+ stub_request(:get, 'http://datastore/customers/1/contracts')
24
+ .to_return(
25
+ body: {
26
+ items: 10.times.map do
27
+ {
28
+ products: { href: 'http://datastore/products' }
29
+ }
30
+ end,
31
+ limit: 10,
32
+ offset: 0,
33
+ total: 33
34
+ }.to_json
35
+ )
36
+ end
37
+
38
+ it 'warns if linked data was simply included but is paginated' do
39
+ expect(lambda {
40
+ Customer.includes_first_page(:contracts).find(1)
41
+ }).to output(
42
+ %r{\[WARNING\] You included `http://datastore/customers/1/contracts`, but this endpoint is paginated. You might want to use `includes_all` instead of `includes` \(https://github.com/DePayFi/dhs#includes_all-for-paginated-endpoints\)\.}
43
+ ).to_stderr
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ before do
7
+ class Location < DHS::Record
8
+ configuration item_key: %i[response location]
9
+ endpoint 'http://uberall/location'
10
+ endpoint 'http://uberall/location/{id}'
11
+ end
12
+ end
13
+
14
+ let(:location_response) do
15
+ {
16
+ response: {
17
+ location: {
18
+ id: 1
19
+ }
20
+ }
21
+ }.to_json
22
+ end
23
+
24
+ let(:stub_request_by_id) do
25
+ stub_request(:get, 'http://uberall/location/1')
26
+ .to_return(body: location_response)
27
+ end
28
+
29
+ let(:stub_request_by_get_parameters) do
30
+ stub_request(:get, 'http://uberall/location?identifier=1&limit=1')
31
+ .to_return(body: location_response)
32
+ end
33
+
34
+ it 'uses configured item_key to unwrap response data for find' do
35
+ stub_request_by_id
36
+ location = Location.find(1)
37
+ expect(location.id).to eq 1
38
+ end
39
+
40
+ it 'uses configured item_key to unwrap response data for find_by' do
41
+ stub_request_by_get_parameters
42
+ location = Location.find_by(identifier: 1)
43
+ expect(location.id).to eq 1
44
+ end
45
+
46
+ describe 'Holding on to request object' do
47
+ let(:account_response) do
48
+ { id: 1 }.to_json
49
+ end
50
+
51
+ let(:stub_location_by_id) do
52
+ stub_request(:get, 'http://uberall/location/1')
53
+ .to_return(headers: { 'X-Custom-Header' => 'rspec' }, body: location_response)
54
+ end
55
+
56
+ let(:stub_account_by_id) do
57
+ stub_request(:get, 'http://yext/account/1')
58
+ .to_return(headers: { 'X-Custom-Header' => 'rspec' }, body: account_response)
59
+ end
60
+
61
+ before do
62
+ class Account < DHS::Record
63
+ endpoint 'http://yext/account'
64
+ endpoint 'http://yext/account/{id}'
65
+ end
66
+
67
+ stub_location_by_id
68
+ stub_account_by_id
69
+ end
70
+
71
+ it 'preserves request object for nested items' do
72
+ location = Location.find(1)
73
+ expect(location._request).to be_present
74
+ end
75
+
76
+ it 'preserves request object for unnested items' do
77
+ account = Account.find(1)
78
+ expect(account._request).to be_present
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ before do
7
+ class Business < DHS::Record
8
+ configuration item_created_key: %i[response business], limit_key: %i[response max], pagination_key: %i[response offset], total_key: %i[response count], pagination_strategy: :offset
9
+ endpoint 'http://uberall/businesses'
10
+ end
11
+ end
12
+
13
+ let(:stub_create_business_request) do
14
+ stub_request(:post, 'http://uberall/businesses')
15
+ .to_return(body: {
16
+ status: 'SUCCESS',
17
+ response: {
18
+ business: {
19
+ identifier: 'ABC123',
20
+ name: 'depay',
21
+ id: 239650
22
+ }
23
+ }
24
+ }.to_json)
25
+ end
26
+
27
+ it 'uses paths from configuration to access nested values' do
28
+ stub_create_business_request
29
+ business = Business.create!(
30
+ identifier: 'ABC123',
31
+ name: 'depay'
32
+ )
33
+ expect(business.identifier).to eq 'ABC123'
34
+ expect(business.name).to eq 'depay'
35
+ expect(business.id).to eq 239650
36
+ end
37
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'last' do
7
+ context 'for not paginated endpoints' do
8
+ before do
9
+ class Sector < DHS::Record
10
+ endpoint 'http://services/sectors'
11
+ end
12
+
13
+ stub_request(:get, 'http://services/sectors?limit=1')
14
+ .to_return(
15
+ body: [{ number: 1 }, { number: 2 }, { number: 3 }].to_json
16
+ )
17
+ end
18
+
19
+ it 'returns the last record from the already complete collection' do
20
+ sector = Sector.last
21
+ expect(sector).to be_kind_of Sector
22
+ expect(sector.number).to eq 3
23
+ end
24
+ end
25
+
26
+ context 'for paginated endpoints' do
27
+ before do
28
+ class Place < DHS::Record
29
+ endpoint 'http://datastore/places'
30
+ end
31
+
32
+ stub_request(:get, 'http://datastore/places?limit=1')
33
+ .to_return(
34
+ body: {
35
+ items: [
36
+ { id: 'first-1', company_name: 'Localsearch AG' }
37
+ ],
38
+ total: 500,
39
+ limit: 1,
40
+ offset: 0
41
+ }.to_json
42
+ )
43
+
44
+ stub_request(:get, 'http://datastore/places?limit=1&offset=499')
45
+ .to_return(
46
+ body: {
47
+ items: [
48
+ { id: 'last-500', company_name: 'Curious GmbH' }
49
+ ],
50
+ total: 500,
51
+ limit: 1,
52
+ offset: 0
53
+ }.to_json
54
+ )
55
+ end
56
+
57
+ it 'returns the last record from the already complete collection' do
58
+ place = Place.last
59
+ expect(place).to be_kind_of Place
60
+ expect(place.id).to eq 'last-500'
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'build' do
7
+ let(:datastore) { 'http://depay.fi/v2' }
8
+
9
+ it 'is possible to load records twice' do
10
+ class Feedback < DHS::Record
11
+ endpoint '{+datastore}/feedbacks'
12
+ end
13
+
14
+ class Feedback < DHS::Record
15
+ endpoint '{+datastore}/feedbacks'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'mapping' do
7
+ let(:datastore) { 'http://depay.fi/v2' }
8
+
9
+ before do
10
+ DHC.config.placeholder('datastore', datastore)
11
+ class LocalEntry < DHS::Record
12
+ endpoint '{+datastore}/local-entries'
13
+ endpoint '{+datastore}/local-entries/{id}'
14
+ end
15
+ end
16
+
17
+ it 'maps some attr accessors to another target (proxy)' do
18
+ class LocalEntry < DHS::Record
19
+ def name
20
+ addresses.first.business.identities.first.name
21
+ end
22
+ end
23
+ stub_request(:get, "#{datastore}/local-entries/1")
24
+ .to_return(status: 200, body: { addresses: [{ business: { identities: [{ name: 'Löwenzorn' }] } }] }.to_json)
25
+ entry = LocalEntry.find(1)
26
+ expect(entry.name).to eq 'Löwenzorn'
27
+ end
28
+
29
+ it 'maps for root_item even if that item is nested in a root collection' do
30
+ class LocalEntry < DHS::Record
31
+ def name
32
+ addresses.first.business.identities.first.name
33
+ end
34
+ end
35
+ stub_request(:get, "#{datastore}/local-entries/1?limit=1")
36
+ .to_return(status: 200, body: { items: [{ addresses: [{ business: { identities: [{ name: 'Löwenzorn' }] } }] }] }.to_json)
37
+ entry = LocalEntry.find_by(id: 1)
38
+ expect(entry.name).to eq 'Löwenzorn'
39
+ end
40
+
41
+ it 'return data proxy in case of item or collection' do
42
+ class LocalEntry < DHS::Record
43
+ def business
44
+ addresses.first.business
45
+ end
46
+ end
47
+ stub_request(:get, "#{datastore}/local-entries/1")
48
+ .to_return(status: 200, body: { addresses: [{ business: { identities: [{ name: 'Löwenzorn' }] } }] }.to_json)
49
+ entry = LocalEntry.find(1)
50
+ expect(entry.business).to be_kind_of DHS::Data
51
+ end
52
+
53
+ it 'clones mappings when using include' do
54
+ class Agb < DHS::Record
55
+ endpoint '{+datastore}/agbs/active?agb_type=CC_TOU'
56
+ def pdf_url
57
+ self['binary_url_pdf_de']
58
+ end
59
+ end
60
+
61
+ preceding_agb_url = "#{datastore}/agbs/547f0b461c266c4830ea6cea"
62
+ # initial request
63
+ stub_request(:get, "#{datastore}/agbs/active?agb_type=CC_TOU&limit=1")
64
+ .to_return(
65
+ status: 200,
66
+ body: {
67
+ 'href' => "#{datastore}/agbs/547f02c61c266c4830ea6ce7",
68
+ 'preceding_agb' => { 'href' => preceding_agb_url },
69
+ 'binary_url_pdf_de' => 'de'
70
+ }.to_json
71
+ )
72
+
73
+ # includes request
74
+ stub_request(:get, preceding_agb_url).to_return(
75
+ status: 200, body: { 'href' => preceding_agb_url }.to_json, headers: {}
76
+ )
77
+
78
+ agb = Agb.includes_first_page(:preceding_agb).first!
79
+ expect(agb.pdf_url).to be == 'de'
80
+ end
81
+
82
+ it 'makes mappings available even for nested data' do
83
+ class LocalEntry < DHS::Record
84
+ def name
85
+ company_name
86
+ end
87
+ end
88
+
89
+ class Favorite < DHS::Record
90
+ endpoint '{+datastore}/favorites'
91
+ endpoint '{+datastore}/favorites/{id}'
92
+ end
93
+ stub_request(:get, "#{datastore}/local-entries/1")
94
+ .to_return(body: { company_name: 'depay.fi' }.to_json)
95
+ stub_request(:get, "#{datastore}/favorites/1")
96
+ .to_return(body: { local_entry: { href: "#{datastore}/local-entries/1" } }.to_json)
97
+
98
+ favorite = Favorite.includes_first_page(:local_entry).find(1)
99
+ expect(favorite.local_entry).to be_kind_of LocalEntry
100
+ expect(favorite.local_entry.name).to eq 'depay.fi'
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'model_name' do
7
+ before do
8
+ class LocalEntry < DHS::Record
9
+ endpoint '{+datastore}/local-entries'
10
+ end
11
+ end
12
+
13
+ it 'provides a model name' do
14
+ expect(LocalEntry.model_name.name).to eq 'LocalEntry'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'new' do
7
+ let(:datastore) { 'http://depay.fi/v2' }
8
+
9
+ before do
10
+ DHC.config.placeholder('datastore', datastore)
11
+ class Rating < DHS::Record
12
+ endpoint '{+datastore}/content-ads/{campaign_id}/feedbacks'
13
+ endpoint '{+datastore}/feedbacks'
14
+ end
15
+ end
16
+
17
+ it 'builds a new item from scratch (like build)' do
18
+ feedback = Rating.new recommended: true
19
+ expect(feedback).to be_kind_of Rating
20
+ expect(feedback.recommended).to eq true
21
+ stub_request(:post, 'http://depay.fi/v2/feedbacks')
22
+ .with(body: '{"recommended":true}')
23
+ feedback.save
24
+ end
25
+
26
+ it 'builds new items also with keys containing dashes' do
27
+ feedback = Rating.new('some-key' => [])
28
+ expect(feedback._raw[:'some-key']).to eq([])
29
+ end
30
+
31
+ context 'initialise records with raw data' do
32
+ before do
33
+ class User < DHS::Record
34
+ endpoint '{+datastore}/users'
35
+ end
36
+ end
37
+
38
+ it 'allows accessing nested data' do
39
+ user = User.new({
40
+ claims: {
41
+ items: [
42
+ { method: 'CustomerCenter' }
43
+ ]
44
+ }
45
+ }.to_json)
46
+ expect(user.claims.first['method']).to eq 'CustomerCenter'
47
+ end
48
+ end
49
+
50
+ context 'custom setters' do
51
+ before do
52
+ class Rating
53
+ def ratings=(ratings)
54
+ _raw[:ratings] = ratings.map { |k, v| { name: k, value: v } }
55
+ end
56
+ end
57
+ end
58
+
59
+ it 'are used by initializer' do
60
+ feedback = Rating.new(ratings: { a: 1, b: 2 })
61
+ expect(feedback.ratings._raw).to eq([{ name: :a, value: 1 }, { name: :b, value: 2 }])
62
+ end
63
+
64
+ it 'can be used directly to change raw data' do
65
+ feedback = Rating.new(ratings: { a: 1 })
66
+ feedback.ratings = { z: 3 }
67
+ expect(feedback.ratings.first.name).to eq :z
68
+ end
69
+
70
+ context 'that do not affect raw data' do
71
+ before do
72
+ class Rating
73
+ attr_accessor :listing
74
+ end
75
+ end
76
+
77
+ let(:listing) { double('listing') }
78
+
79
+ it 'are used by initializer' do
80
+ feedback = Rating.new(listing: listing)
81
+ expect(feedback.listing).to eq(listing)
82
+ end
83
+
84
+ it 'do not set raw data' do
85
+ feedback = Rating.new(listing: listing)
86
+ expect(feedback._raw[:listing]).to be_nil
87
+ end
88
+ end
89
+
90
+ context 'and custom getters' do
91
+ before do
92
+ class Rating
93
+ def ratings
94
+ Hash[_raw[:ratings].map { |r| [r[:name], r[:value]] }]
95
+ end
96
+ end
97
+ end
98
+
99
+ it 'uses custom getters to show data for exploration' do
100
+ feedback = Rating.new(ratings: { a: 1, b: 2 })
101
+ expect(feedback.ratings).to eq(a: 1, b: 2)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end