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,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS, type: :request do
6
+ context 'autoloading' do
7
+ let(:endpoints) { DHS::Record::Endpoints.all }
8
+
9
+ it "pre/re-loads all DHS classes initialy, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
10
+ expect(endpoints['http://datastore/v2/users']).to be_present
11
+ expect(endpoints['http://datastore/v2/users/{id}']).to be_present
12
+
13
+ expect(
14
+ DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users' }
15
+ ).to be_present
16
+ expect(
17
+ DummyUser.endpoints.detect { |endpoint| endpoint.url == 'http://datastore/v2/users/{id}' }
18
+ ).to be_present
19
+ end
20
+
21
+ it "also pre/re-loads all DHS classes that inherited from an DHS provider, because it's necessary for endpoint-to-record-class-discovery", reset_before: false do
22
+ expect(endpoints['http://customers']).to be_present
23
+ expect(endpoints['http://customers/{id}']).to be_present
24
+
25
+ expect(
26
+ DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers' }
27
+ ).to be_present
28
+ expect(
29
+ DummyCustomer.endpoints.detect { |endpoint| endpoint.url == 'http://customers/{id}' }
30
+ ).to be_present
31
+
32
+ customer_request = stub_request(:get, 'http://customers/1')
33
+ .with(
34
+ headers: {
35
+ 'Authorization' => 'token123'
36
+ }
37
+ )
38
+ .to_return(body: { name: 'Steve' }.to_json)
39
+
40
+ DummyCustomer.find(1)
41
+
42
+ expect(customer_request).to have_been_requested
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'accessors' do
11
+ let(:response_data) do
12
+ {
13
+ items: items,
14
+ extra: extra,
15
+ total: 1
16
+ }
17
+ end
18
+
19
+ before do
20
+ class Record < DHS::Record
21
+ endpoint 'http://datastore/records`'
22
+ end
23
+ stub_request(:get, %r{http://datastore/records})
24
+ .to_return(body: response_data.to_json)
25
+ end
26
+
27
+ it 'allows access to extra data passed with collection' do
28
+ expect(collection.extra).to eq(extra)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:datastore) { 'http://depay.fi/v2' }
7
+ let(:items) { [{ name: 'Steve' }] }
8
+ let(:collection) { Account.where }
9
+
10
+ before do
11
+ DHC.config.placeholder('datastore', datastore)
12
+ class Account < DHS::Record
13
+ endpoint '{+datastore}/accounts'
14
+ end
15
+ stub_request(:get, 'http://depay.fi/v2/accounts')
16
+ .to_return(body: response_data.to_json)
17
+ end
18
+
19
+ context 'plain array' do
20
+ let(:response_data) do
21
+ items
22
+ end
23
+
24
+ it 'initalises a collection' do
25
+ expect(collection.first.name).to eq 'Steve'
26
+ end
27
+
28
+ it 'casts items to be instance of defined DHS::Record' do
29
+ expect(collection.first).to be_kind_of Account
30
+ end
31
+ end
32
+
33
+ context 'items key' do
34
+ let(:response_data) do
35
+ {
36
+ items: items
37
+ }
38
+ end
39
+
40
+ it 'initalises a collection when reponse contains a key items containing an array of items' do
41
+ expect(collection.first.name).to eq 'Steve'
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:search) { 'http://depay.fi/search' }
7
+ let(:limit) { 10 }
8
+ let(:total) { 20 }
9
+
10
+ before do
11
+ DHC.config.placeholder('search', search)
12
+ class Search < DHS::Record
13
+ configuration items_key: :docs, limit_key: :size, pagination_key: :start, pagination_strategy: :start, total_key: :totalResults
14
+ endpoint '{+search}/{type}'
15
+ end
16
+ stub_request(:get, 'http://depay.fi/search/phonebook?size=10').to_return(
17
+ body: {
18
+ docs: (1..10).to_a,
19
+ start: 1,
20
+ size: limit,
21
+ totalResults: total
22
+ }.to_json
23
+ )
24
+ stub_request(:get, 'http://depay.fi/search/phonebook?size=10&start=11').to_return(
25
+ body: {
26
+ docs: (11..20).to_a,
27
+ start: 11,
28
+ size: limit,
29
+ totalResults: total
30
+ }.to_json
31
+ )
32
+ end
33
+
34
+ context 'lets you configure how to deal with collections' do
35
+ it 'initalises and gives access to collections according to configuration' do
36
+ results = Search.all(type: :phonebook, size: 10)
37
+ expect(results.count).to eq total
38
+ expect(results.total).to eq total
39
+ expect(results.limit).to eq limit
40
+ expect(results.offset).to eq 11
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:data) do
7
+ %w[ROLE_USER ROLE_LOCALCH_ACCOUNT]
8
+ end
9
+
10
+ let(:collection) do
11
+ DHS::Collection.new(DHS::Data.new(data))
12
+ end
13
+
14
+ context 'delegates methods to raw' do
15
+ %w(length size last sample present? blank? empty? compact).each do |method|
16
+ it "delegates #{method} to raw" do
17
+ expect(collection.send(method.to_sym)).not_to be_nil
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:data) do
7
+ [1, 2, 3]
8
+ end
9
+
10
+ let(:collection) do
11
+ DHS::Collection.new(DHS::Data.new(data))
12
+ end
13
+
14
+ context 'enumerable' do
15
+ it 'works with map' do
16
+ expect(
17
+ collection.map { |x| x + 1 }
18
+ ).to eq [2, 3, 4]
19
+ end
20
+
21
+ it 'works with select' do
22
+ expect(
23
+ collection.select { |x| x == 2 }
24
+ ).to eq [2]
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:collection) do
7
+ DHS::Collection.new(DHS::Data.new([]))
8
+ end
9
+
10
+ context 'array misses href' do
11
+ it 'works with empty array' do
12
+ expect(
13
+ collection.href
14
+ ).to eq nil
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:total) { 0 }
7
+
8
+ let(:limit) { 50 }
9
+
10
+ let(:offset) { 0 }
11
+
12
+ let(:collection) do
13
+ {
14
+ href: "#{datastore}/feedbacks",
15
+ items: [],
16
+ total: total,
17
+ limit: limit,
18
+ offset: offset
19
+ }
20
+ end
21
+
22
+ let(:item) do
23
+ {
24
+ href: "#{datastore}/users/1",
25
+ feedbacks: collection
26
+ }
27
+ end
28
+
29
+ let(:datastore) { 'http://depay.fi/v2' }
30
+
31
+ before do
32
+ DHC.config.placeholder('datastore', datastore)
33
+ class Feedback < DHS::Record
34
+ endpoint '{+datastore}/feedbacks'
35
+ endpoint '{+datastore}/feedbacks/{id}'
36
+ end
37
+
38
+ class User < DHS::Record
39
+ endpoint '{+datastore}/users'
40
+ endpoint '{+datastore}/users/{id}'
41
+ end
42
+ end
43
+
44
+ it 'provides meta data for collections' do
45
+ stub_request(:get, "#{datastore}/feedbacks").to_return(status: 200, body: collection.to_json)
46
+ feedbacks = Feedback.where
47
+ expect(feedbacks.total).to eq total
48
+ expect(feedbacks.limit).to eq limit
49
+ expect(feedbacks.offset).to eq offset
50
+ expect(feedbacks.href).to eq "#{datastore}/feedbacks"
51
+ end
52
+
53
+ it 'provides meta data also when navigating' do
54
+ stub_request(:get, "#{datastore}/users/1").to_return(status: 200, body: item.to_json)
55
+ user = User.find(1)
56
+ expect(user.feedbacks.href).to eq "#{datastore}/feedbacks"
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:data) do
7
+ %w[ROLE_USER ROLE_LOCALCH_ACCOUNT]
8
+ end
9
+
10
+ let(:collection) do
11
+ DHS::Data.new(DHS::Data.new(data))
12
+ end
13
+
14
+ context '#respond_to?' do
15
+ # In this case raw collection is an Array implementing first
16
+ it 'forwards calls to raw collection' do
17
+ expect(collection.respond_to?(:first)).to be(true)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'to_a' do
11
+ let(:response_data) do
12
+ {
13
+ items: items,
14
+ extra: extra,
15
+ total: 1
16
+ }
17
+ end
18
+
19
+ let(:subject) { collection.to_a }
20
+
21
+ before do
22
+ class Record < DHS::Record
23
+ endpoint 'http://datastore/records`'
24
+ end
25
+ stub_request(:get, %r{http://datastore/records})
26
+ .to_return(body: response_data.to_json)
27
+ end
28
+
29
+ it 'returns an array and not DHS::Data' do
30
+ expect(subject).to be_kind_of Array
31
+ expect(subject).not_to be_kind_of DHS::Data
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:items) { [{ name: 'Steve' }] }
7
+ let(:extra) { 'extra' }
8
+ let(:collection) { Record.where }
9
+
10
+ context 'to_ary' do
11
+ before do
12
+ class Record < DHS::Record
13
+ endpoint 'http://datastore/records`'
14
+ end
15
+ stub_request(:get, %r{http://datastore/records})
16
+ .to_return(body: response_data.to_json)
17
+ end
18
+
19
+ let(:response_data) do
20
+ {
21
+ items: items,
22
+ extra: extra,
23
+ total: 1
24
+ }
25
+ end
26
+
27
+ let(:subject) { collection.to_ary }
28
+
29
+ it 'returns an array' do
30
+ expect(subject).to be_present
31
+ expect(subject).to be_kind_of Array
32
+ expect(subject[0]).to be_kind_of Record
33
+ expect(subject[0].name).to eq 'Steve'
34
+ end
35
+
36
+ it 'responds to to_ary' do
37
+ expect(subject.respond_to?(:to_ary)).to eq true
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Collection do
6
+ let(:datastore) { 'http://depay.fi/v2' }
7
+
8
+ before do
9
+ DHC.config.placeholder('datastore', datastore)
10
+ class Account < DHS::Record
11
+ endpoint '{+datastore}/accounts/{id}'
12
+ end
13
+ end
14
+
15
+ let(:data) {
16
+ {
17
+ 'authorities' => %w[ROLE_USER ROLE_LOCALCH_ACCOUNT]
18
+ }
19
+ }
20
+
21
+ it 'lets you access items of an array if they are not objects' do
22
+ stub_request(:get, "#{datastore}/accounts/1").to_return(status: 200, body: data.to_json)
23
+ feedback = Account.find(1)
24
+ expect(feedback.authorities.first).to eq 'ROLE_USER'
25
+ expect(feedback.authorities[1]).to eq 'ROLE_LOCALCH_ACCOUNT'
26
+ end
27
+ end
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Complex do
6
+ it 'returns nil when result is empty' do
7
+ expect(DHS::Complex.reduce([])).to be_nil
8
+ end
9
+
10
+ it 'forwards primitive types' do
11
+ expect(DHS::Complex.reduce(entry_id: 123)).to eq(entry_id: 123)
12
+ end
13
+
14
+ it 'fails when trying to merge primitive types' do
15
+ expect {
16
+ DHS::Complex.reduce([{ entry: true }, { entry: :content }])
17
+ }.to raise_error(ArgumentError)
18
+ end
19
+
20
+ it 'does not fail trying to merge primitive types when they are the same' do
21
+ expect {
22
+ DHS::Complex.reduce([{ entry: true }, { entry: true }])
23
+ }.not_to raise_error
24
+ end
25
+
26
+ context 'first level' do
27
+ context 'reduces symbols into/with X' do
28
+ it 'reduces symbols into hash' do
29
+ expect(DHS::Complex.reduce([
30
+ { entries: :contract },
31
+ :entries
32
+ ])).to eq(entries: :contract)
33
+ end
34
+
35
+ it 'reduces symbols into array' do
36
+ expect(DHS::Complex.reduce([
37
+ [:contracts],
38
+ :entries
39
+ ])).to eq(%i[contracts entries])
40
+ expect(DHS::Complex.reduce([
41
+ [:entries],
42
+ :entries
43
+ ])).to eq(:entries)
44
+ end
45
+
46
+ it 'reduces symbols with symbols' do
47
+ expect(DHS::Complex.reduce(%i[
48
+ contracts
49
+ entries
50
+ ])).to eq(%i[contracts entries])
51
+ expect(DHS::Complex.reduce(%i[
52
+ entries
53
+ entries
54
+ ])).to eq(:entries)
55
+ end
56
+ end
57
+
58
+ context 'reduces arrays into/with X' do
59
+ it 'reduces arrays into an hash' do
60
+ expect(DHS::Complex.reduce([
61
+ { entries: :contract },
62
+ [:entries]
63
+ ])).to eq(entries: :contract)
64
+ expect(DHS::Complex.reduce([
65
+ { entries: :contract },
66
+ [:products]
67
+ ])).to eq([{ entries: :contract }, :products])
68
+ end
69
+
70
+ it 'reduces arrays into an arrays' do
71
+ expect(DHS::Complex.reduce([
72
+ [:entries],
73
+ [:entries]
74
+ ])).to eq(:entries)
75
+ expect(DHS::Complex.reduce([
76
+ [:entries],
77
+ [:products]
78
+ ])).to eq(%i[entries products])
79
+ end
80
+
81
+ it 'reduces arrays into an symbols' do
82
+ expect(DHS::Complex.reduce([
83
+ :entries,
84
+ [:entries]
85
+ ])).to eq(:entries)
86
+ expect(DHS::Complex.reduce([
87
+ :entries,
88
+ [:products]
89
+ ])).to eq(%i[entries products])
90
+ end
91
+ end
92
+
93
+ context 'reduces hashes into/with X' do
94
+ it 'reduces hash into an hash' do
95
+ expect(DHS::Complex.reduce([
96
+ { entries: :contract },
97
+ { entries: :products }
98
+ ])).to eq(entries: %i[contract products])
99
+ expect(DHS::Complex.reduce([
100
+ { entries: :contract },
101
+ { entries: :contract }
102
+ ])).to eq(entries: :contract)
103
+ end
104
+
105
+ it 'reduces hash into an array' do
106
+ expect(DHS::Complex.reduce([
107
+ [:entries],
108
+ { entries: :products }
109
+ ])).to eq(entries: :products)
110
+ expect(DHS::Complex.reduce([
111
+ [{ entries: :contract }],
112
+ { entries: :contract }
113
+ ])).to eq(entries: :contract)
114
+ end
115
+
116
+ it 'reduces hash into a symbol' do
117
+ expect(DHS::Complex.reduce([
118
+ :entries,
119
+ { entries: :products }
120
+ ])).to eq(entries: :products)
121
+ expect(DHS::Complex.reduce([
122
+ :products,
123
+ { entries: :contract }
124
+ ])).to eq([:products, { entries: :contract }])
125
+ end
126
+ end
127
+
128
+ context 'reduces array into/with X' do
129
+ it 'reduces array into hash' do
130
+ expect(DHS::Complex.reduce([
131
+ { entries: :contract },
132
+ %i[entries products]
133
+ ])).to eq([{ entries: :contract }, :products])
134
+ end
135
+
136
+ it 'reduces array into array' do
137
+ expect(DHS::Complex.reduce([
138
+ [:contracts],
139
+ %i[entries products contracts]
140
+ ])).to eq(%i[contracts entries products])
141
+ end
142
+
143
+ it 'reduces array with symbols' do
144
+ expect(DHS::Complex.reduce([
145
+ :contracts,
146
+ %i[entries products]
147
+ ])).to eq(%i[contracts entries products])
148
+ end
149
+ end
150
+ end
151
+
152
+ context 'multi-level' do
153
+ it 'reduces a complex multi-level example' do
154
+ expect(DHS::Complex.reduce([
155
+ :contracts,
156
+ [:entries, products: { content_ads: :address }],
157
+ products: { content_ads: { place: :location } }
158
+ ])).to eq([
159
+ :contracts,
160
+ :entries,
161
+ products: { content_ads: [:address, { place: :location }] }
162
+ ])
163
+ end
164
+
165
+ it 'reduces another complex multi-level example' do
166
+ expect(DHS::Complex.reduce([
167
+ [entries: :content_ads, products: :price],
168
+ [:entries, products: { content_ads: :address }],
169
+ [entries: { content_ads: :owner }, products: [{ price: :region }, :image, { content_ads: :owner }]]
170
+ ])).to eq(
171
+ entries: { content_ads: :owner },
172
+ products: [{ content_ads: %i[address owner], price: :region }, :image]
173
+ )
174
+ end
175
+
176
+ it 'reduces another complex multi-level example (single plus array)' do
177
+ expect(DHS::Complex.reduce([
178
+ { entries: :products },
179
+ { entries: %i[customer contracts] }
180
+ ])).to eq(
181
+ entries: %i[products customer contracts]
182
+ )
183
+ end
184
+
185
+ it 'reduces another complex multi-level example (single hash plus array)' do
186
+ expect(DHS::Complex.reduce([
187
+ { entries: { customer: :contracts } },
188
+ { entries: %i[customer content_ads] }
189
+ ])).to eq(
190
+ entries: [{ customer: :contracts }, :content_ads]
191
+ )
192
+ end
193
+
194
+ it 'reduces properly' do
195
+ expect(DHS::Complex.reduce([
196
+ %i[entries place content_ads], [{ place: :content_ads }], { content_ads: :place }
197
+ ])).to eq(
198
+ [:entries, { place: :content_ads, content_ads: :place }]
199
+ )
200
+ end
201
+ end
202
+ end