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.
- checksums.yaml +7 -0
- data/bin/hoodoo +5 -0
- data/lib/hoodoo.rb +27 -0
- data/lib/hoodoo/active.rb +32 -0
- data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
- data/lib/hoodoo/active/active_record/base.rb +81 -0
- data/lib/hoodoo/active/active_record/creator.rb +134 -0
- data/lib/hoodoo/active/active_record/dated.rb +343 -0
- data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
- data/lib/hoodoo/active/active_record/finder.rb +606 -0
- data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
- data/lib/hoodoo/active/active_record/secure.rb +431 -0
- data/lib/hoodoo/active/active_record/support.rb +106 -0
- data/lib/hoodoo/active/active_record/translated.rb +87 -0
- data/lib/hoodoo/active/active_record/uuid.rb +80 -0
- data/lib/hoodoo/active/active_record/writer.rb +321 -0
- data/lib/hoodoo/client.rb +23 -0
- data/lib/hoodoo/client/augmented_array.rb +29 -0
- data/lib/hoodoo/client/augmented_base.rb +168 -0
- data/lib/hoodoo/client/augmented_hash.rb +23 -0
- data/lib/hoodoo/client/client.rb +354 -0
- data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
- data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
- data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
- data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
- data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
- data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
- data/lib/hoodoo/client/headers.rb +269 -0
- data/lib/hoodoo/communicators.rb +23 -0
- data/lib/hoodoo/communicators/fast.rb +44 -0
- data/lib/hoodoo/communicators/pool.rb +601 -0
- data/lib/hoodoo/communicators/slow.rb +84 -0
- data/lib/hoodoo/data.rb +51 -0
- data/lib/hoodoo/data/resources/caller.rb +39 -0
- data/lib/hoodoo/data/resources/errors.rb +28 -0
- data/lib/hoodoo/data/resources/log.rb +31 -0
- data/lib/hoodoo/data/resources/session.rb +26 -0
- data/lib/hoodoo/data/types/error_primitive.rb +27 -0
- data/lib/hoodoo/data/types/permissions.rb +40 -0
- data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
- data/lib/hoodoo/data/types/permissions_full.rb +28 -0
- data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
- data/lib/hoodoo/discovery.rb +20 -0
- data/lib/hoodoo/errors.rb +19 -0
- data/lib/hoodoo/errors/error_descriptions.rb +229 -0
- data/lib/hoodoo/errors/errors.rb +322 -0
- data/lib/hoodoo/generator.rb +139 -0
- data/lib/hoodoo/logger.rb +23 -0
- data/lib/hoodoo/logger/fast_writer.rb +27 -0
- data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
- data/lib/hoodoo/logger/logger.rb +387 -0
- data/lib/hoodoo/logger/slow_writer.rb +49 -0
- data/lib/hoodoo/logger/writer_mixin.rb +52 -0
- data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
- data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
- data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
- data/lib/hoodoo/middleware.rb +33 -0
- data/lib/hoodoo/presenters.rb +45 -0
- data/lib/hoodoo/presenters/base.rb +281 -0
- data/lib/hoodoo/presenters/base_dsl.rb +519 -0
- data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
- data/lib/hoodoo/presenters/embedding.rb +232 -0
- data/lib/hoodoo/presenters/types/array.rb +118 -0
- data/lib/hoodoo/presenters/types/boolean.rb +26 -0
- data/lib/hoodoo/presenters/types/date.rb +26 -0
- data/lib/hoodoo/presenters/types/date_time.rb +26 -0
- data/lib/hoodoo/presenters/types/decimal.rb +47 -0
- data/lib/hoodoo/presenters/types/enum.rb +55 -0
- data/lib/hoodoo/presenters/types/field.rb +158 -0
- data/lib/hoodoo/presenters/types/float.rb +26 -0
- data/lib/hoodoo/presenters/types/hash.rb +361 -0
- data/lib/hoodoo/presenters/types/integer.rb +26 -0
- data/lib/hoodoo/presenters/types/object.rb +117 -0
- data/lib/hoodoo/presenters/types/string.rb +53 -0
- data/lib/hoodoo/presenters/types/tags.rb +24 -0
- data/lib/hoodoo/presenters/types/text.rb +26 -0
- data/lib/hoodoo/presenters/types/uuid.rb +54 -0
- data/lib/hoodoo/services.rb +34 -0
- data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
- data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
- data/lib/hoodoo/services/discovery/discovery.rb +186 -0
- data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
- data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
- data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
- data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
- data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
- data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
- data/lib/hoodoo/services/middleware/interaction.rb +127 -0
- data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
- data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
- data/lib/hoodoo/services/services/context.rb +153 -0
- data/lib/hoodoo/services/services/implementation.rb +132 -0
- data/lib/hoodoo/services/services/interface.rb +934 -0
- data/lib/hoodoo/services/services/permissions.rb +250 -0
- data/lib/hoodoo/services/services/request.rb +189 -0
- data/lib/hoodoo/services/services/response.rb +316 -0
- data/lib/hoodoo/services/services/service.rb +141 -0
- data/lib/hoodoo/services/services/session.rb +729 -0
- data/lib/hoodoo/utilities.rb +12 -0
- data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
- data/lib/hoodoo/utilities/utilities.rb +380 -0
- data/lib/hoodoo/utilities/uuid.rb +44 -0
- data/lib/hoodoo/version.rb +17 -0
- data/spec/active/active_record/base_spec.rb +57 -0
- data/spec/active/active_record/creator_spec.rb +88 -0
- data/spec/active/active_record/dated_spec.rb +248 -0
- data/spec/active/active_record/error_mapping_spec.rb +360 -0
- data/spec/active/active_record/finder_spec.rb +744 -0
- data/spec/active/active_record/search_helper_spec.rb +384 -0
- data/spec/active/active_record/secure_spec.rb +435 -0
- data/spec/active/active_record/support_spec.rb +225 -0
- data/spec/active/active_record/translated_spec.rb +19 -0
- data/spec/active/active_record/uuid_spec.rb +72 -0
- data/spec/active/active_record/writer_spec.rb +272 -0
- data/spec/alchemy/alchemy-amq.rb +33 -0
- data/spec/client/augmented_array_spec.rb +15 -0
- data/spec/client/augmented_base_spec.rb +50 -0
- data/spec/client/augmented_hash_spec.rb +15 -0
- data/spec/client/client_spec.rb +955 -0
- data/spec/client/endpoint/endpoint_spec.rb +70 -0
- data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
- data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
- data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
- data/spec/client/headers_spec.rb +172 -0
- data/spec/communicators/fast_spec.rb +9 -0
- data/spec/communicators/pool_spec.rb +339 -0
- data/spec/communicators/slow_spec.rb +15 -0
- data/spec/data/resources/caller_spec.rb +156 -0
- data/spec/data/resources/errors_spec.rb +22 -0
- data/spec/data/resources/log_spec.rb +20 -0
- data/spec/data/resources/session_spec.rb +15 -0
- data/spec/data/types/error_primitive_spec.rb +15 -0
- data/spec/data/types/permissions_defaults_spec.rb +25 -0
- data/spec/data/types/permissions_full_spec.rb +44 -0
- data/spec/data/types/permissions_resources_spec.rb +34 -0
- data/spec/data/types/permissions_spec.rb +37 -0
- data/spec/errors/error_descriptions_spec.rb +98 -0
- data/spec/errors/errors_spec.rb +346 -0
- data/spec/integration/service_actions_spec.rb +112 -0
- data/spec/logger/fast_writer_spec.rb +18 -0
- data/spec/logger/logger_spec.rb +259 -0
- data/spec/logger/slow_writer_spec.rb +144 -0
- data/spec/logger/writers/file_writer_spec.rb +37 -0
- data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
- data/spec/logger/writers/stream_writer_spec.rb +38 -0
- data/spec/presenters/base_dsl_spec.rb +111 -0
- data/spec/presenters/base_spec.rb +871 -0
- data/spec/presenters/common_resource_fields_spec.rb +30 -0
- data/spec/presenters/embedding_spec.rb +87 -0
- data/spec/presenters/types/array_spec.rb +249 -0
- data/spec/presenters/types/boolean_spec.rb +51 -0
- data/spec/presenters/types/date_spec.rb +57 -0
- data/spec/presenters/types/date_time_spec.rb +59 -0
- data/spec/presenters/types/decimal_spec.rb +58 -0
- data/spec/presenters/types/enum_spec.rb +71 -0
- data/spec/presenters/types/field_spec.rb +77 -0
- data/spec/presenters/types/float_spec.rb +50 -0
- data/spec/presenters/types/hash_spec.rb +1069 -0
- data/spec/presenters/types/integer_spec.rb +50 -0
- data/spec/presenters/types/object_spec.rb +177 -0
- data/spec/presenters/types/string_spec.rb +65 -0
- data/spec/presenters/types/tags_spec.rb +56 -0
- data/spec/presenters/types/text_spec.rb +50 -0
- data/spec/presenters/types/uuid_spec.rb +46 -0
- data/spec/presenters/walk_spec.rb +198 -0
- data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
- data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
- data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
- data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
- data/spec/services/discovery/discovery_spec.rb +73 -0
- data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
- data/spec/services/discovery/results/for_http_spec.rb +37 -0
- data/spec/services/discovery/results/for_local_spec.rb +21 -0
- data/spec/services/discovery/results/for_remote_spec.rb +15 -0
- data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
- data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
- data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
- data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
- data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
- data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
- data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
- data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
- data/spec/services/middleware/middleware_cors_spec.rb +93 -0
- data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
- data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
- data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
- data/spec/services/middleware/middleware_logging_spec.rb +356 -0
- data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
- data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
- data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
- data/spec/services/middleware/middleware_public_spec.rb +238 -0
- data/spec/services/middleware/middleware_spec.rb +1569 -0
- data/spec/services/middleware/string_inquirer_spec.rb +30 -0
- data/spec/services/services/application_spec.rb +74 -0
- data/spec/services/services/context_spec.rb +48 -0
- data/spec/services/services/implementation_spec.rb +45 -0
- data/spec/services/services/interface_spec.rb +262 -0
- data/spec/services/services/permissions_spec.rb +249 -0
- data/spec/services/services/request_spec.rb +95 -0
- data/spec/services/services/response_spec.rb +250 -0
- data/spec/services/services/session_spec.rb +432 -0
- data/spec/spec_helper.rb +298 -0
- data/spec/utilities/utilities_spec.rb +537 -0
- data/spec/utilities/uuid_spec.rb +20 -0
- 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
|