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,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'pagination chain' do
7
+ context 'default pagination (offset)' do
8
+ before do
9
+ class Record < DHS::Record
10
+ endpoint 'http://depay.fi/records'
11
+ endpoint 'http://depay.fi/records/{id}'
12
+ end
13
+ end
14
+
15
+ it 'allows to chain pagination methods' do
16
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&offset=200&limit=100').to_return(body: [].to_json)
17
+ Record.where(color: 'blue').page(3).first
18
+ expect(request).to have_been_made.times(1)
19
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&offset=20&limit=10').to_return(body: [].to_json)
20
+ Record.where(color: 'blue').page(3).per(10).first
21
+ Record.where(color: 'blue').per(10).page(3).first
22
+ Record.where(color: 'blue').per(20).page(5).per(10).page(3).first
23
+ expect(request).to have_been_made.times(3)
24
+ end
25
+
26
+ it 'allows to start chains with pagination methods' do
27
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&offset=200&limit=100').to_return(body: [].to_json)
28
+ Record.page(3).where(color: 'blue').first
29
+ expect(request).to have_been_made.times(1)
30
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&offset=20&limit=10').to_return(body: [].to_json)
31
+ Record.page(3).per(10).where(color: 'blue').first
32
+ Record.per(10).page(3).where(color: 'blue').first
33
+ Record.per(20).page(5).where(color: 'blue').per(10).page(3).first
34
+ expect(request).to have_been_made.times(3)
35
+ end
36
+
37
+ it 'defaults page to 1' do
38
+ request = stub_request(:get, 'http://depay.fi/records?limit=10&offset=0').to_return(body: [].to_json)
39
+ Record.per(10).first
40
+ Record.per(10).page('').first
41
+ expect(request).to have_been_made.times(2)
42
+ end
43
+
44
+ it 'provides limit as alias for per' do
45
+ request = stub_request(:get, 'http://depay.fi/records?limit=10&offset=0').to_return(body: [].to_json)
46
+ Record.limit(10).first
47
+ Record.page('').limit(10).first
48
+ expect(request).to have_been_made.times(2)
49
+ end
50
+
51
+ it 'also works with strings' do
52
+ request = stub_request(:get, 'http://depay.fi/records?limit=10&offset=0').to_return(body: [].to_json)
53
+ Record.limit('10').first
54
+ Record.page('1').limit('10').first
55
+ expect(request).to have_been_made.times(2)
56
+ end
57
+ end
58
+
59
+ context 'start pagination' do
60
+ before do
61
+ class Record < DHS::Record
62
+ configuration pagination_strategy: 'start', pagination_key: 'start'
63
+ endpoint 'http://depay.fi/records'
64
+ endpoint 'http://depay.fi/records/{id}'
65
+ end
66
+ end
67
+
68
+ it 'allows to chain pagination methods' do
69
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&start=201&limit=100').to_return(body: [].to_json)
70
+ Record.where(color: 'blue').page(3).first
71
+ expect(request).to have_been_made.times(1)
72
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&start=21&limit=10').to_return(body: [].to_json)
73
+ Record.where(color: 'blue').page(3).per(10).first
74
+ Record.where(color: 'blue').per(10).page(3).first
75
+ Record.where(color: 'blue').per(20).page(5).per(10).page(3).first
76
+ expect(request).to have_been_made.times(3)
77
+ end
78
+ end
79
+
80
+ context 'page pagination' do
81
+ before do
82
+ class Record < DHS::Record
83
+ configuration pagination_strategy: 'page', pagination_key: 'page'
84
+ endpoint 'http://depay.fi/records'
85
+ endpoint 'http://depay.fi/records/{id}'
86
+ end
87
+ end
88
+
89
+ it 'allows to chain pagination methods' do
90
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&page=3&limit=100').to_return(body: [].to_json)
91
+ Record.where(color: 'blue').page(3).first
92
+ expect(request).to have_been_made.times(1)
93
+ request = stub_request(:get, 'http://depay.fi/records?color=blue&page=3&limit=10').to_return(body: [].to_json)
94
+ Record.where(color: 'blue').page(3).per(10).first
95
+ Record.where(color: 'blue').per(10).page(3).first
96
+ Record.where(color: 'blue').per(20).page(5).per(10).page(3).first
97
+ expect(request).to have_been_made.times(3)
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'pagination links' do
7
+ before do
8
+ class Customer < DHS::Record
9
+ endpoint 'http://datastore/customer'
10
+ end
11
+ end
12
+
13
+ let!(:request) do
14
+ stub_request(:get, "http://datastore/customer#{query}")
15
+ .to_return(body: body)
16
+ end
17
+
18
+ let(:query) { "?name=#{name}&page=#{page}" }
19
+
20
+ let(:customers) do
21
+ Customer.where(name: name, page: page)
22
+ end
23
+
24
+ context 'next and previous link is present' do
25
+ let(:name) { 'Simpl' }
26
+ let(:page) { 2 }
27
+ let(:body) do
28
+ {
29
+ next: "http://datastore/customer?name=#{name}&page=3",
30
+ previous: "http://datastore/customer?name=#{name}&page=1",
31
+ items: [{ name: 'Simplificator' }]
32
+ }.to_json
33
+ end
34
+
35
+ it 'tells me that there is a next link' do
36
+ expect(customers.next?).to eq true
37
+ expect(customers.previous?).to eq true
38
+ end
39
+ end
40
+
41
+ context 'next link is present, previous is not' do
42
+ let(:name) { 'Simpl' }
43
+ let(:page) { 2 }
44
+ let(:body) do
45
+ {
46
+ next: "http://datastore/customer?name=#{name}&page=3",
47
+ items: [{ name: 'Simplificator' }]
48
+ }.to_json
49
+ end
50
+
51
+ it 'tells me that there is a next link' do
52
+ expect(customers.next?).to eq true
53
+ expect(customers.previous?).to eq false
54
+ end
55
+ end
56
+
57
+ context 'no next link and no previous link is present' do
58
+ let(:name) { 'Simplificator' }
59
+ let(:page) { 1 }
60
+ let(:body) do
61
+ {
62
+ items: [{ name: 'Simplificator' }]
63
+ }.to_json
64
+ end
65
+
66
+ it 'tells me that there is no next link' do
67
+ expect(customers.next?).to eq false
68
+ expect(customers.previous?).to eq false
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'pagination' do
7
+ let(:datastore) { 'http://depay.fi/v2' }
8
+ let(:record) { Feedback.where(entry_id: 1) }
9
+ let(:total) { 200 }
10
+ let(:total_pages) { total / limit }
11
+ let(:current_page) { offset + 1 }
12
+ let(:prev_page) { current_page - 1 }
13
+ let(:next_page) { current_page + 1 }
14
+ let(:offset) { 0 }
15
+ let(:limit) { 10 }
16
+ let(:body_json) do
17
+ {
18
+ items: [],
19
+ total: total,
20
+ offset: offset,
21
+ limit: limit
22
+ }.to_json
23
+ end
24
+
25
+ before do
26
+ DHC.config.placeholder('datastore', datastore)
27
+ class Feedback < DHS::Record
28
+ endpoint '{+datastore}/feedbacks'
29
+ end
30
+ stub_request(:get, 'http://depay.fi/v2/feedbacks?entry_id=1')
31
+ .to_return(body: body_json)
32
+ end
33
+
34
+ it 'responds to limit_value' do
35
+ expect(record.limit_value).to eq(limit)
36
+ end
37
+
38
+ it 'responds to total_pages' do
39
+ expect(record.total_pages).to eq(total_pages)
40
+ end
41
+
42
+ it 'responds to current_page' do
43
+ expect(record.current_page).to eq(current_page)
44
+ end
45
+
46
+ it 'responds to first_page' do
47
+ expect(record.first_page).to eq(1)
48
+ end
49
+
50
+ it 'responds to last_page' do
51
+ expect(record.last_page).to eq(total_pages)
52
+ end
53
+
54
+ it 'responds to prev_page' do
55
+ expect(record.prev_page).to eq(prev_page)
56
+ end
57
+
58
+ it 'responds to next_page' do
59
+ expect(record.next_page).to eq(next_page)
60
+ end
61
+
62
+ context 'when amount of total pages is not diviable by the limit' do
63
+ let(:total) { 2738 }
64
+ let(:limit) { 100 }
65
+
66
+ it 'rounds up' do
67
+ expect(record.total_pages).to eq(28)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context '#persisted?' do
7
+ let(:datastore) { 'http://depay.fi/v2' }
8
+
9
+ before do
10
+ DHC.config.placeholder('datastore', datastore)
11
+ class Feedback < DHS::Record
12
+ endpoint '{+datastore}/content-ads/{campaign_id}/feedbacks'
13
+ end
14
+ end
15
+
16
+ context 'for new record' do
17
+ context 'with a nil href' do
18
+ subject { Feedback.new }
19
+
20
+ it 'is false' do
21
+ expect(subject.persisted?).to be(false)
22
+ end
23
+ end
24
+
25
+ context 'with an empty href' do
26
+ subject { Feedback.new(href: '') }
27
+
28
+ it 'is false' do
29
+ expect(subject.persisted?).to be(false)
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'for saved record' do
35
+ let(:campaign_id) { 'aaa' }
36
+ let(:parameters) { { recommended: true } }
37
+
38
+ subject { Feedback.new(parameters.merge(campaign_id: campaign_id)) }
39
+
40
+ before do
41
+ stub_request(:post, "#{datastore}/content-ads/#{campaign_id}/feedbacks")
42
+ .with(body: parameters.to_json)
43
+ .to_return(status: 200, body: parameters.merge(href: "#{datastore}/content-ads/#{campaign_id}/feedbacks/123456789").to_json)
44
+ end
45
+
46
+ it 'is true' do
47
+ subject.save
48
+ expect(subject.persisted?).to be(true)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'provider' do
7
+ before do
8
+ module Provider
9
+ class BaseRecord < DHS::Record
10
+ provider params: { api_key: 123 }
11
+ end
12
+
13
+ class Record < Provider::BaseRecord
14
+ endpoint 'http://provider/records'
15
+ end
16
+ end
17
+
18
+ class AnotherRecord < DHS::Record
19
+ endpoint 'http://other_provider/records'
20
+ end
21
+
22
+ stub_request(:get, 'http://provider/records?id=1&api_key=123')
23
+ .to_return(body: { name: 'Steve' }.to_json)
24
+
25
+ stub_request(:get, 'http://other_provider/records?id=1')
26
+ .to_return(body: { name: 'Not Steve' }.to_json)
27
+ end
28
+
29
+ it 'applies provider options when making requests to that provider' do
30
+ record = Provider::Record.find(1)
31
+ expect(record.name).to eq 'Steve'
32
+ end
33
+
34
+ it 'does not apply provider options when making requests to other records' do
35
+ Provider::Record.find(1)
36
+ record = AnotherRecord.find(1)
37
+ expect(record.name).to eq 'Not Steve'
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'references' do
7
+ before do
8
+ class Customer < DHS::Record
9
+ endpoint 'http://datastore/customers/{id}'
10
+ end
11
+
12
+ class User < DHS::Record
13
+ endpoint 'http://datastore/users/{id}'
14
+ endpoint 'http://datastore/customers/{customer_id}/users/{id}'
15
+ def reversed_name
16
+ name.split.reverse.join(' ')
17
+ end
18
+ end
19
+ end
20
+
21
+ let!(:customer_request) do
22
+ stub_request(:get, 'http://datastore/customers/1')
23
+ .to_return(body: {
24
+ 'electronic_addresses' => {
25
+ 'href' => 'http://datastore/electronic_addresses'
26
+ },
27
+ 'contact_addresses' => {
28
+ 'href' => 'http://datastore/contact_addresses'
29
+ },
30
+ 'users' => {
31
+ 'href' => 'http://datastore/customers/1/users'
32
+ }
33
+ }.to_json)
34
+ end
35
+
36
+ let!(:electronic_addresses_request) do
37
+ stub_request(:get, 'http://datastore/electronic_addresses')
38
+ .with(referencing_options)
39
+ .to_return(body: [].to_json)
40
+ end
41
+
42
+ let!(:contact_addresses_request) do
43
+ stub_request(:get, 'http://datastore/contact_addresses')
44
+ .with(referencing_options)
45
+ .to_return(body: [].to_json)
46
+ end
47
+
48
+ let(:referencing_options) do
49
+ { headers: { 'Authentication' => 'Bearer 123' } }
50
+ end
51
+
52
+ it 'uses the "references" hash for all symbols of the "including" array' do
53
+ Customer
54
+ .includes_first_page(:electronic_addresses, :contact_addresses)
55
+ .references(
56
+ electronic_addresses: referencing_options,
57
+ contact_addresses: referencing_options
58
+ )
59
+ .find(1)
60
+ assert_requested(electronic_addresses_request)
61
+ assert_requested(contact_addresses_request)
62
+ end
63
+
64
+ describe 'mapping related classes correctly' do
65
+ before do
66
+ stub_request(:get, 'http://datastore/customers/1/users?limit=100').to_return(
67
+ status: 200,
68
+ body: {
69
+ href: 'http://datastore/customers/1/users?offset=0&limit=100',
70
+ items: [
71
+ { href: 'http://datastore/customers/1/users/1' }
72
+ ],
73
+ total: 1,
74
+ offset: 0,
75
+ limit: 10
76
+ }.to_json
77
+ )
78
+
79
+ stub_request(:get, 'http://datastore/customers/1/users/1')
80
+ .with(headers: { 'Authentication' => 'Bearer 123' })
81
+ .to_return(body: { href: 'http://datastore/users/1', name: 'Elizabeth Baker' }.to_json)
82
+ end
83
+
84
+ it 'maps correctly' do
85
+ users = Customer
86
+ .includes(:users)
87
+ .references(users: referencing_options)
88
+ .find(1)
89
+ .users
90
+
91
+ expect(users.first.reversed_name).to be_present
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ describe DHS::Record do
6
+ context 'cache' do
7
+ let(:transaction) { Transaction.find(1) }
8
+ let(:user) { transaction.user }
9
+
10
+ before do
11
+ class Transaction < DHS::Record
12
+ endpoint 'http://myservice/transactions'
13
+ endpoint 'http://myservice/transactions/{id}'
14
+ has_one :user
15
+ end
16
+
17
+ class User < DHS::Record
18
+ has_many :comments
19
+
20
+ def email
21
+ self[:email_address]
22
+ end
23
+ end
24
+
25
+ class Comment < DHS::Record
26
+ end
27
+
28
+ [1, 2].each do |id|
29
+ stub_request(:get, "http://myservice/transactions/#{id}")
30
+ .to_return(body: {
31
+ user: {
32
+ email_address: 'steve@depay.fi',
33
+ comments: []
34
+ }
35
+ }.to_json)
36
+ end
37
+ end
38
+
39
+ it 'caches the relation in memory' do
40
+ allow(DHS::Record).to receive(:for_url).and_return(User)
41
+ user_object_id = transaction.user.object_id
42
+ expect(transaction.user.object_id).to eql(user_object_id)
43
+ transaction2 = Transaction.find(2)
44
+ expect(transaction2.user.object_id).not_to eql(user_object_id)
45
+ end
46
+
47
+ it 'recalculates cache for relation when it was modified' do
48
+ allow(DHS::Record).to receive(:for_url).and_return(Comment)
49
+ expect(user.comments).to be_blank
50
+ comments_object_id = user.comments.object_id
51
+ user.comments = [Comment.new]
52
+ expect(user.comments.object_id).not_to eql(comments_object_id)
53
+ expect(user.comments).not_to be_blank
54
+ end
55
+ end
56
+
57
+ context 'clear cache' do
58
+ before do
59
+ class Place < DHS::Record
60
+ endpoint 'https://datastore/places/{id}', followlocation: true, headers: { 'Prefer' => 'redirect-strategy=redirect-over-not-found' }
61
+ has_many :available_assets
62
+ end
63
+
64
+ class AvailableAsset < DHS::Record
65
+ end
66
+
67
+ stub_request(:get, "http://datastore/places/#{place_id}/available-assets?limit=100")
68
+ .to_return(body: {
69
+ total: available_assets.size,
70
+ items: available_assets
71
+ }.to_json)
72
+ end
73
+
74
+ let(:place_id) { SecureRandom.urlsafe_base64 }
75
+
76
+ let(:place_hash) do
77
+ {
78
+ href: "https://datastore/places/#{place_id}",
79
+ id: place_id,
80
+ available_assets: { href: "http://datastore/places/#{place_id}/available-assets?offset=0&limit=10" }
81
+ }
82
+ end
83
+
84
+ let(:available_asset_hash) do
85
+ { asset_code: 'OPENING_HOURS' }
86
+ end
87
+
88
+ let(:available_assets) { [available_asset_hash] }
89
+
90
+ it 'clears the cache when using find' do
91
+ stub_request(:get, place_hash[:href])
92
+ .to_return(body: place_hash.to_json)
93
+ place = Place
94
+ .options(auth: { bearer: 'XYZ' })
95
+ .includes(:available_assets)
96
+ .find(place_id)
97
+ expect(place.available_assets.first).to be_a(AvailableAsset)
98
+ end
99
+
100
+ it 'clears the cache when using where' do
101
+ stub_request(:get, place_hash[:href])
102
+ .to_return(body: place_hash.to_json)
103
+ place = Place
104
+ .options(auth: { bearer: 'XYZ' })
105
+ .includes(:available_assets)
106
+ .where(id: place_id)
107
+ expect(place.available_assets.first).to be_a(AvailableAsset)
108
+ end
109
+
110
+ it 'clears the cache when using find_by' do
111
+ stub_request(:get, "https://datastore/places/#{place_id}?limit=1")
112
+ .to_return(body: place_hash.to_json)
113
+ place = Place
114
+ .options(auth: { bearer: 'XYZ' })
115
+ .includes(:available_assets)
116
+ .find_by(id: place_id)
117
+ expect(place.available_assets.first).to be_a(AvailableAsset)
118
+ end
119
+ end
120
+ end