praxis 2.0.pre.17 → 2.0.pre.21

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 (235) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +54 -0
  3. data/.simplecov +3 -1
  4. data/.travis.yml +2 -1
  5. data/CHANGELOG.md +19 -0
  6. data/CONTRIBUTING.md +2 -79
  7. data/Gemfile +5 -1
  8. data/Guardfile +6 -4
  9. data/LICENSE +0 -2
  10. data/MAINTAINERS.md +1 -0
  11. data/README.md +15 -22
  12. data/Rakefile +4 -2
  13. data/bin/praxis +55 -58
  14. data/lib/praxis/action_definition/headers_dsl_compiler.rb +5 -6
  15. data/lib/praxis/action_definition.rb +65 -95
  16. data/lib/praxis/api_definition.rb +21 -29
  17. data/lib/praxis/api_general_info.rb +55 -66
  18. data/lib/praxis/application.rb +15 -32
  19. data/lib/praxis/blueprint.rb +80 -73
  20. data/lib/praxis/bootloader.rb +24 -33
  21. data/lib/praxis/bootloader_stages/environment.rb +5 -10
  22. data/lib/praxis/bootloader_stages/file_loader.rb +3 -6
  23. data/lib/praxis/bootloader_stages/plugin_config_load.rb +4 -6
  24. data/lib/praxis/bootloader_stages/plugin_config_prepare.rb +2 -2
  25. data/lib/praxis/bootloader_stages/plugin_loader.rb +3 -7
  26. data/lib/praxis/bootloader_stages/plugin_setup.rb +3 -3
  27. data/lib/praxis/bootloader_stages/routing.rb +5 -8
  28. data/lib/praxis/bootloader_stages/subgroup_loader.rb +2 -10
  29. data/lib/praxis/bootloader_stages/warn_unloaded_files.rb +15 -19
  30. data/lib/praxis/callbacks.rb +12 -11
  31. data/lib/praxis/collection.rb +11 -14
  32. data/lib/praxis/config.rb +17 -28
  33. data/lib/praxis/config_hash.rb +2 -1
  34. data/lib/praxis/controller.rb +7 -6
  35. data/lib/praxis/dispatcher.rb +34 -42
  36. data/lib/praxis/docs/open_api/info_object.rb +11 -8
  37. data/lib/praxis/docs/open_api/media_type_object.rb +18 -17
  38. data/lib/praxis/docs/open_api/operation_object.rb +7 -4
  39. data/lib/praxis/docs/open_api/parameter_object.rb +17 -14
  40. data/lib/praxis/docs/open_api/paths_object.rb +11 -9
  41. data/lib/praxis/docs/open_api/request_body_object.rb +14 -13
  42. data/lib/praxis/docs/open_api/response_object.rb +24 -18
  43. data/lib/praxis/docs/open_api/responses_object.rb +3 -1
  44. data/lib/praxis/docs/open_api/schema_object.rb +61 -29
  45. data/lib/praxis/docs/open_api/server_object.rb +5 -2
  46. data/lib/praxis/docs/open_api/tag_object.rb +9 -6
  47. data/lib/praxis/docs/open_api_generator.rb +114 -150
  48. data/lib/praxis/endpoint_definition.rb +60 -77
  49. data/lib/praxis/error_handler.rb +2 -2
  50. data/lib/praxis/exception.rb +2 -0
  51. data/lib/praxis/exceptions/config.rb +3 -1
  52. data/lib/praxis/exceptions/config_load.rb +2 -0
  53. data/lib/praxis/exceptions/config_validation.rb +3 -1
  54. data/lib/praxis/exceptions/invalid_configuration.rb +3 -1
  55. data/lib/praxis/exceptions/invalid_response.rb +3 -1
  56. data/lib/praxis/exceptions/invalid_trait.rb +3 -1
  57. data/lib/praxis/exceptions/stage_not_found.rb +3 -1
  58. data/lib/praxis/exceptions/validation.rb +4 -3
  59. data/lib/praxis/extensions/attribute_filtering/active_record_filter_query_builder.rb +163 -149
  60. data/lib/praxis/extensions/attribute_filtering/active_record_patches/5x.rb +18 -13
  61. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_0.rb +13 -9
  62. data/lib/praxis/extensions/attribute_filtering/active_record_patches/6_1_plus.rb +14 -11
  63. data/lib/praxis/extensions/attribute_filtering/active_record_patches.rb +12 -9
  64. data/lib/praxis/extensions/attribute_filtering/filter_tree_node.rb +8 -5
  65. data/lib/praxis/extensions/attribute_filtering/filtering_params.rb +89 -65
  66. data/lib/praxis/extensions/attribute_filtering/filters_parser.rb +68 -62
  67. data/lib/praxis/extensions/attribute_filtering.rb +3 -1
  68. data/lib/praxis/extensions/field_expansion.rb +6 -4
  69. data/lib/praxis/extensions/field_selection/active_record_query_selector.rb +10 -8
  70. data/lib/praxis/extensions/field_selection/field_selector.rb +91 -92
  71. data/lib/praxis/extensions/field_selection/sequel_query_selector.rb +12 -12
  72. data/lib/praxis/extensions/field_selection.rb +3 -1
  73. data/lib/praxis/extensions/pagination/active_record_pagination_handler.rb +6 -4
  74. data/lib/praxis/extensions/pagination/header_generator.rb +16 -11
  75. data/lib/praxis/extensions/pagination/ordering_params.rb +29 -28
  76. data/lib/praxis/extensions/pagination/pagination_handler.rb +44 -42
  77. data/lib/praxis/extensions/pagination/pagination_params.rb +29 -48
  78. data/lib/praxis/extensions/pagination/sequel_pagination_handler.rb +8 -7
  79. data/lib/praxis/extensions/pagination.rb +10 -15
  80. data/lib/praxis/extensions/rails_compat/request_methods.rb +3 -4
  81. data/lib/praxis/extensions/rails_compat.rb +2 -0
  82. data/lib/praxis/extensions/rendering.rb +12 -12
  83. data/lib/praxis/field_expander.rb +8 -9
  84. data/lib/praxis/file_group.rb +8 -12
  85. data/lib/praxis/finalizable.rb +1 -0
  86. data/lib/praxis/handlers/json.rb +5 -2
  87. data/lib/praxis/handlers/plain.rb +2 -1
  88. data/lib/praxis/handlers/www_form.rb +6 -3
  89. data/lib/praxis/handlers/{xml-sample.rb → xml_sample.rb} +26 -22
  90. data/lib/praxis/mapper/active_model_compat.rb +13 -10
  91. data/lib/praxis/mapper/resource.rb +196 -181
  92. data/lib/praxis/mapper/selector_generator.rb +106 -112
  93. data/lib/praxis/mapper/sequel_compat.rb +70 -67
  94. data/lib/praxis/media_type.rb +2 -2
  95. data/lib/praxis/media_type_identifier.rb +26 -22
  96. data/lib/praxis/middleware_app.rb +18 -15
  97. data/lib/praxis/multipart/parser.rb +46 -51
  98. data/lib/praxis/multipart/part.rb +78 -110
  99. data/lib/praxis/notifications.rb +2 -4
  100. data/lib/praxis/plugin.rb +11 -18
  101. data/lib/praxis/plugin_concern.rb +12 -15
  102. data/lib/praxis/plugins/mapper_plugin.rb +15 -13
  103. data/lib/praxis/plugins/pagination_plugin.rb +8 -6
  104. data/lib/praxis/plugins/rails_plugin.rb +33 -28
  105. data/lib/praxis/renderer.rb +11 -15
  106. data/lib/praxis/request.rb +48 -44
  107. data/lib/praxis/request_stages/action.rb +4 -6
  108. data/lib/praxis/request_stages/load_request.rb +2 -4
  109. data/lib/praxis/request_stages/request_stage.rb +19 -23
  110. data/lib/praxis/request_stages/response.rb +4 -6
  111. data/lib/praxis/request_stages/validate.rb +3 -5
  112. data/lib/praxis/request_stages/validate_params_and_headers.rb +15 -22
  113. data/lib/praxis/request_stages/validate_payload.rb +25 -28
  114. data/lib/praxis/request_superclassing.rb +3 -3
  115. data/lib/praxis/resource_definition.rb +1 -0
  116. data/lib/praxis/response.rb +24 -26
  117. data/lib/praxis/response_definition.rb +77 -122
  118. data/lib/praxis/response_template.rb +11 -15
  119. data/lib/praxis/responses/http.rb +23 -44
  120. data/lib/praxis/responses/internal_server_error.rb +18 -21
  121. data/lib/praxis/responses/multipart_ok.rb +4 -9
  122. data/lib/praxis/responses/validation_error.rb +8 -15
  123. data/lib/praxis/route.rb +8 -10
  124. data/lib/praxis/router/rack.rb +13 -7
  125. data/lib/praxis/router/simple.rb +10 -5
  126. data/lib/praxis/router.rb +27 -34
  127. data/lib/praxis/routing_config.rb +52 -29
  128. data/lib/praxis/simple_media_type.rb +5 -8
  129. data/lib/praxis/stage.rb +17 -25
  130. data/lib/praxis/tasks/api_docs.rb +17 -16
  131. data/lib/praxis/tasks/console.rb +3 -1
  132. data/lib/praxis/tasks/environment.rb +2 -0
  133. data/lib/praxis/tasks/routes.rb +26 -24
  134. data/lib/praxis/tasks.rb +3 -1
  135. data/lib/praxis/trait.rb +37 -46
  136. data/lib/praxis/types/fuzzy_hash.rb +13 -14
  137. data/lib/praxis/types/media_type_common.rb +11 -10
  138. data/lib/praxis/types/multipart_array/part_definition.rb +14 -17
  139. data/lib/praxis/types/multipart_array.rb +100 -115
  140. data/lib/praxis/validation_handler.rb +5 -3
  141. data/lib/praxis/version.rb +3 -1
  142. data/lib/praxis.rb +4 -5
  143. data/praxis.gemspec +22 -21
  144. data/spec/functional_spec.rb +44 -56
  145. data/spec/praxis/action_definition_spec.rb +39 -48
  146. data/spec/praxis/api_definition_spec.rb +45 -47
  147. data/spec/praxis/api_general_info_spec.rb +28 -29
  148. data/spec/praxis/application_spec.rb +18 -14
  149. data/spec/praxis/blueprint_spec.rb +33 -34
  150. data/spec/praxis/bootloader_spec.rb +32 -30
  151. data/spec/praxis/callbacks_spec.rb +37 -37
  152. data/spec/praxis/collection_spec.rb +18 -25
  153. data/spec/praxis/config_hash_spec.rb +5 -4
  154. data/spec/praxis/config_spec.rb +27 -26
  155. data/spec/praxis/controller_spec.rb +8 -9
  156. data/spec/praxis/endpoint_definition_spec.rb +25 -32
  157. data/spec/praxis/extensions/attribute_filtering/active_record_filter_query_builder_spec.rb +171 -114
  158. data/spec/praxis/extensions/attribute_filtering/filter_tree_node_spec.rb +22 -21
  159. data/spec/praxis/extensions/attribute_filtering/filtering_params_spec.rb +112 -60
  160. data/spec/praxis/extensions/attribute_filtering/filters_parser_spec.rb +37 -38
  161. data/spec/praxis/extensions/field_expansion_spec.rb +8 -10
  162. data/spec/praxis/extensions/field_selection/active_record_query_selector_spec.rb +14 -13
  163. data/spec/praxis/extensions/field_selection/field_selector_spec.rb +9 -16
  164. data/spec/praxis/extensions/field_selection/sequel_query_selector_spec.rb +50 -49
  165. data/spec/praxis/extensions/pagination/active_record_pagination_handler_spec.rb +32 -31
  166. data/spec/praxis/extensions/rendering_spec.rb +9 -9
  167. data/spec/praxis/extensions/support/spec_resources_active_model.rb +32 -49
  168. data/spec/praxis/extensions/support/spec_resources_sequel.rb +48 -48
  169. data/spec/praxis/field_expander_spec.rb +6 -5
  170. data/spec/praxis/file_group_spec.rb +3 -1
  171. data/spec/praxis/handlers/json_spec.rb +6 -5
  172. data/spec/praxis/mapper/resource_spec.rb +39 -29
  173. data/spec/praxis/mapper/selector_generator_spec.rb +80 -46
  174. data/spec/praxis/media_type_identifier_spec.rb +13 -10
  175. data/spec/praxis/media_type_spec.rb +12 -12
  176. data/spec/praxis/middleware_app_spec.rb +23 -22
  177. data/spec/praxis/multipart/parser_spec.rb +7 -9
  178. data/spec/praxis/notifications_spec.rb +4 -4
  179. data/spec/praxis/plugin_concern_spec.rb +5 -6
  180. data/spec/praxis/renderer_spec.rb +10 -9
  181. data/spec/praxis/request_spec.rb +38 -41
  182. data/spec/praxis/request_stages/action_spec.rb +14 -15
  183. data/spec/praxis/request_stages/request_stage_spec.rb +30 -41
  184. data/spec/praxis/request_stages/validate_spec.rb +3 -1
  185. data/spec/praxis/response_definition_spec.rb +79 -92
  186. data/spec/praxis/response_spec.rb +35 -40
  187. data/spec/praxis/responses/internal_server_error_spec.rb +6 -9
  188. data/spec/praxis/responses/validation_error_spec.rb +17 -18
  189. data/spec/praxis/route_spec.rb +4 -7
  190. data/spec/praxis/router_spec.rb +69 -79
  191. data/spec/praxis/routing_config_spec.rb +15 -14
  192. data/spec/praxis/stage_spec.rb +56 -53
  193. data/spec/praxis/trait_spec.rb +17 -17
  194. data/spec/praxis/types/fuzzy_hash_spec.rb +11 -9
  195. data/spec/praxis/types/multipart_array/part_definition_spec.rb +3 -2
  196. data/spec/praxis/types/multipart_array_spec.rb +33 -48
  197. data/spec/spec_app/app/concerns/authenticated.rb +5 -5
  198. data/spec/spec_app/app/concerns/basic_api.rb +3 -1
  199. data/spec/spec_app/app/concerns/log_wrapper.rb +5 -3
  200. data/spec/spec_app/app/controllers/base_class.rb +6 -5
  201. data/spec/spec_app/app/controllers/instances.rb +31 -34
  202. data/spec/spec_app/app/controllers/volumes.rb +6 -6
  203. data/spec/spec_app/app/responses/multipart.rb +1 -2
  204. data/spec/spec_app/app/responses/other_response.rb +2 -2
  205. data/spec/spec_app/config/environment.rb +19 -6
  206. data/spec/spec_app/config.ru +4 -3
  207. data/spec/spec_app/design/api.rb +13 -15
  208. data/spec/spec_app/design/media_types/instance.rb +6 -6
  209. data/spec/spec_app/design/media_types/volume.rb +2 -1
  210. data/spec/spec_app/design/media_types/volume_snapshot.rb +2 -1
  211. data/spec/spec_app/design/resources/instances.rb +11 -17
  212. data/spec/spec_app/design/resources/volume_snapshots.rb +4 -5
  213. data/spec/spec_app/design/resources/volumes.rb +4 -5
  214. data/spec/spec_helper.rb +11 -13
  215. data/spec/support/be_deep_equal_matcher.rb +5 -0
  216. data/spec/support/spec_authorization_plugin.rb +7 -12
  217. data/spec/support/spec_blueprints.rb +5 -4
  218. data/spec/support/spec_complex_authentication_plugin.rb +17 -34
  219. data/spec/support/spec_endpoint_definitions.rb +2 -3
  220. data/spec/support/spec_media_types.rb +28 -35
  221. data/spec/support/spec_resources.rb +22 -16
  222. data/spec/support/spec_simple_authentication_plugin.rb +5 -9
  223. data/tasks/loader.thor +4 -2
  224. data/tasks/thor/app.rb +7 -5
  225. data/tasks/thor/example.rb +23 -22
  226. data/tasks/thor/model.rb +7 -7
  227. data/tasks/thor/scaffold.rb +23 -23
  228. data/tasks/thor/templates/generator/example_app/app/v1/resources/user.rb +0 -8
  229. data/tasks/thor/templates/generator/scaffold/implementation/resources/item.rb +1 -2
  230. metadata +72 -84
  231. data/MAINTAINERS +0 -2
  232. data/TODO.md +0 -25
  233. data/spec/praxis/api_resource_spec.rb +0 -0
  234. data/spec/praxis/dispatcher_spec.rb +0 -0
  235. data/spec/spec_app/app/responses/bulk_response.rb +0 -0
@@ -1,56 +1,57 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sequel'
2
4
 
3
5
  require 'praxis/mapper/sequel_compat'
4
6
 
5
-
6
7
  # Creates a new in-memory DB, and the necessary tables (and mini-seeds) for the sequel models in this file
7
8
  def create_and_seed_tables
8
- sequeldb = Sequel.sqlite
9
- # sequeldb.loggers = [Logger.new($stdout)] # Uncomment to see sequel logs
10
-
11
- sequeldb.create_table! :sequel_simple_models do
12
- primary_key :id
13
- String :simple_name
14
- Integer :parent_id
15
- String :parent_uuid
16
- Integer :other_model_id
17
- String :added_column
9
+ sequeldb = Sequel.sqlite
10
+ # sequeldb.loggers = [Logger.new($stdout)] # Uncomment to see sequel logs
11
+
12
+ sequeldb.create_table! :sequel_simple_models do
13
+ primary_key :id
14
+ String :simple_name
15
+ Integer :parent_id
16
+ String :parent_uuid
17
+ Integer :other_model_id
18
+ String :added_column
19
+ end
20
+ sequeldb.create_table! :sequel_other_models do
21
+ primary_key :id
22
+ end
23
+ sequeldb.create_table! :sequel_parent_models do
24
+ primary_key :id
25
+ String :uuid
26
+ end
27
+ sequeldb.create_table! :sequel_tag_models do
28
+ primary_key :id
29
+ String :tag_name
30
+ end
31
+ sequeldb.create_table! :sequel_simple_models_sequel_tag_models do
32
+ Integer :sequel_simple_model_id
33
+ Integer :tag_id
18
34
  end
19
- sequeldb.create_table! :sequel_other_models do
20
- primary_key :id
21
- end
22
- sequeldb.create_table! :sequel_parent_models do
23
- primary_key :id
24
- String :uuid
25
- end
26
- sequeldb.create_table! :sequel_tag_models do
27
- primary_key :id
28
- String :tag_name
29
- end
30
- sequeldb.create_table! :sequel_simple_models_sequel_tag_models do
31
- Integer :sequel_simple_model_id
32
- Integer :tag_id
33
- end
34
-
35
- sequeldb[:sequel_parent_models] << { id: 1 , uuid: 'deadbeef1'}
36
- sequeldb[:sequel_parent_models] << { id: 2 , uuid: 'deadbeef2'}
37
-
38
- sequeldb[:sequel_other_models] << { id: 11 }
39
- sequeldb[:sequel_other_models] << { id: 22 }
40
-
41
- sequeldb[:sequel_tag_models] << { id: 1 , tag_name: 'blue' }
42
- sequeldb[:sequel_tag_models] << { id: 2 , tag_name: 'red' }
43
-
44
- # Simple model 1 is tagged as blue and red
45
- sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 1, tag_id: 1 }
46
- sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 1, tag_id: 2 }
47
- # Simple model 2 is tagged as red
48
- sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 2, tag_id: 2 }
49
-
50
- # It's weird to have a parent id and parent uuid (which points to different actual parents)
51
- # But it allows us to check pointing to both PKs and not PK columns
52
- sequeldb[:sequel_simple_models] << { id: 1 , simple_name: 'Simple1', parent_id: 1, other_model_id: 11, parent_uuid: 'deadbeef1'}
53
- sequeldb[:sequel_simple_models] << { id: 2 , simple_name: 'Simple2', parent_id: 2, other_model_id: 22, parent_uuid: 'deadbeef1'}
35
+
36
+ sequeldb[:sequel_parent_models] << { id: 1, uuid: 'deadbeef1' }
37
+ sequeldb[:sequel_parent_models] << { id: 2, uuid: 'deadbeef2' }
38
+
39
+ sequeldb[:sequel_other_models] << { id: 11 }
40
+ sequeldb[:sequel_other_models] << { id: 22 }
41
+
42
+ sequeldb[:sequel_tag_models] << { id: 1, tag_name: 'blue' }
43
+ sequeldb[:sequel_tag_models] << { id: 2, tag_name: 'red' }
44
+
45
+ # Simple model 1 is tagged as blue and red
46
+ sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 1, tag_id: 1 }
47
+ sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 1, tag_id: 2 }
48
+ # Simple model 2 is tagged as red
49
+ sequeldb[:sequel_simple_models_sequel_tag_models] << { sequel_simple_model_id: 2, tag_id: 2 }
50
+
51
+ # It's weird to have a parent id and parent uuid (which points to different actual parents)
52
+ # But it allows us to check pointing to both PKs and not PK columns
53
+ sequeldb[:sequel_simple_models] << { id: 1, simple_name: 'Simple1', parent_id: 1, other_model_id: 11, parent_uuid: 'deadbeef1' }
54
+ sequeldb[:sequel_simple_models] << { id: 2, simple_name: 'Simple2', parent_id: 2, other_model_id: 22, parent_uuid: 'deadbeef1' }
54
55
  end
55
56
 
56
57
  create_and_seed_tables
@@ -76,7 +77,6 @@ class SequelTagModel < Sequel::Model
76
77
  include Praxis::Mapper::SequelCompat
77
78
  end
78
79
 
79
-
80
80
  # A set of resource classes for use in specs
81
81
  class SequelBaseResource < Praxis::Mapper::Resource
82
82
  end
@@ -100,7 +100,7 @@ class SequelSimpleResource < SequelBaseResource
100
100
 
101
101
  # Forces to add an extra column (added_column)...and yet another (parent_id) that will serve
102
102
  # to check that if that's already automatically added due to an association, it won't interfere or duplicate
103
- property :parent, dependencies: [:parent, :added_column, :parent_id]
103
+ property :parent, dependencies: %i[parent added_column parent_id]
104
104
 
105
105
  property :name, dependencies: [:simple_name]
106
106
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe Praxis::FieldExpander do
5
6
  let(:field_expander) { Praxis::FieldExpander.new }
6
7
  let(:expanded_person_default_fieldset) do
7
8
  # The only ones that are not already leaves is the full name, which can expand to first, last
8
- PersonBlueprint.default_fieldset.merge!(full_name: {first: true, last: true})
9
+ PersonBlueprint.default_fieldset.merge!(full_name: { first: true, last: true })
9
10
  end
10
11
  let(:expanded_address_default_fieldset) do
11
12
  # AddressBlueprint' default fieldset already has all attributes as leaves
@@ -96,20 +97,20 @@ describe Praxis::FieldExpander do
96
97
 
97
98
  context 'expanding a two-dimensional collection' do
98
99
  it 'expands the fields discarding the collection nexting nesting' do
99
- matrix_type = Attributor::Collection.of(Attributor::Collection.of(FullName))
100
+ matrix_type = Attributor::Collection.of(Attributor::Collection.of(FullName))
100
101
  expect(field_expander.expand(matrix_type)).to eq(first: true, last: true)
101
102
  end
102
103
  end
103
104
 
104
105
  context 'circular expansions' do
105
106
  it 'preserve field object identity for circular references' do
106
- result = field_expander.expand(PersonBlueprint, address: {resident: true}, work_address: {resident: true})
107
+ result = field_expander.expand(PersonBlueprint, address: { resident: true }, work_address: { resident: true })
107
108
  expect(result[:address][:resident]).to be(result[:work_address][:resident])
108
109
  end
109
110
 
110
111
  context 'with collections of Blueprints' do
111
112
  it 'still preserves object identity' do
112
- result = field_expander.expand(PersonBlueprint, address: {resident: true}, prior_addresses: {resident: true})
113
+ result = field_expander.expand(PersonBlueprint, address: { resident: true }, prior_addresses: { resident: true })
113
114
  expect(result[:address][:resident]).to be(result[:prior_addresses][:resident])
114
115
  end
115
116
  end
@@ -146,4 +147,4 @@ describe Praxis::FieldExpander do
146
147
  expect(field_expander.expand(type, true)).to eq(expected)
147
148
  end
148
149
  end
149
- end
150
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::FileGroup do
4
6
  let(:app) { Praxis::Application.instance }
5
7
  let(:layout) { app.file_layout }
6
8
 
7
- context '#initialize' do
9
+ context '#initialize' do
8
10
  it 'raises an error if given nil for the base path' do
9
11
  expect { Praxis::FileGroup.new(nil) }.to raise_error(ArgumentError)
10
12
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::Handlers::JSON do
4
- let(:dictionary) { {"foo" => 1} }
6
+ let(:dictionary) { { 'foo' => 1 } }
5
7
  let(:dictionary_json) { '{"foo":1}' }
6
8
 
7
- let(:array) { [1,2,3] }
9
+ let(:array) { [1, 2, 3] }
8
10
  let(:array_json) { '[1,2,3]' }
9
11
 
10
12
  describe '#parse' do
@@ -14,14 +16,13 @@ describe Praxis::Handlers::JSON do
14
16
 
15
17
  it 'handles arrays' do
16
18
  expect(subject.parse(array_json)).to eq(array)
17
-
18
19
  end
19
20
  end
20
21
 
21
22
  # slightly cheesy: use #parse to test #generate by round-tripping everything
22
23
  describe '#generate' do
23
24
  it 'pretty-prints' do
24
- result = subject.generate({"foo" => 1})
25
+ result = subject.generate({ 'foo' => 1 })
25
26
  expect(result).to include("\n")
26
27
  expect(result).to match(/^ /m)
27
28
  end
@@ -34,4 +35,4 @@ describe Praxis::Handlers::JSON do
34
35
  expect(subject.parse(subject.generate(array))).to eq(array)
35
36
  end
36
37
  end
37
- end
38
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Praxis::Mapper::Resource do
4
6
  let(:parent_record) { ParentModel.new(id: 100, name: 'george sr') }
5
- let(:parent_records) { [ParentModel.new(id: 101, name: "georgia"),ParentModel.new(id: 102, name: 'georgina')] }
7
+ let(:parent_records) { [ParentModel.new(id: 101, name: 'georgia'), ParentModel.new(id: 102, name: 'georgina')] }
6
8
  let(:record) { SimpleModel.new(id: 103, name: 'george xvi') }
7
- let(:model) { SimpleModel}
9
+ let(:model) { SimpleModel }
8
10
 
9
11
  context 'configuration' do
10
12
  subject(:resource) { SimpleResource }
@@ -30,10 +32,10 @@ describe Praxis::Mapper::Resource do
30
32
  context 'retrieving resources' do
31
33
  context 'getting a single resource' do
32
34
  before do
33
- expect(SimpleModel).to receive(:get).with(name: 'george xvi').and_return(record)
35
+ expect(SimpleModel).to receive(:get).with(name: 'george xvi').and_return(record)
34
36
  end
35
37
 
36
- subject(:resource) { SimpleResource.get(:name => 'george xvi') }
38
+ subject(:resource) { SimpleResource.get(name: 'george xvi') }
37
39
 
38
40
  it { is_expected.to be_kind_of(SimpleResource) }
39
41
 
@@ -45,7 +47,7 @@ describe Praxis::Mapper::Resource do
45
47
  expect(SimpleModel).to receive(:all).with(name: ['george xvi']).and_return([record])
46
48
  end
47
49
 
48
- subject(:resource_collection) { SimpleResource.all(:name => ["george xvi"]) }
50
+ subject(:resource_collection) { SimpleResource.all(name: ['george xvi']) }
49
51
 
50
52
  it { is_expected.to be_kind_of(Array) }
51
53
 
@@ -58,7 +60,6 @@ describe Praxis::Mapper::Resource do
58
60
  end
59
61
 
60
62
  context 'delegating to the underlying model' do
61
-
62
63
  subject { SimpleResource.new(record) }
63
64
 
64
65
  it 'does respond_to attributes in the model' do
@@ -66,13 +67,13 @@ describe Praxis::Mapper::Resource do
66
67
  end
67
68
 
68
69
  it 'does not respond_to :id if the model does not have it' do
69
- resource = OtherResource.new(OtherModel.new(:name => "foo"))
70
+ resource = OtherResource.new(OtherModel.new(name: 'foo'))
70
71
  expect(resource).not_to respond_to(:id)
71
72
  end
72
73
 
73
74
  it 'returns raw results for simple attributes' do
74
75
  expect(record).to receive(:name).and_call_original
75
- expect(subject.name).to eq("george xvi")
76
+ expect(subject.name).to eq('george xvi')
76
77
  end
77
78
 
78
79
  it 'wraps model objects in Resource instances' do
@@ -81,14 +82,14 @@ describe Praxis::Mapper::Resource do
81
82
  parent = subject.parent
82
83
 
83
84
  expect(parent).to be_kind_of(ParentResource)
84
- expect(parent.name).to eq("george sr")
85
+ expect(parent.name).to eq('george sr')
85
86
  expect(parent.record).to eq(parent_record)
86
87
  end
87
88
 
88
- context "for serialized array associations" do
89
- let(:record) { YamlArrayModel.new(:id => 1)}
89
+ context 'for serialized array associations' do
90
+ let(:record) { YamlArrayModel.new(id: 1) }
90
91
 
91
- subject { YamlArrayResource.new(record)}
92
+ subject { YamlArrayResource.new(record) }
92
93
 
93
94
  it 'wraps arrays of model objects in an array of resource instances' do
94
95
  expect(record).to receive(:parents).and_return(parent_records)
@@ -98,34 +99,33 @@ describe Praxis::Mapper::Resource do
98
99
  expect(parents).to be_kind_of(Array)
99
100
 
100
101
  parents.each { |parent| expect(parent).to be_kind_of(ParentResource) }
101
- expect(parents.collect { |parent| parent.record }).to match_array(parent_records)
102
+ expect(parents.collect(&:record)).to match_array(parent_records)
102
103
  end
103
104
  end
104
105
  end
105
106
 
106
107
  context 'resource_delegate' do
107
- let(:other_name) { "foo" }
108
- let(:other_attribute) { "other value" }
109
- let(:other_record) { OtherModel.new(:name => other_name, :other_attribute => other_attribute)}
108
+ let(:other_name) { 'foo' }
109
+ let(:other_attribute) { 'other value' }
110
+ let(:other_record) { OtherModel.new(name: other_name, other_attribute: other_attribute) }
110
111
  let(:other_resource) { OtherResource.new(other_record) }
111
112
 
112
- let(:record) { SimpleModel.new(id: 105, name: "george xvi", other_name: other_name) }
113
+ let(:record) { SimpleModel.new(id: 105, name: 'george xvi', other_name: other_name) }
113
114
 
114
115
  subject(:resource) { SimpleResource.new(record) }
115
-
116
+
116
117
  it 'delegates to the target' do
117
118
  expect(record).to receive(:other_model).and_return(other_record)
118
119
  expect(resource.other_attribute).to eq(other_attribute)
119
120
  end
120
121
  end
121
122
 
122
-
123
- context "memoized resource creation" do
124
- let(:other_name) { "foo" }
125
- let(:other_attribute) { "other value" }
126
- let(:other_record) { OtherModel.new(:name => other_name, :other_attribute => other_attribute)}
123
+ context 'memoized resource creation' do
124
+ let(:other_name) { 'foo' }
125
+ let(:other_attribute) { 'other value' }
126
+ let(:other_record) { OtherModel.new(name: other_name, other_attribute: other_attribute) }
127
127
  let(:other_resource) { OtherResource.new(other_record) }
128
- let(:record) { SimpleModel.new(id: 105, name: "george xvi", other_name: other_name) }
128
+ let(:record) { SimpleModel.new(id: 105, name: 'george xvi', other_name: other_name) }
129
129
 
130
130
  subject(:resource) { SimpleResource.new(record) }
131
131
 
@@ -134,10 +134,21 @@ describe Praxis::Mapper::Resource do
134
134
  expect(resource.other_resource).to be(SimpleResource.new(record).other_resource)
135
135
  end
136
136
 
137
- end
137
+ it 'memoizes result of related associations' do
138
+ expect(record).to receive(:parent).once.and_return(parent_record)
139
+ expect(resource.parent).to be(resource.parent)
140
+ end
138
141
 
142
+ it 'can clear memoization' do
143
+ expect(record).to receive(:parent).twice.and_return(parent_record)
139
144
 
140
- context ".wrap" do
145
+ expect(resource.parent).to be(resource.parent) # One time only calling the record parent method
146
+ resource.clear_memoization
147
+ expect(resource.parent).to be(resource.parent) # One time only time calling the record parent method after the reset
148
+ end
149
+ end
150
+
151
+ context '.wrap' do
141
152
  it 'memoizes resource creation' do
142
153
  expect(SimpleResource.wrap(record)).to be(SimpleResource.wrap(record))
143
154
  end
@@ -153,9 +164,9 @@ describe Praxis::Mapper::Resource do
153
164
  expect(wrapped_set).to be_kind_of(Array)
154
165
  expect(wrapped_set.length).to be(1)
155
166
  end
156
-
167
+
157
168
  it 'works with non-enumerable objects, that respond to collect' do
158
- collectable = double("ArrayProxy", to_a: [record, record] )
169
+ collectable = double('ArrayProxy', to_a: [record, record])
159
170
 
160
171
  wrapped_set = SimpleResource.wrap(collectable)
161
172
  expect(wrapped_set.length).to be(2)
@@ -165,5 +176,4 @@ describe Praxis::Mapper::Resource do
165
176
  expect(SimpleResource.wrap(record)).to be(OtherResource.wrap(record))
166
177
  end
167
178
  end
168
-
169
179
  end