hoodoo 1.0.2

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 (216) hide show
  1. checksums.yaml +7 -0
  2. data/bin/hoodoo +5 -0
  3. data/lib/hoodoo.rb +27 -0
  4. data/lib/hoodoo/active.rb +32 -0
  5. data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
  6. data/lib/hoodoo/active/active_record/base.rb +81 -0
  7. data/lib/hoodoo/active/active_record/creator.rb +134 -0
  8. data/lib/hoodoo/active/active_record/dated.rb +343 -0
  9. data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
  10. data/lib/hoodoo/active/active_record/finder.rb +606 -0
  11. data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
  12. data/lib/hoodoo/active/active_record/secure.rb +431 -0
  13. data/lib/hoodoo/active/active_record/support.rb +106 -0
  14. data/lib/hoodoo/active/active_record/translated.rb +87 -0
  15. data/lib/hoodoo/active/active_record/uuid.rb +80 -0
  16. data/lib/hoodoo/active/active_record/writer.rb +321 -0
  17. data/lib/hoodoo/client.rb +23 -0
  18. data/lib/hoodoo/client/augmented_array.rb +29 -0
  19. data/lib/hoodoo/client/augmented_base.rb +168 -0
  20. data/lib/hoodoo/client/augmented_hash.rb +23 -0
  21. data/lib/hoodoo/client/client.rb +354 -0
  22. data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
  23. data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
  24. data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
  25. data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
  26. data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
  27. data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
  28. data/lib/hoodoo/client/headers.rb +269 -0
  29. data/lib/hoodoo/communicators.rb +23 -0
  30. data/lib/hoodoo/communicators/fast.rb +44 -0
  31. data/lib/hoodoo/communicators/pool.rb +601 -0
  32. data/lib/hoodoo/communicators/slow.rb +84 -0
  33. data/lib/hoodoo/data.rb +51 -0
  34. data/lib/hoodoo/data/resources/caller.rb +39 -0
  35. data/lib/hoodoo/data/resources/errors.rb +28 -0
  36. data/lib/hoodoo/data/resources/log.rb +31 -0
  37. data/lib/hoodoo/data/resources/session.rb +26 -0
  38. data/lib/hoodoo/data/types/error_primitive.rb +27 -0
  39. data/lib/hoodoo/data/types/permissions.rb +40 -0
  40. data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
  41. data/lib/hoodoo/data/types/permissions_full.rb +28 -0
  42. data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
  43. data/lib/hoodoo/discovery.rb +20 -0
  44. data/lib/hoodoo/errors.rb +19 -0
  45. data/lib/hoodoo/errors/error_descriptions.rb +229 -0
  46. data/lib/hoodoo/errors/errors.rb +322 -0
  47. data/lib/hoodoo/generator.rb +139 -0
  48. data/lib/hoodoo/logger.rb +23 -0
  49. data/lib/hoodoo/logger/fast_writer.rb +27 -0
  50. data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
  51. data/lib/hoodoo/logger/logger.rb +387 -0
  52. data/lib/hoodoo/logger/slow_writer.rb +49 -0
  53. data/lib/hoodoo/logger/writer_mixin.rb +52 -0
  54. data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
  55. data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
  56. data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
  57. data/lib/hoodoo/middleware.rb +33 -0
  58. data/lib/hoodoo/presenters.rb +45 -0
  59. data/lib/hoodoo/presenters/base.rb +281 -0
  60. data/lib/hoodoo/presenters/base_dsl.rb +519 -0
  61. data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
  62. data/lib/hoodoo/presenters/embedding.rb +232 -0
  63. data/lib/hoodoo/presenters/types/array.rb +118 -0
  64. data/lib/hoodoo/presenters/types/boolean.rb +26 -0
  65. data/lib/hoodoo/presenters/types/date.rb +26 -0
  66. data/lib/hoodoo/presenters/types/date_time.rb +26 -0
  67. data/lib/hoodoo/presenters/types/decimal.rb +47 -0
  68. data/lib/hoodoo/presenters/types/enum.rb +55 -0
  69. data/lib/hoodoo/presenters/types/field.rb +158 -0
  70. data/lib/hoodoo/presenters/types/float.rb +26 -0
  71. data/lib/hoodoo/presenters/types/hash.rb +361 -0
  72. data/lib/hoodoo/presenters/types/integer.rb +26 -0
  73. data/lib/hoodoo/presenters/types/object.rb +117 -0
  74. data/lib/hoodoo/presenters/types/string.rb +53 -0
  75. data/lib/hoodoo/presenters/types/tags.rb +24 -0
  76. data/lib/hoodoo/presenters/types/text.rb +26 -0
  77. data/lib/hoodoo/presenters/types/uuid.rb +54 -0
  78. data/lib/hoodoo/services.rb +34 -0
  79. data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
  80. data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
  81. data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
  82. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
  83. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
  84. data/lib/hoodoo/services/discovery/discovery.rb +186 -0
  85. data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
  86. data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
  87. data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
  88. data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
  89. data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
  90. data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
  91. data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
  92. data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
  93. data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
  94. data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
  95. data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
  96. data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
  97. data/lib/hoodoo/services/middleware/interaction.rb +127 -0
  98. data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
  99. data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
  100. data/lib/hoodoo/services/services/context.rb +153 -0
  101. data/lib/hoodoo/services/services/implementation.rb +132 -0
  102. data/lib/hoodoo/services/services/interface.rb +934 -0
  103. data/lib/hoodoo/services/services/permissions.rb +250 -0
  104. data/lib/hoodoo/services/services/request.rb +189 -0
  105. data/lib/hoodoo/services/services/response.rb +316 -0
  106. data/lib/hoodoo/services/services/service.rb +141 -0
  107. data/lib/hoodoo/services/services/session.rb +729 -0
  108. data/lib/hoodoo/utilities.rb +12 -0
  109. data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
  110. data/lib/hoodoo/utilities/utilities.rb +380 -0
  111. data/lib/hoodoo/utilities/uuid.rb +44 -0
  112. data/lib/hoodoo/version.rb +17 -0
  113. data/spec/active/active_record/base_spec.rb +57 -0
  114. data/spec/active/active_record/creator_spec.rb +88 -0
  115. data/spec/active/active_record/dated_spec.rb +248 -0
  116. data/spec/active/active_record/error_mapping_spec.rb +360 -0
  117. data/spec/active/active_record/finder_spec.rb +744 -0
  118. data/spec/active/active_record/search_helper_spec.rb +384 -0
  119. data/spec/active/active_record/secure_spec.rb +435 -0
  120. data/spec/active/active_record/support_spec.rb +225 -0
  121. data/spec/active/active_record/translated_spec.rb +19 -0
  122. data/spec/active/active_record/uuid_spec.rb +72 -0
  123. data/spec/active/active_record/writer_spec.rb +272 -0
  124. data/spec/alchemy/alchemy-amq.rb +33 -0
  125. data/spec/client/augmented_array_spec.rb +15 -0
  126. data/spec/client/augmented_base_spec.rb +50 -0
  127. data/spec/client/augmented_hash_spec.rb +15 -0
  128. data/spec/client/client_spec.rb +955 -0
  129. data/spec/client/endpoint/endpoint_spec.rb +70 -0
  130. data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
  131. data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
  132. data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
  133. data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
  134. data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
  135. data/spec/client/headers_spec.rb +172 -0
  136. data/spec/communicators/fast_spec.rb +9 -0
  137. data/spec/communicators/pool_spec.rb +339 -0
  138. data/spec/communicators/slow_spec.rb +15 -0
  139. data/spec/data/resources/caller_spec.rb +156 -0
  140. data/spec/data/resources/errors_spec.rb +22 -0
  141. data/spec/data/resources/log_spec.rb +20 -0
  142. data/spec/data/resources/session_spec.rb +15 -0
  143. data/spec/data/types/error_primitive_spec.rb +15 -0
  144. data/spec/data/types/permissions_defaults_spec.rb +25 -0
  145. data/spec/data/types/permissions_full_spec.rb +44 -0
  146. data/spec/data/types/permissions_resources_spec.rb +34 -0
  147. data/spec/data/types/permissions_spec.rb +37 -0
  148. data/spec/errors/error_descriptions_spec.rb +98 -0
  149. data/spec/errors/errors_spec.rb +346 -0
  150. data/spec/integration/service_actions_spec.rb +112 -0
  151. data/spec/logger/fast_writer_spec.rb +18 -0
  152. data/spec/logger/logger_spec.rb +259 -0
  153. data/spec/logger/slow_writer_spec.rb +144 -0
  154. data/spec/logger/writers/file_writer_spec.rb +37 -0
  155. data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
  156. data/spec/logger/writers/stream_writer_spec.rb +38 -0
  157. data/spec/presenters/base_dsl_spec.rb +111 -0
  158. data/spec/presenters/base_spec.rb +871 -0
  159. data/spec/presenters/common_resource_fields_spec.rb +30 -0
  160. data/spec/presenters/embedding_spec.rb +87 -0
  161. data/spec/presenters/types/array_spec.rb +249 -0
  162. data/spec/presenters/types/boolean_spec.rb +51 -0
  163. data/spec/presenters/types/date_spec.rb +57 -0
  164. data/spec/presenters/types/date_time_spec.rb +59 -0
  165. data/spec/presenters/types/decimal_spec.rb +58 -0
  166. data/spec/presenters/types/enum_spec.rb +71 -0
  167. data/spec/presenters/types/field_spec.rb +77 -0
  168. data/spec/presenters/types/float_spec.rb +50 -0
  169. data/spec/presenters/types/hash_spec.rb +1069 -0
  170. data/spec/presenters/types/integer_spec.rb +50 -0
  171. data/spec/presenters/types/object_spec.rb +177 -0
  172. data/spec/presenters/types/string_spec.rb +65 -0
  173. data/spec/presenters/types/tags_spec.rb +56 -0
  174. data/spec/presenters/types/text_spec.rb +50 -0
  175. data/spec/presenters/types/uuid_spec.rb +46 -0
  176. data/spec/presenters/walk_spec.rb +198 -0
  177. data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
  178. data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
  179. data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
  180. data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
  181. data/spec/services/discovery/discovery_spec.rb +73 -0
  182. data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
  183. data/spec/services/discovery/results/for_http_spec.rb +37 -0
  184. data/spec/services/discovery/results/for_local_spec.rb +21 -0
  185. data/spec/services/discovery/results/for_remote_spec.rb +15 -0
  186. data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
  187. data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
  188. data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
  189. data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
  190. data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
  191. data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
  192. data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
  193. data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
  194. data/spec/services/middleware/middleware_cors_spec.rb +93 -0
  195. data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
  196. data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
  197. data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
  198. data/spec/services/middleware/middleware_logging_spec.rb +356 -0
  199. data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
  200. data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
  201. data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
  202. data/spec/services/middleware/middleware_public_spec.rb +238 -0
  203. data/spec/services/middleware/middleware_spec.rb +1569 -0
  204. data/spec/services/middleware/string_inquirer_spec.rb +30 -0
  205. data/spec/services/services/application_spec.rb +74 -0
  206. data/spec/services/services/context_spec.rb +48 -0
  207. data/spec/services/services/implementation_spec.rb +45 -0
  208. data/spec/services/services/interface_spec.rb +262 -0
  209. data/spec/services/services/permissions_spec.rb +249 -0
  210. data/spec/services/services/request_spec.rb +95 -0
  211. data/spec/services/services/response_spec.rb +250 -0
  212. data/spec/services/services/session_spec.rb +432 -0
  213. data/spec/spec_helper.rb +298 -0
  214. data/spec/utilities/utilities_spec.rb +537 -0
  215. data/spec/utilities/uuid_spec.rb +20 -0
  216. metadata +615 -0
@@ -0,0 +1,31 @@
1
+ ########################################################################
2
+ # File:: common_resource_fields.rb
3
+ # (C):: Loyalty New Zealand 2014
4
+ #
5
+ # Purpose:: Define a schema describing fields common to any schema that
6
+ # describes an API Resource.
7
+ # ----------------------------------------------------------------------
8
+ # 02-Dec-2014 (ADH): Split from DocumentedPresenter.
9
+ ########################################################################
10
+
11
+ module Hoodoo
12
+ module Presenters
13
+
14
+ # Used internally for additional validation of common Resource fields.
15
+ # See Hoodoo::Presenters::Base::validate.
16
+ #
17
+ class CommonResourceFields < Hoodoo::Presenters::Base
18
+ schema do
19
+ uuid :id, :required => true
20
+ datetime :created_at, :required => true
21
+ text :kind, :required => true
22
+ text :language
23
+
24
+ hash :secured_with
25
+
26
+ hash :_embed
27
+ hash :_reference
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,232 @@
1
+ ########################################################################
2
+ # File:: embedding.rb
3
+ # (C):: Loyalty New Zealand 2015
4
+ #
5
+ # Purpose:: Light weight, simple support for basic embed and reference
6
+ # operations that help reduce service reliance on "knowing"
7
+ # exactly how to structure such data / avoid inconsistency.
8
+ # ----------------------------------------------------------------------
9
+ # 29-Apr-2015 (ADH): Created.
10
+ ########################################################################
11
+
12
+ module Hoodoo
13
+ module Presenters
14
+
15
+ # The Embedding namespace collects classes that assist with rendering
16
+ # embedded resource data.
17
+ #
18
+ module Embedding
19
+
20
+ # The Embeddable base class should not be instantiated directly.
21
+ # It provides common functionality for
22
+ # Hoodoo::Presenters::Embedding::Embeds and
23
+ # Hoodoo::Presenters::Embedding::References - use those instead.
24
+ #
25
+ class Embeddable
26
+
27
+ # Create an instance.
28
+ #
29
+ def initialize
30
+ @hash = {}
31
+ end
32
+
33
+ # Add a singlular resource (for embedding) or UUID (for referencing)
34
+ # to an embed or reference assembly.
35
+ #
36
+ # +key+:: The key to use in the resource representation leading to
37
+ # the embedded resource object or UUID string. Typically
38
+ # follows a singular name convention in your resource API
39
+ # field language of choice, e.g. "member" (an API where the
40
+ # resource names and fields are in English), "mitglied" (an
41
+ # API described in German).
42
+ #
43
+ # This key must match the value specified in the query string
44
+ # of a request in order to ask for the thing in question to
45
+ # be embedded / referenced.
46
+ #
47
+ # +rendered_resource_or_uuid+:: A rendered resource representation
48
+ # in full, or a resource UUID String.
49
+ #
50
+ def add_one( key, rendered_resource_or_uuid )
51
+ validate_one( rendered_resource_or_uuid )
52
+ @hash[ key ] = rendered_resource_or_uuid
53
+ end
54
+
55
+ # Add a collection of resources (for embedding) or UUIDs (for
56
+ # referencing) to an embed or reference assembly.
57
+ #
58
+ # +key+:: The key to use in the resource representation leading to
59
+ # the embedded resource object or UUID string array. Typically
60
+ # follows a plural name convention in your resource API field
61
+ # language of choice, e.g. "members" (an API where the
62
+ # resource names and fields are in English), "mitglieder" (an
63
+ # API described in German).
64
+ #
65
+ # This key must match the value specified in the query string
66
+ # of a request in order to ask for the things in question to
67
+ # be embedded / referenced.
68
+ #
69
+ # +array_of_rendered_resources_or_uuids+::
70
+ # An Array of rendered resource representations in full, or an
71
+ # Array of resource UUID Strings.
72
+ #
73
+ def add_many( key, array_of_rendered_resources_or_uuids )
74
+ validate_many( array_of_rendered_resources_or_uuids )
75
+ @hash[ key ] = array_of_rendered_resources_or_uuids
76
+ end
77
+
78
+ # Delete all data associated with the given key.
79
+ #
80
+ # +key+:: As provided to a prior call to #add_one or #add_many. Has no
81
+ # side effects if the key has not been previously used in such
82
+ # a call; no error is raised in this case either.
83
+ #
84
+ def remove( key )
85
+ @hash.delete( key )
86
+ end
87
+
88
+ # Returns a Hash where keys are the keys provided in calls to #add_one
89
+ # or #add_many and values are the values provided to those same
90
+ # corresponding calls. Returns an empty Hash if no such calls have
91
+ # been made or if all the keys were subsequently removed with #remove.
92
+ #
93
+ def retrieve
94
+ @hash
95
+ end
96
+ end
97
+
98
+ # Instantiate this class and add one, or an Array of fully rendered
99
+ # resource objects to it via the API described in the base class,
100
+ # Hoodoo::Presenters::Embedding::Embeddable. You can then pass it to
101
+ # the likes of Hoodoo::Presenters::Base.render_in via the +options+
102
+ # parameter to have the embed data included in the fully rendered end
103
+ # result.
104
+ #
105
+ # When a request arrives to embed data for a particular resource or
106
+ # list of resources (in which case, do the following for each item in
107
+ # that list):
108
+ #
109
+ # * Render the embedded resource(s)
110
+ # * Create an instance of this class
111
+ # * Add the rendered resource representations using this class's API
112
+ # * Use Hoodoo::Presenters::Base.render_in to render the final, target
113
+ # resource, passing in the embed collection via the +options+ Hash.
114
+ #
115
+ # Simple example:
116
+ #
117
+ # embeds = Hoodoo::Presenters::Embedding::Embeds.new
118
+ # embeds.add_one( 'balance', rendered_balance )
119
+ # embeds.add_many( 'vouchers', rendered_voucher_array )
120
+ #
121
+ class Embeds < Embeddable
122
+
123
+ public
124
+
125
+ # Returns the top-level resource key used for reference data, as per
126
+ # the API documentation - which is the String +_embed+.
127
+ #
128
+ def resource_key
129
+ '_embed'
130
+ end
131
+
132
+ protected
133
+
134
+ # Called from #add_one in the base class to make sure the right data
135
+ # is being supplied. Raises an exception if it gets worried.
136
+ #
137
+ # +thing+:: The value that'll be stored; should be a Hash.
138
+ #
139
+ def validate_one( thing )
140
+ unless thing.is_a?( ::Hash )
141
+ raise "Hoodoo::Presenters::Embedding::Embeds\#add_one requires a rendered resource Hash, but was given an instance of #{ thing.class }"
142
+ end
143
+ end
144
+
145
+ # Called from #add_many in the base class to make sure the right data
146
+ # is being supplied. Raises an exception if it gets worried.
147
+ #
148
+ # +thing+:: The value that'll be stored; should be an Array of Hashes
149
+ # but only the first array entry is checked, for speed.
150
+ #
151
+ def validate_many( thing )
152
+ unless thing.is_a?( ::Array )
153
+ raise "Hoodoo::Presenters::Embedding::Embeds\#add_many requires an Array, but was given an instance of #{ thing.class }"
154
+ end
155
+
156
+ unless thing[ 0 ].nil? || thing[ 0 ].is_a?( ::Hash )
157
+ raise "Hoodoo::Presenters::Embedding::Embeds\#add_many requires an Array of rendered resource Hashes, but the first Array entry is an instance of #{ thing[ 0 ].class }"
158
+ end
159
+ end
160
+
161
+ end
162
+
163
+ # Instantiate this class and add one, or an Array of UUID strings via
164
+ # the API described in the base class,
165
+ # Hoodoo::Presenters::Embedding::Embeddable. You can then pass it to
166
+ # the likes of Hoodoo::Presenters::Base.render_in via the +options+
167
+ # parameter to have the reference data included in the fully rendered
168
+ # end result.
169
+ #
170
+ # When a request arrives to reference UUID data for a particular
171
+ # resource or list of resources (in which case, do the following for
172
+ # each item in that list):
173
+ #
174
+ # * Obtain the referenced resource UUID(s)
175
+ # * Create an instance of this class
176
+ # * Add the UUIDs using this class's API
177
+ # * Use Hoodoo::Presenters::Base.render_in to render the final, target
178
+ # resource, passing in the reference collection via the +options+
179
+ # Hash.
180
+ #
181
+ # Simple example:
182
+ #
183
+ # references = Hoodoo::Presenters::Embedding::References.new
184
+ # references.add_one( 'member', member_uuid )
185
+ # references.add_many( 'memberships', array_of_membership_uuids )
186
+ #
187
+ class References < Embeddable
188
+
189
+ public
190
+
191
+ # Returns the top-level resource key used for reference data, as per
192
+ # the API documentation - which is the String +_reference+.
193
+ #
194
+ def resource_key
195
+ '_reference'
196
+ end
197
+
198
+ protected
199
+
200
+ # Called from #add_one in the base class to make sure the right data
201
+ # is being supplied. Raises an exception if it gets worried.
202
+ #
203
+ # +thing+:: The value that'll be stored; should be a valid UUID.
204
+ #
205
+ def validate_one( thing )
206
+ unless Hoodoo::UUID.valid?( thing )
207
+ raise 'Hoodoo::Presenters::Embedding::References#add_one requires a valid UUID String, but the given value is invalid'
208
+ end
209
+ end
210
+
211
+ # Called from #add_many in the base class to make sure the right data
212
+ # is being supplied. Raises an exception if it gets worried.
213
+ #
214
+ # +thing+:: The value that'll be stored; should be an Array of valid
215
+ # UUIDs, but only the first array entry is checked, for
216
+ # speed.
217
+ #
218
+ def validate_many( thing )
219
+ unless thing.is_a?( ::Array )
220
+ raise "Hoodoo::Presenters::Embedding::References\#add_many requires an Array, but was given an instance of #{ thing.class }"
221
+ end
222
+
223
+ unless thing[ 0 ].nil? || Hoodoo::UUID.valid?( thing[ 0 ] )
224
+ raise 'Hoodoo::Presenters::Embedding::References#add_many requires an Array of valid UUID strings, but the first Array entry is invalid'
225
+ end
226
+ end
227
+
228
+ end
229
+
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,118 @@
1
+ module Hoodoo
2
+ module Presenters
3
+
4
+ # A JSON Array schema member.
5
+ #
6
+ class Array < Hoodoo::Presenters::Field
7
+
8
+ include Hoodoo::Presenters::BaseDSL
9
+
10
+ # The properties of this object, an +array+ of +Field+ instances.
11
+ #
12
+ attr_accessor :properties
13
+
14
+ # Check if data is a valid Array and return a Hoodoo::Errors instance.
15
+ #
16
+ def validate( data, path = '' )
17
+ errors = super( data, path )
18
+ return errors if errors.has_errors? || ( ! @required && data.nil? )
19
+
20
+ if data.is_a?( ::Array )
21
+ # No array entry schema? No array entry validation, then.
22
+ unless @properties.nil?
23
+ data.each_with_index do | item, index |
24
+ @properties.each do | name, property |
25
+ rdata = ( item.is_a?( ::Hash ) && item.has_key?( name ) ) ? item[ name ] : nil
26
+ indexed_path = "#{ full_path( path ) }[#{ index }]"
27
+ errors.merge!( property.validate( rdata, indexed_path ) )
28
+ end
29
+ end
30
+ end
31
+ else
32
+ errors.add_error(
33
+ 'generic.invalid_array',
34
+ :message => "Field `#{ full_path( path ) }` is an invalid array",
35
+ :reference => { :field_name => full_path( path ) }
36
+ )
37
+ end
38
+
39
+ errors
40
+ end
41
+
42
+ # Render an array into the target hash based on the internal state that
43
+ # describes this instance's current path (position in the heirarchy of
44
+ # nested schema entities).
45
+ #
46
+ # +data+:: The Array to render.
47
+ # +target+:: The Hash that we render into. A "path" of keys leading to
48
+ # nested Hashes is built via +super()+, with the final
49
+ # key entry yielding the rendered array.
50
+ #
51
+ def render( data, target )
52
+
53
+ # Data provided is explicitly nil or not an array? Don't need to render
54
+ # anything beyond 'nil' at the field (the not-array case covers nil and
55
+ # covers invalid input, which is treated as nil).
56
+
57
+ return super( nil, target ) if ! data.is_a?( ::Array )
58
+
59
+ # Otherwise, start looking at rendering array contents (even if the
60
+ # input array is empty). This relies on pass-by-reference; we'll update
61
+ # this specific instance of 'array' later. Call 'super' to render the
62
+ # 'array' instance in place in 'target' straight away...
63
+
64
+ array = []
65
+ path = super( array, target )
66
+
67
+ # ...then look at rendering the input entries of 'data' into 'array'.
68
+
69
+ if @properties.nil?
70
+ # Must modify existing instance of 'array', so use 'push()'
71
+ array.push( *data )
72
+
73
+ else
74
+ data.each do | item |
75
+
76
+ # We have properties defined so array values (in "item") must be
77
+ # Hashes. If non-Hash, treat as if nil; explicit-nil-means-nil.
78
+
79
+ unless item.is_a?( ::Hash )
80
+ # Must modify existing instance of 'array', so use 'push()'
81
+ array.push( nil )
82
+ next
83
+ end
84
+
85
+ subtarget = {}
86
+
87
+ @properties.each do | name, property |
88
+ name = name.to_s
89
+ has_key = item.has_key?( name )
90
+
91
+ next unless has_key || property.has_default?()
92
+
93
+ property.render( has_key ? item[ name ] : property.default, subtarget )
94
+ end
95
+
96
+ rendered = subtarget.empty? ? {} : read_at_path( subtarget, path )
97
+
98
+ # Must modify existing instance of 'array', so use 'push()'
99
+ array.push( rendered )
100
+ end
101
+ end
102
+ end
103
+
104
+ # Invoke a given block, passing this item; call recursively for any
105
+ # defined sub-fields too. See Hoodoo::Presenters::Base#walk for why.
106
+ #
107
+ # &block:: Mandatory block, which is passed 'self' when called.
108
+ #
109
+ def walk( &block )
110
+ block.call( self )
111
+
112
+ @properties.each do | name, property |
113
+ property.walk( &block )
114
+ end unless @properties.nil?
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,26 @@
1
+ module Hoodoo
2
+ module Presenters
3
+
4
+ # A JSON Boolean schema member.
5
+ #
6
+ class Boolean < Hoodoo::Presenters::Field
7
+
8
+ # Check if data is a valid Boolean and return a Hoodoo::Errors instance.
9
+ #
10
+ def validate( data, path = '' )
11
+ errors = super( data, path )
12
+ return errors if errors.has_errors? || ( ! @required && data.nil? )
13
+
14
+ unless !! data == data
15
+ errors.add_error(
16
+ 'generic.invalid_boolean',
17
+ :message => "Field `#{ full_path( path ) }` is an invalid boolean",
18
+ :reference => { :field_name => full_path( path ) }
19
+ )
20
+ end
21
+
22
+ errors
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Hoodoo
2
+ module Presenters
3
+
4
+ # A JSON Date schema member.
5
+ #
6
+ class Date < Hoodoo::Presenters::Field
7
+
8
+ # Check if data is a valid Date and return a Hoodoo::Errors instance.
9
+ #
10
+ def validate( data, path = '' )
11
+ errors = super( data, path )
12
+ return errors if errors.has_errors? || ( ! @required && data.nil? )
13
+
14
+ unless Hoodoo::Utilities.valid_iso8601_subset_date?( data )
15
+ errors.add_error(
16
+ 'generic.invalid_date',
17
+ :message => "Field `#{ full_path( path ) }` is an invalid ISO8601 date",
18
+ :reference => { :field_name => full_path( path ) }
19
+ )
20
+ end
21
+
22
+ errors
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Hoodoo
2
+ module Presenters
3
+
4
+ # A JSON DateTime schema member.
5
+ #
6
+ class DateTime < Hoodoo::Presenters::Field
7
+
8
+ # Check if data is a valid DateTime and return a Hoodoo::Errors instance.
9
+ #
10
+ def validate( data, path = '' )
11
+ errors = super( data, path )
12
+ return errors if errors.has_errors? || ( ! @required && data.nil? )
13
+
14
+ unless Hoodoo::Utilities.valid_iso8601_subset_datetime?( data )
15
+ errors.add_error(
16
+ 'generic.invalid_datetime',
17
+ :message => "Field `#{ full_path( path ) }` is an invalid ISO8601 datetime",
18
+ :reference => { :field_name => full_path( path ) }
19
+ )
20
+ end
21
+
22
+ errors
23
+ end
24
+ end
25
+ end
26
+ end