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,519 @@
1
+ ########################################################################
2
+ # File:: base_dsl.rb
3
+ # (C):: Loyalty New Zealand 2014
4
+ #
5
+ # Purpose:: Implement a DSL used to define a schema for data rendering
6
+ # and validation.
7
+ # ----------------------------------------------------------------------
8
+ # 02-Dec-2014 (ADH): Merge of DocumentedDSL code into BaseDSL.
9
+ ########################################################################
10
+
11
+ module Hoodoo
12
+ module Presenters
13
+
14
+ # A mixin to be used by any presenter that wants to support the
15
+ # Hoodoo::Presenters family of schema DSL methods. See e.g.
16
+ # Hoodoo::Presenters::Base. Mixed in by e.g.
17
+ # Hoodoo::Presenters::Object so that an instance can nest
18
+ # definitions of fields inside itself using this DSL.
19
+ #
20
+ module BaseDSL
21
+
22
+ # Define a JSON object with the supplied name and options.
23
+ #
24
+ # +name+:: The JSON key.
25
+ # +options+:: Optional +Hash+ of options, e.g. :required => true
26
+ # &block:: Block declaring the fields making up the nested object
27
+ #
28
+ # Example - mandatory JSON field "currencies" would lead to an object
29
+ # which had the same fields as Hoodoo::Data::Types::Currency along with
30
+ # an up-to-32 character string with field name "notes", that field also
31
+ # being required. Whether or not the fields of the referenced Currency
32
+ # type are needed is up to the definition of that type. See #type for
33
+ # more information.
34
+ #
35
+ # class Wealthy < Hoodoo::Presenters::Base
36
+ # schema do
37
+ # object :currencies, :required => true do
38
+ # type :Currency
39
+ # string :notes, :required => true, :length => 32
40
+ # end
41
+ # end
42
+ # end
43
+ #
44
+ def object( name, options = {}, &block )
45
+ raise ArgumentError.new( 'Hoodoo::Presenters::Base#Object must have block' ) unless block_given?
46
+
47
+ obj = property( name, Hoodoo::Presenters::Object, options, &block )
48
+ internationalised() if obj.is_internationalised?()
49
+ end
50
+
51
+ # Define a JSON array with the supplied name and options. If there is
52
+ # a block provided, then more DSL calls inside the block define how each
53
+ # array entry must look; otherwise array entries are not validated /
54
+ # are undefined.
55
+ #
56
+ # When an array field uses +:required => true+, this only says that at
57
+ # least an empty array must be present, nothing more. If the array uses
58
+ # a block with fields that themselves are required, then this is only
59
+ # checked for if the array contains one or more entries (and is checked
60
+ # for each of those entries).
61
+ #
62
+ # +name+:: The JSON key
63
+ # +options+:: A +Hash+ of options, e.g. :required => true
64
+ # &block:: Optional block declaring the fields of each array item
65
+ #
66
+ # Example - mandatory JSON field "currencies" would lead to an array
67
+ # where each array entry contains the fields defined by
68
+ # Hoodoo::Data::Types::Currency along with an up-to-32 character string
69
+ # with field name "notes", that field also being required. Whether or not
70
+ # the fields of the referenced Currency type are needed is up to the
71
+ # definition of that type. See #type for more information.
72
+ #
73
+ # class VeryWealthy < Hoodoo::Presenters::Base
74
+ # schema do
75
+ # array :currencies, :required => true do
76
+ # type :Currency
77
+ # string :notes, :required => true, :length => 32
78
+ # end
79
+ # end
80
+ # end
81
+ #
82
+ def array( name, options = {}, &block )
83
+ ary = property( name, Hoodoo::Presenters::Array, options, &block )
84
+ internationalised() if ary.is_internationalised?()
85
+ end
86
+
87
+ # Define a JSON object with the supplied name and optional constraints
88
+ # on properties (like hash keys) and property values (like hash values)
89
+ # that the object may contain, in abstract terms.
90
+ #
91
+ # +name+:: The JSON key
92
+ # +options+:: A +Hash+ of options, e.g. :required => true
93
+ # &block:: Optional block declaring the fields making up the nested
94
+ # hash
95
+ #
96
+ # Example 1 - a Hash where keys must be <= 16 characters long and values
97
+ # must match the Hoodoo::Data::Types::Currency type.
98
+ #
99
+ # class CurrencyHash < Hoodoo::Presenters::Base
100
+ # schema do
101
+ # hash :currencies do
102
+ # keys :length => 16 do
103
+ # type :Currency
104
+ # end
105
+ # end
106
+ # end
107
+ # end
108
+ #
109
+ # See Hoodoo::Presenters::Hash#keys for more information and examples.
110
+ #
111
+ # Example 2 - a Hash where keys must be 'one' or 'two', each with a
112
+ # value matching the given schema.
113
+ #
114
+ # class AltCurrencyHash < Hoodoo::Presenters::Base
115
+ # schema do
116
+ # hash :currencies do
117
+ # key :one do
118
+ # type :Currency
119
+ # end
120
+ #
121
+ # key :two do
122
+ # text :title
123
+ # text :description
124
+ # end
125
+ # end
126
+ # end
127
+ # end
128
+ #
129
+ # See Hoodoo::Presenters::Hash#key for more information and examples.
130
+ #
131
+ def hash( name, options = {}, &block )
132
+ hash = property( name, Hoodoo::Presenters::Hash, options, &block )
133
+ internationalised() if hash.is_internationalised?()
134
+ end
135
+
136
+ # Define a JSON integer with the supplied name and options.
137
+ #
138
+ # +name+:: The JSON key
139
+ # +options+:: A +Hash+ of options, e.g. :required => true
140
+ #
141
+ def integer( name, options = {} )
142
+ property( name, Hoodoo::Presenters::Integer, options )
143
+ end
144
+
145
+ # Define a JSON string with the supplied name and options.
146
+ #
147
+ # +name+:: The JSON key
148
+ # +options+:: A +Hash+ of options, e.g. :required => true, :length => 10
149
+ #
150
+ def string( name, options = {} )
151
+ property( name, Hoodoo::Presenters::String, options )
152
+ end
153
+
154
+ # Define a JSON float with the supplied name and options.
155
+ #
156
+ # +name+:: The JSON key
157
+ # +options+:: A +Hash+ of options, e.g. :required => true
158
+ #
159
+ def float( name, options = {} )
160
+ property( name, Hoodoo::Presenters::Float, options )
161
+ end
162
+
163
+ # Define a JSON decimal with the supplied name and options.
164
+ #
165
+ # +name+:: The JSON key
166
+ # +options+:: A +Hash+ of options, e.g. :required => true, :precision => 10
167
+ #
168
+ def decimal( name, options = {} )
169
+ property( name, Hoodoo::Presenters::Decimal, options )
170
+ end
171
+
172
+ # Define a JSON boolean with the supplied name and options.
173
+ #
174
+ # +name+:: The JSON key
175
+ # +options+:: A +Hash+ of options, e.g. :required => true
176
+ #
177
+ def boolean( name, options = {} )
178
+ property( name, Hoodoo::Presenters::Boolean, options )
179
+ end
180
+
181
+ # Define a JSON date with the supplied name and options.
182
+ #
183
+ # +name+:: The JSON key
184
+ # +options+:: A +Hash+ of options, e.g. :required => true
185
+ #
186
+ def date( name, options = {} )
187
+ property( name, Hoodoo::Presenters::Date, options )
188
+ end
189
+
190
+ # Define a JSON datetime with the supplied name and options.
191
+ #
192
+ # +name+:: The JSON key
193
+ # +options+:: A +Hash+ of options, e.g. :required => true
194
+ #
195
+ def datetime( name, options = {} )
196
+ property( name, Hoodoo::Presenters::DateTime, options )
197
+ end
198
+
199
+ # Define a JSON string of unlimited length with the supplied name
200
+ # and options.
201
+ #
202
+ # +name+:: The JSON key
203
+ # +options+:: A +Hash+ of options, e.g. :required => true
204
+ #
205
+ def text( name, options = {} )
206
+ property( name, Hoodoo::Presenters::Text, options )
207
+ end
208
+
209
+ # Define a JSON string which can only have a restricted set of exactly
210
+ # matched values, with the supplied name and options.
211
+ #
212
+ # +name+:: The JSON key
213
+ # +options+:: A +Hash+ of options, e.g. :required => true and mandatory
214
+ # :from => [array-of-allowed-strings-or-symbols]
215
+ #
216
+ def enum( name, options = {} )
217
+ property( name, Hoodoo::Presenters::Enum, options )
218
+ end
219
+
220
+ # Declares that this Type or Resource has a string field of unlimited
221
+ # length that contains comma-separated tag strings.
222
+ #
223
+ # +field_name+:: Name of the field that will hold the tags.
224
+ # +options+:: Optional options hash. See Hoodoo::Presenters::BaseDSL.
225
+ #
226
+ # Example - a Product resource which supports product tagging:
227
+ #
228
+ # class Product < Hoodoo::Presenters::Base
229
+ # schema do
230
+ # internationalised
231
+ #
232
+ # text :name
233
+ # text :description
234
+ # string :sku, :length => 64
235
+ # tags :tags
236
+ # end
237
+ # end
238
+ #
239
+ def tags( field_name, options = nil )
240
+ options ||= {}
241
+ property( field_name, Hoodoo::Presenters::Tags, options )
242
+ end
243
+
244
+ # Declares that this Type or Resource _refers to_ another Resource
245
+ # instance via its UUID. There's no need to declare the presence of the
246
+ # UUID field _for the instance itself_ on all resource definitions as
247
+ # that's implicit; this #uuid method is just for relational information
248
+ # (AKA associations).
249
+ #
250
+ # +field_name+:: Name of the field that will hold the UUID.
251
+ # +options+:: Options hash. See below.
252
+ #
253
+ # In addition to standard options from Hoodoo::Presenters::BaseDSL,
254
+ # extra option keys and values are:
255
+ #
256
+ # +:resource+:: The name of a resource (as a symbol, e.g. +:Product+) that
257
+ # the UUID should refer to. Implementations _may_ use this
258
+ # to validate that the resource, where a UUID is provided,
259
+ # really is for a Product instance and not something else.
260
+ # Optional.
261
+ #
262
+ # Example - a basket item that refers to an integer quantity of some
263
+ # specific Product resource instance:
264
+ #
265
+ # class BasketItem < Hoodoo::Presenters::Base
266
+ # schema do
267
+ # integer :quantity, :required => true
268
+ # uuid :product_id, :resource => :Product
269
+ # end
270
+ # end
271
+ #
272
+ def uuid( field_name, options = nil )
273
+ options ||= {}
274
+ property(field_name, Hoodoo::Presenters::UUID, options)
275
+ end
276
+
277
+ # Declare that a nested type of a given name is included at this point.
278
+ # This is only normally done within an +array+ or +object+ declaration.
279
+ # The fields of the given named type are considered to be defined inline
280
+ # at the point of declaration - essentially, it's macro expansion.
281
+ #
282
+ # +type_info+:: The Hoodoo::Presenters::Base subclass for the Type in
283
+ # question, e.g. +BasketItem+. The deprecated form of this
284
+ # interface takes the name of the type to nest as a symbol,
285
+ # e.g. +:BasketItem+, in which case the Type must be
286
+ # declared within nested modules "Hoodoo::Data::Types".
287
+ #
288
+ # +options+:: Optional options hash. No options currently defined.
289
+ #
290
+ # It doesn't make sense to mark a +type+ 'field' as +:required+ in the
291
+ # options since the declaration just expands to the contents of the
292
+ # referenced type and it is the definition of that type that determines
293
+ # whether or not its various field(s) are optional or required.
294
+ #
295
+ # Example 1 - a basket includes an array of the Type described by class
296
+ # +BasketItem+:
297
+ #
298
+ # class Basket < Hoodoo::Presenters::Base
299
+ # schema do
300
+ # array :items do
301
+ # type BasketItem
302
+ # end
303
+ # end
304
+ # end
305
+ #
306
+ # A fragment of JSON for a basket might look like this:
307
+ #
308
+ # {
309
+ # "items": [
310
+ # {
311
+ # // (First BasketItem's fields)
312
+ # },
313
+ # {
314
+ # // (First BasketItem's fields)
315
+ # },
316
+ # // etc.
317
+ # ]
318
+ # }
319
+ #
320
+ # Example 2 - a basket item refers to a product description by having
321
+ # its fields inline. So suppose we have this:
322
+ #
323
+ # class Product < Hoodoo::Presenters::Base
324
+ # schema do
325
+ # internationalised
326
+ # text :name
327
+ # text :description
328
+ # end
329
+ # end
330
+ #
331
+ # class BasketItem < Hoodoo::Presenters::Base
332
+ # schema do
333
+ # object :product_data do
334
+ # type Product
335
+ # end
336
+ # end
337
+ # end
338
+ #
339
+ # ...then this would be a valid BasketItem fragment of JSON:
340
+ #
341
+ # {
342
+ # "product_data": {
343
+ # "name": "Washing powder",
344
+ # "description": "Washes whiter than white!"
345
+ # }
346
+ # }
347
+ #
348
+ # It is also possible to use this mechanism for inline expansions when
349
+ # you have, say, a Resource defined _entirely_ in terms of something
350
+ # reused elsewhere as a Type. For example, suppose the product/basket
351
+ # information from above included information on a Currency that was
352
+ # used for payment. It might reuse a Type; meanwhile we might have a
353
+ # resource for managing Currencies, defined entirely through that Type:
354
+ #
355
+ # class Currency < Hoodoo::Presenters::Base
356
+ # schema do
357
+ # string :curency_code, :required => true, :length => 8
358
+ # string :symbol, :length => 16
359
+ # integer :multiplier, :default => 100
360
+ # array :qualifiers do
361
+ # string :qualifier, :length => 32
362
+ # end
363
+ # end
364
+ # end
365
+ #
366
+ # resource :Currency do
367
+ # schema do
368
+ # type Currency # Fields are *inline*
369
+ # end
370
+ # end
371
+ #
372
+ # This means that the *Resource* of +Currency+ has exactly the same
373
+ # fields as the *Type* of Currency. The Resource could define other
374
+ # fields too, though this would be risky as the Type might gain
375
+ # same-named fields in future, leading to undefined behaviour. At such a
376
+ # time, a degree of cut-and-paste and removing the +type+ call from the
377
+ # Resource definition would probably be wise.
378
+ #
379
+ def type( type_info, options = nil )
380
+ options ||= {}
381
+
382
+ if type_info.is_a?( Class ) && type_info < Hoodoo::Presenters::Base
383
+ klass = type_info
384
+ else
385
+ begin
386
+ klass = Hoodoo::Data::Types.const_get( type_info )
387
+ rescue
388
+ raise "Hoodoo::Presenters::Base\#type: Unrecognised type name '#{ type_info }'"
389
+ end
390
+ end
391
+
392
+ self.instance_exec( &klass.get_schema_definition() )
393
+ end
394
+
395
+ # Declare that a resource of a given name is included at this point.
396
+ # This is only normally done within the description of the schema for an
397
+ # interface. The fields of the given named resource are considered to be
398
+ # defined inline at the point of declaration - essentially, it's macro
399
+ # expansion.
400
+ #
401
+ # +resource_info+:: The Hoodoo::Presenters::Base subclass for the
402
+ # Resource in question, e.g. +Product+. The deprecated
403
+ # form of this interface takes the name of the type to
404
+ # nest as a symbol, e.g. +:Product+, in which case the
405
+ # Resource must be declared within nested modules
406
+ # "Hoodoo::Data::Types".
407
+ #
408
+ # +options+:: Optional options hash. No options currently defined.
409
+ #
410
+ # Example - an iterface takes an +Outlet+ resource in its create action.
411
+ #
412
+ # class Outlet < Hoodoo::Presenters::Base
413
+ # schema do
414
+ # internationalised
415
+ #
416
+ # text :name
417
+ # uuid :participant_id, :resource => :Participant, :required => true
418
+ # uuid :calculator_id, :resource => :Calculator
419
+ # end
420
+ # end
421
+ #
422
+ # class OutletInterface < Hoodoo::Services::Interface
423
+ # to_create do
424
+ # resource Outlet
425
+ # end
426
+ # end
427
+ #
428
+ # It doesn't make sense to mark a +resource+ 'field' as +:required+ in
429
+ # the options since the declaration just expands to the contents of the
430
+ # referenced resource and it is the definition of that resource that
431
+ # determines whether or not its various field(s) are optional / required.
432
+ # That is, the following two declarations behave identically:
433
+ #
434
+ # resource Outlet
435
+ #
436
+ # resource Outlet, :required => true # Pointless option!
437
+ #
438
+ def resource( resource_info, options = nil )
439
+ options ||= {}
440
+
441
+ if resource_info.is_a?( Class ) && resource_info < Hoodoo::Presenters::Base
442
+ klass = resource_info
443
+ else
444
+ begin
445
+ klass = Hoodoo::Data::Resources.const_get( resource_info )
446
+ rescue
447
+ raise "Hoodoo::Presenters::Base\#resource: Unrecognised resource name '#{ resource_info }'"
448
+ end
449
+ end
450
+
451
+ self.instance_exec( &klass.get_schema_definition() )
452
+ end
453
+
454
+ # Declares that this Type or Resource contains fields which will may
455
+ # carry human-readable data subject to platform interntionalisation
456
+ # rules. A Resource which is internationalised automatically gains a
457
+ # +language+ field (part of the Platform API's Common Fields) used
458
+ # in resource representations. A Type which is internationalised
459
+ # gains nothing until it is cross-referenced by a Resource definion,
460
+ # at which point the cross-referencing resource becomes itself
461
+ # implicitly internationalised (so it "taints" the resource). For
462
+ # cross-referencing, see #type.
463
+ #
464
+ # +options+:: Optional options hash. No options currently defined.
465
+ #
466
+ # Example - a Member resource with internationalised fields such as
467
+ # the member's name:
468
+ #
469
+ # class Member < Hoodoo::Presenters::Base
470
+ # schema do
471
+ #
472
+ # # Say that Member will contain at least one field that holds
473
+ # # human readable data, causing the Member to be subject to
474
+ # # internationalisation rules.
475
+ #
476
+ # internationalised
477
+ #
478
+ # # Declare fields as normal, for example...
479
+ #
480
+ # text :name
481
+ #
482
+ # end
483
+ # end
484
+ #
485
+ def internationalised( options = nil )
486
+ options ||= {}
487
+ @internationalised = true
488
+ end
489
+
490
+ # An enquiry method related to, but not part of the DSL; returns +true+
491
+ # if the schema instance is internationalised, else +false+.
492
+ #
493
+ def is_internationalised?
494
+ !! @internationalised
495
+ end
496
+
497
+ private
498
+
499
+ # Define a JSON property with the supplied name, type and options.
500
+ # Returns the new property instance.
501
+ #
502
+ # +name+:: The JSON key
503
+ # +type+:: A +Class+ for validation
504
+ # +options+:: A +Hash+ of options, e.g. :required => true
505
+ #
506
+ def property( name, type, options = {}, &block )
507
+ name = name.to_s
508
+ inst = type.new( name, options.merge( { :path => @path + [ name ] } ) )
509
+ inst.instance_eval( &block ) if block_given?
510
+
511
+ @properties ||= {}
512
+ @properties[ name ] = inst
513
+
514
+ return inst
515
+ end
516
+
517
+ end
518
+ end
519
+ end