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,23 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: client.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: Include code that makes it easy to call resource endpoints.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 10-Mar-2015 (ADH): Created
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
require 'hoodoo/client/headers'
|
11
|
+
|
12
|
+
require 'hoodoo/client/augmented_base'
|
13
|
+
require 'hoodoo/client/augmented_hash'
|
14
|
+
require 'hoodoo/client/augmented_array'
|
15
|
+
|
16
|
+
require 'hoodoo/client/endpoint/endpoint'
|
17
|
+
require 'hoodoo/client/endpoint/endpoints/http_based'
|
18
|
+
require 'hoodoo/client/endpoint/endpoints/http'
|
19
|
+
require 'hoodoo/client/endpoint/endpoints/amqp'
|
20
|
+
require 'hoodoo/client/endpoint/endpoints/not_found'
|
21
|
+
require 'hoodoo/client/endpoint/endpoints/auto_session'
|
22
|
+
|
23
|
+
require 'hoodoo/client/client'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: augmented_array.rb.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: A subclass of Ruby standard library Array used by the
|
6
|
+
# Hoodoo::Client::Endpoint family.
|
7
|
+
# ----------------------------------------------------------------------
|
8
|
+
# 11-Dec-2014 (ADH): Created.
|
9
|
+
# 05-Mar-2015 (ADH): Moved to Hoodoo::Client.
|
10
|
+
########################################################################
|
11
|
+
|
12
|
+
module Hoodoo
|
13
|
+
class Client # Just used as a namespace here
|
14
|
+
|
15
|
+
# Ruby standard library Array subclass which mixes in
|
16
|
+
# Hoodoo::Client::AugmentedBase. See that for details.
|
17
|
+
#
|
18
|
+
class AugmentedArray < ::Array
|
19
|
+
include Hoodoo::Client::AugmentedBase
|
20
|
+
|
21
|
+
# For lists, the (optional) total size of the data set, of which
|
22
|
+
# the contents of this Array will often only represent a single
|
23
|
+
# page. If unknown, the value is +nil+.
|
24
|
+
#
|
25
|
+
attr_accessor :dataset_size
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: augmented_array.rb.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: A subclass of Ruby standard library Array used by the
|
6
|
+
# Hoodoo::Client::Endpoint family.
|
7
|
+
# ----------------------------------------------------------------------
|
8
|
+
# 11-Dec-2014 (ADH): Created.
|
9
|
+
# 05-Mar-2015 (ADH): Moved to Hoodoo::Client.
|
10
|
+
########################################################################
|
11
|
+
|
12
|
+
module Hoodoo
|
13
|
+
class Client # Just used as a namespace here
|
14
|
+
|
15
|
+
# Base mixin for Hoodoo::Client::AugmentedHash and
|
16
|
+
# Hoodoo::Client::AugmentedArray, used by the
|
17
|
+
# Hoodoo::Client::Endpoint family for return
|
18
|
+
# values in its resource calling API - see:
|
19
|
+
#
|
20
|
+
# * Hoodoo::Client::Endpoint#list
|
21
|
+
# * Hoodoo::Client::Endpoint#show
|
22
|
+
# * Hoodoo::Client::Endpoint#create
|
23
|
+
# * Hoodoo::Client::Endpoint#update
|
24
|
+
# * Hoodoo::Client::Endpoint#delete
|
25
|
+
#
|
26
|
+
# The error handling mechanism this mixin provides is intentionally
|
27
|
+
# analogous to that used for mapping ActiveRecord model validation
|
28
|
+
# failures to platform errors in Hoodoo::ActiveRecord::ErrorMapping
|
29
|
+
# for when resource endpoint implementations are calling other
|
30
|
+
# resource endpoint implementations, while also supporting use cases
|
31
|
+
# of external callers wanting to communicate with resources from
|
32
|
+
# "outside the system".
|
33
|
+
#
|
34
|
+
module AugmentedBase
|
35
|
+
|
36
|
+
# This call is typically used by resource endpoint implementations
|
37
|
+
# ("service authors") during inter-resource calls, rather than by
|
38
|
+
# external entities calling into a system via Hoodoo::Client.
|
39
|
+
#
|
40
|
+
# Errors set via #set_platform_errors are added to the
|
41
|
+
# given Hoodoo::Errors instance. Generally, #set_platform_errors is
|
42
|
+
# only called by the Hoodoo::Client under-the-hood implementation
|
43
|
+
# code as part of routine error handling.
|
44
|
+
#
|
45
|
+
# Returns +true+ if any errors were added else +false+ if everything
|
46
|
+
# is OK (no platform errors have been noted internally).
|
47
|
+
#
|
48
|
+
# This makes the idiomatic example for "make inter-resource call,
|
49
|
+
# add any errors to my service's response and return on error" very
|
50
|
+
# simple, at the expense of modifying the passed-in error collection
|
51
|
+
# contents (mutating a parameter is a risky pattern). For an
|
52
|
+
# alternative pattern which avoids this, see #platform_errors.
|
53
|
+
#
|
54
|
+
# Otherwise, a hypothetical resource +Member+ could be listed as
|
55
|
+
# follows, as part of a hypothetical +show+ implementation of some
|
56
|
+
# other resource:
|
57
|
+
#
|
58
|
+
# def show( context )
|
59
|
+
# list = context.resource( :Member ).list()
|
60
|
+
# return if list.adds_errors_to?( context.response.errors )
|
61
|
+
# # ...
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# External callers that have nothing to do with resource endpoint
|
65
|
+
# implementations could still construct an errors collection manually
|
66
|
+
# and make use of this method, but calling #platform_errors makes a
|
67
|
+
# lot more sense for that use case.
|
68
|
+
#
|
69
|
+
# +collection+:: A Hoodoo::Errors instance, typically obtained
|
70
|
+
# from the Hoodoo::Services::Context instance passed to
|
71
|
+
# a service implementation in calls like
|
72
|
+
# Hoodoo::Services::Implementation#list or
|
73
|
+
# Hoodoo::Services::Implementation#show, via
|
74
|
+
# +context.response.errors+
|
75
|
+
# (i.e. Hoodoo::Services::Context#response /
|
76
|
+
# Hoodoo::Services::Response#errors). The collection you
|
77
|
+
# pass is updated with any errors noted internally via
|
78
|
+
# (usually-middleware-automatically-called) method
|
79
|
+
# #set_platform_errors.
|
80
|
+
#
|
81
|
+
def adds_errors_to?( collection )
|
82
|
+
to_add = self.platform_errors()
|
83
|
+
|
84
|
+
if to_add.has_errors?
|
85
|
+
collection.merge!( to_add )
|
86
|
+
return true
|
87
|
+
else
|
88
|
+
return false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# This call is typically used by external entities calling into a
|
93
|
+
# system via Hoodoo::Client.
|
94
|
+
#
|
95
|
+
# Returns a Hoodoo::Errors instance that's either been assigned
|
96
|
+
# via #set_platform_errors or is an empty, internally assigned
|
97
|
+
# collection. This method is very closely related to
|
98
|
+
# #adds_errors_to? and, if you have not already done so, you should
|
99
|
+
# read that method's documentation before continuing.
|
100
|
+
#
|
101
|
+
# For external client users, the error handling pattern is:
|
102
|
+
#
|
103
|
+
# client = Hoodoo::Client.new( ... )
|
104
|
+
# endpoint = client.resource( 'Foo' )
|
105
|
+
# result = endpoint.show/list/create/update/delete( ... )
|
106
|
+
#
|
107
|
+
# if result.platform_errors.halt_processing?
|
108
|
+
# # Handle result.platform_errors's error data
|
109
|
+
# else
|
110
|
+
# # Success case
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# For service authors, the #platform_errors method supports a
|
114
|
+
# slightly more verbose form of error handling for inter-resource
|
115
|
+
# calls that avoids changing a passed in parameter in the manner
|
116
|
+
# of #adds_errors_to?. Compare the idiom shown there:
|
117
|
+
#
|
118
|
+
# return if list.adds_errors_to?( context.response.errors )
|
119
|
+
#
|
120
|
+
# ...with the idiomatic use of this method:
|
121
|
+
#
|
122
|
+
# context.response.add_errors( list.platform_errors )
|
123
|
+
# return if context.response.halt_processing?
|
124
|
+
#
|
125
|
+
# It is a little more verbose and very slightly less efficient as
|
126
|
+
# it involves more method calls end to end, but you may prefer the
|
127
|
+
# conceptually cleaner approach. You can lean on the return value
|
128
|
+
# of #add_errors and end up back at one line of (very slightly less
|
129
|
+
# obvious) code, too:
|
130
|
+
#
|
131
|
+
# return if context.response.add_errors( list.platform_errors )
|
132
|
+
#
|
133
|
+
def platform_errors
|
134
|
+
@nz_co_loyalty_platform_errors ||= Hoodoo::Errors.new
|
135
|
+
end
|
136
|
+
|
137
|
+
# Sets the Hoodoo::Errors instance used by #adds_errors_to? or
|
138
|
+
# returned by #platform_errors.
|
139
|
+
#
|
140
|
+
# It is expected that only Hoodoo::Client-family code will call this
|
141
|
+
# method as part of general error handling, though client code may
|
142
|
+
# find other uses that are independent of the inter-resource call
|
143
|
+
# case wherein the method may be safely invoked.
|
144
|
+
#
|
145
|
+
def set_platform_errors( errors )
|
146
|
+
@nz_co_loyalty_platform_errors = errors
|
147
|
+
end
|
148
|
+
|
149
|
+
# On success, this Hash may be updated with options describing
|
150
|
+
# 'out-of-band' information associated with the response, derived from
|
151
|
+
# HTTP headers for HTTP-based transports. Non-HTTP transports still
|
152
|
+
# carry HTTP-like headers and apply equally here.
|
153
|
+
#
|
154
|
+
# For more about the mapping from header to option, see class method
|
155
|
+
# Hoodoo::Client::Headers.x_header_to_options. Since Hoodoo itself
|
156
|
+
# sets up <tt>X-Interaction-ID</tt> and <tt>X-Service-Response-Time</tt>
|
157
|
+
# headers in _most_ cases, you can expect to at least find the options
|
158
|
+
# +interaction_id+ and +service_response_time+ set for successful calls.
|
159
|
+
#
|
160
|
+
# Under some circustances, especially for certain error conditions, the
|
161
|
+
# value may be +nil+, though Hoodoo endeavours to avoid this and at
|
162
|
+
# least fill in +interaction_id+ where possible.
|
163
|
+
#
|
164
|
+
attr_accessor :response_options
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: augmented_array.rb.rb
|
3
|
+
# (C):: Loyalty New Zealand 2014
|
4
|
+
#
|
5
|
+
# Purpose:: A subclass of Ruby standard library Array used by the
|
6
|
+
# Hoodoo::Client::Endpoint family.
|
7
|
+
# ----------------------------------------------------------------------
|
8
|
+
# 11-Dec-2014 (ADH): Created.
|
9
|
+
# 05-Mar-2015 (ADH): Moved to Hoodoo::Client.
|
10
|
+
########################################################################
|
11
|
+
|
12
|
+
module Hoodoo
|
13
|
+
class Client # Just used as a namespace here
|
14
|
+
|
15
|
+
# Ruby standard library Hash subclass which mixes in
|
16
|
+
# Hoodoo::Client::AugmentedBase. See that for details.
|
17
|
+
#
|
18
|
+
class AugmentedHash < ::Hash
|
19
|
+
include Hoodoo::Client::AugmentedBase
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,354 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: client.rb
|
3
|
+
# (C):: Loyalty New Zealand 2015
|
4
|
+
#
|
5
|
+
# Purpose:: Easy communication with Resource implementations.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 25-Feb-2015 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
require 'hoodoo/client/headers'
|
11
|
+
|
12
|
+
module Hoodoo
|
13
|
+
|
14
|
+
# Hoodoo::Client provides a high-level abstracted interface for making
|
15
|
+
# calls to Resource implementations. A Client instance is created and used
|
16
|
+
# as a factory for objects representing individual Resources. Callers use
|
17
|
+
# a consistent, high level interface in these objects to make requests to
|
18
|
+
# those Resources and do not usually need to worry about where
|
19
|
+
# implementations are, or how they are being contacted.
|
20
|
+
#
|
21
|
+
# Please see the constructor documentation for full details.
|
22
|
+
#
|
23
|
+
class Client
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
# Create a client instance. This is used as a factory for endpoint
|
28
|
+
# instances which communicate with Resource implementations.
|
29
|
+
#
|
30
|
+
# == Overview
|
31
|
+
#
|
32
|
+
# Suppose you have Resources with only +public_actions+ so that no
|
33
|
+
# sessions are needed, with resource implementations running at host
|
34
|
+
# "test.com" on paths which follow downcase/pluralisation conventions.
|
35
|
+
# In this case, creating a Client instance can be as simple as:
|
36
|
+
#
|
37
|
+
# client = Hoodoo::Client.new(
|
38
|
+
# base_uri: 'http://test.com/',
|
39
|
+
# auto_session: false
|
40
|
+
# )
|
41
|
+
#
|
42
|
+
# Ask this client for an endpoint of Resource "Member" implementing
|
43
|
+
# version 2 of its interface:
|
44
|
+
#
|
45
|
+
# members = client.resource( :Member, 2 )
|
46
|
+
#
|
47
|
+
# Perform operations on the endpoints according to the methods in the
|
48
|
+
# base class - see these for details:
|
49
|
+
#
|
50
|
+
# * Hoodoo::Client::Endpoint#list
|
51
|
+
# * Hoodoo::Client::Endpoint#show
|
52
|
+
# * Hoodoo::Client::Endpoint#create
|
53
|
+
# * Hoodoo::Client::Endpoint#update
|
54
|
+
# * Hoodoo::Client::Endpoint#delete
|
55
|
+
#
|
56
|
+
# The above reference describes the basic approach for each call, with
|
57
|
+
# common parameters such as the query hash or body hash data described
|
58
|
+
# in the base class constructor, Hoodoo::Client::Endpoint#new.
|
59
|
+
#
|
60
|
+
# As an example, we could list records 50-79 inclusive of "Member"
|
61
|
+
# sorted by +created_at+ ascending, embedding an "account" for each,
|
62
|
+
# where field 'surname' matches 'Smith' - assuming there's an
|
63
|
+
# implementation of such a Resource interface available! - as follows:
|
64
|
+
#
|
65
|
+
# results = members.list(
|
66
|
+
# :offset => 50,
|
67
|
+
# :limit => 25,
|
68
|
+
# :sort => :created_at,
|
69
|
+
# :direction => :asc,
|
70
|
+
# :embeds => 'account',
|
71
|
+
# :search => { :surname => 'Smith' }
|
72
|
+
# )
|
73
|
+
#
|
74
|
+
# This will return a Hoodoo::Client::AugmentedArray. This is an Array
|
75
|
+
# subclass which will contain the (up to) 25 results from the above
|
76
|
+
# call and supports Hoodoo::Client::AugmentedArray#dataset_size which
|
77
|
+
# (if the called Resource endpoint implementation provides the
|
78
|
+
# information) gives the total size of the data set at the time of
|
79
|
+
# calling.
|
80
|
+
#
|
81
|
+
# The other 4 methods return a Hoodoo::Client::AugmentedHash. This is a
|
82
|
+
# Hash subclass. Both the Array and Hash subclasses provide a common
|
83
|
+
# standard way to handle errors. See the documentation of these classes
|
84
|
+
# for details; in brief, you _must_ _always_ check for errors before
|
85
|
+
# examining the Hash or Array data with a pattern such as this:
|
86
|
+
#
|
87
|
+
# if results.platform_errors.has_errors?
|
88
|
+
# # Examine results.platform_errors, which is a
|
89
|
+
# # Hoodoo::Errors instance, and deal with the contents.
|
90
|
+
# else
|
91
|
+
# # Treat 'results' as a Hash containing the Resource
|
92
|
+
# # data (String keys) or Array of Hashes of such data.
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# == Session management
|
96
|
+
#
|
97
|
+
# By default, the Hoodoo::Client constructor assumes you want automatic
|
98
|
+
# session management.
|
99
|
+
#
|
100
|
+
# If you want to use automatic sessions, a Resource endpoint which
|
101
|
+
# implements the Session Resource interface is required. This must
|
102
|
+
# accept a POST (+create+) action with a payload of two JSON fields:
|
103
|
+
# +caller_id+ and +authentication_secret+. It must return a Resource
|
104
|
+
# with an "id" value that contains the session ID to quote in future
|
105
|
+
# requests via the X-Session-ID HTTP header; or it should return an
|
106
|
+
# error if the Caller ID and/or authentication secret are incorrect.
|
107
|
+
#
|
108
|
+
# The Resource is assumed to live at the same base URI and/or be
|
109
|
+
# discovered by the same mechanism (e.g. by convention) as everything
|
110
|
+
# else you'll use the client instance for. For more about discovery
|
111
|
+
# related paramters, see later.
|
112
|
+
#
|
113
|
+
# You will need to provide the +caller_id+ and +authentication_secret+
|
114
|
+
# (as named parameter +caller_secret+) to the constructor. If the name
|
115
|
+
# of the Resource implementing the Session interface is not 'Session',
|
116
|
+
# or not at version 1, then you can also provide alternatives. For
|
117
|
+
# example, suppose we want to use automatic session management for
|
118
|
+
# Caller ID "0123" and secret "ABCD" via version 2 of "CustomSession":
|
119
|
+
#
|
120
|
+
# client = Hoodoo::Client.new(
|
121
|
+
# base_uri: 'http://test.com/',
|
122
|
+
# auto_session_resource: 'CustomSession',
|
123
|
+
# auto_session_version: 2,
|
124
|
+
# caller_id: '0123',
|
125
|
+
# caller_secret: 'ABCD'
|
126
|
+
# )
|
127
|
+
#
|
128
|
+
# Finally, you can manually supply a session ID externally for the
|
129
|
+
# X-Session-ID header through the +session_id+ parameter. This may be
|
130
|
+
# used in conjunction with auto-session management; in that case, the
|
131
|
+
# given session is used until it expires (a "platform.invalid_session"
|
132
|
+
# error is encountered), after which a new one will be obtained.
|
133
|
+
#
|
134
|
+
# == Discovery parameters
|
135
|
+
#
|
136
|
+
# The Client instance needs to be able to find the place where the
|
137
|
+
# requested Resource implementations are located, which it does using
|
138
|
+
# the Hoodoo::Services::Discovery framework. You should read the
|
139
|
+
# description of this framework to get a feel for how that works first.
|
140
|
+
#
|
141
|
+
# One of the following *named* parameters must be supplied in order to
|
142
|
+
# choose a discovery engine for finding Resource endpoints:
|
143
|
+
#
|
144
|
+
# +discoverer+:: The Client needs a *Discoverer* to map from resource
|
145
|
+
# names and versions to locations on the Internet of the
|
146
|
+
# actual resource endpoint implementation. Via the
|
147
|
+
# +discoverer+ parameter, you can explicitly pass a
|
148
|
+
# Hoodoo::Services::Discovery subclass instance
|
149
|
+
# customised to your own requirements. There are also
|
150
|
+
# convenience parameters available - see below - that
|
151
|
+
# create discoverer instances for you, covering common
|
152
|
+
# use cases. If provided, the +discoverer+ parameter
|
153
|
+
# takes precedence over any other parameters below.
|
154
|
+
#
|
155
|
+
# +base_uri+:: When given, Resource discovery is done by
|
156
|
+
# Hoodoo::Services::Discovery::ByConvention. The path
|
157
|
+
# that the by-convention discoverer creates is appended
|
158
|
+
# to the base URI to build the full URI at which a server
|
159
|
+
# implementing each requested Resource endpoint must be
|
160
|
+
# listening (else a 404 / 'platform.not_found' response
|
161
|
+
# arises). Specify as a String. If provided, the
|
162
|
+
# +base_uri+ parameter takes precedence over any other
|
163
|
+
# parameters below.
|
164
|
+
#
|
165
|
+
# +drb_uri+:: When given, Resource discovery is done by
|
166
|
+
# Hoodoo::Services::Discovery::ByDRb. A DRb service
|
167
|
+
# providing discovery data must be running at the given
|
168
|
+
# URI. Specify as a String. See
|
169
|
+
# Hoodoo::Services::Discovery::ByDRb::DRbServer and file
|
170
|
+
# +drb_server_start.rb+ for more.
|
171
|
+
#
|
172
|
+
# +drb_port+:: Instead of +drb_uri+, you can provide the port number
|
173
|
+
# of a DRb server on localhost. See
|
174
|
+
# Hoodoo::Services::Discovery::ByDRb for which of
|
175
|
+
# +drb_uri+ or +drb_port+ take precedence, if both are
|
176
|
+
# provided.
|
177
|
+
#
|
178
|
+
# As an example of using a custom Discoverer, consider a simple HTTP
|
179
|
+
# case with the +base_uri+ parameter. The default "by convention"
|
180
|
+
# discoverer pluralises all paths, but let's say you have exceptions
|
181
|
+
# for Version and Health singleton resources which you've elected to
|
182
|
+
# place on singular, not plural, paths. You will need to construct a
|
183
|
+
# custom discoverer with these exceptions. See the documentation for
|
184
|
+
# Hoodoo::Services::Discovery::ByConvention to understand the options
|
185
|
+
# passed in for the custom routing information.
|
186
|
+
#
|
187
|
+
# base_uri = 'https://api.test.com/'
|
188
|
+
#
|
189
|
+
# discoverer = Hoodoo::Services::Discovery::ByConvention.new(
|
190
|
+
# :base_uri => base_uri,
|
191
|
+
# :routing => {
|
192
|
+
# :Version => { 1 => '/v1/version' },
|
193
|
+
# :Health => { 1 => '/v1/health' }
|
194
|
+
# }
|
195
|
+
# )
|
196
|
+
#
|
197
|
+
# client = Hoodoo::Client.new(
|
198
|
+
# :discoverer => discoverer,
|
199
|
+
# # ...other options...
|
200
|
+
# )
|
201
|
+
#
|
202
|
+
# == Other parameters
|
203
|
+
#
|
204
|
+
# The following additional *named* parameters are all optional:
|
205
|
+
#
|
206
|
+
# +locale+:: The String given in Content-Language _and_
|
207
|
+
# Accept-Language HTTP headers for requests;
|
208
|
+
# default is "en-nz".
|
209
|
+
#
|
210
|
+
# +session_id+:: An optional session ID to be used for the
|
211
|
+
# initial X-Session-ID request header value.
|
212
|
+
#
|
213
|
+
# +auto_session+:: If +false+, automatic session management is
|
214
|
+
# disabled. Default is +true+.
|
215
|
+
#
|
216
|
+
# +auto_session_resource+:: Name of the Resource to use for automatic
|
217
|
+
# session management as a String or Symbol.
|
218
|
+
# Default is +"Session"+.
|
219
|
+
#
|
220
|
+
# +auto_session_version+:: Version of the Resource to use for
|
221
|
+
# automatic session management as an Integer.
|
222
|
+
# Default is 1.
|
223
|
+
#
|
224
|
+
# +caller_id+:: If using automatic session management, a
|
225
|
+
# Caller UUID must be provided. It is used
|
226
|
+
# as the +caller_id+ field's value in the
|
227
|
+
# POST (+create+) call to the session
|
228
|
+
# Resource endpoint.
|
229
|
+
#
|
230
|
+
# +caller_secret+:: If using automatic session management, a
|
231
|
+
# Caller authentication secret must be
|
232
|
+
# provide. It is used as the
|
233
|
+
# +authentication_secret+ field's value in
|
234
|
+
# the POST (+create+) call to the session
|
235
|
+
# Resource endpoint.
|
236
|
+
#
|
237
|
+
# If curious about the implementation details of automatic session
|
238
|
+
# management, see the Hoodoo::Client::Endpoints::AutoSession class's
|
239
|
+
# code.
|
240
|
+
#
|
241
|
+
def initialize( base_uri: nil,
|
242
|
+
drb_uri: nil,
|
243
|
+
drb_port: nil,
|
244
|
+
discoverer: nil,
|
245
|
+
|
246
|
+
locale: nil,
|
247
|
+
|
248
|
+
session_id: nil,
|
249
|
+
auto_session: :true,
|
250
|
+
auto_session_resource: 'Session',
|
251
|
+
auto_session_version: 1,
|
252
|
+
caller_id: nil,
|
253
|
+
caller_secret: nil )
|
254
|
+
|
255
|
+
@base_uri = base_uri
|
256
|
+
@drb_uri = drb_uri
|
257
|
+
@drb_port = drb_port
|
258
|
+
|
259
|
+
@locale = locale
|
260
|
+
|
261
|
+
@discoverer = if discoverer != nil
|
262
|
+
discoverer
|
263
|
+
elsif @base_uri != nil
|
264
|
+
Hoodoo::Services::Discovery::ByConvention.new(
|
265
|
+
:base_uri => @base_uri
|
266
|
+
)
|
267
|
+
elsif @drb_uri != nil || @drb_port != nil
|
268
|
+
Hoodoo::Services::Discovery::ByDRb.new(
|
269
|
+
:drb_uri => @drb_uri,
|
270
|
+
:drb_port => @drb_port
|
271
|
+
)
|
272
|
+
else
|
273
|
+
raise 'Hoodoo::Client: Please pass one of the "discoverer", "base_uri", "drb_uri" or "drb_port" parameters.'
|
274
|
+
end
|
275
|
+
|
276
|
+
# If doing automatic sessions, acquire a session creation endpoint
|
277
|
+
|
278
|
+
@session_id = session_id
|
279
|
+
@caller_id = caller_id
|
280
|
+
@caller_secret = caller_secret
|
281
|
+
|
282
|
+
if auto_session
|
283
|
+
@auto_session_endpoint = Hoodoo::Client::Endpoint.endpoint_for(
|
284
|
+
auto_session_resource,
|
285
|
+
auto_session_version,
|
286
|
+
{ :discoverer => @discoverer }
|
287
|
+
)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Get an endpoint instance which you can use for talking to a Resource.
|
292
|
+
# See the constructor for full information.
|
293
|
+
#
|
294
|
+
# You'll always get an endpoint instance back from this call. If an
|
295
|
+
# implementation of the given version of the given Resource cannot be
|
296
|
+
# contacted, you will only get a 404 ('platform.not_found') or 408
|
297
|
+
# ('platform.timeout') response when you try to make a call to it.
|
298
|
+
#
|
299
|
+
# +resource+:: Resource name as a Symbol or String (e.g. +:Purchase+).
|
300
|
+
#
|
301
|
+
# +version+:: Endpoint version as an Integer; optional; default is 1.
|
302
|
+
#
|
303
|
+
# +options+:: Optional options Hash (see below).
|
304
|
+
#
|
305
|
+
# The options Hash key/values are as follows:
|
306
|
+
#
|
307
|
+
# +locale+:: Locale string for request/response, e.g. "en-gb". Optional.
|
308
|
+
# If omitted, defaults to the locale set in this Client
|
309
|
+
# instance's constructor.
|
310
|
+
#
|
311
|
+
# OTHERS:: See Hoodoo::Client::Headers' +HEADER_TO_PROPERTY+. All
|
312
|
+
# such option keys _MUST_ be Symbols.
|
313
|
+
#
|
314
|
+
def resource( resource, version = 1, options = {} )
|
315
|
+
|
316
|
+
endpoint_options = {
|
317
|
+
:discoverer => @discoverer,
|
318
|
+
:session_id => @session_id,
|
319
|
+
:locale => options[ :locale ] || @locale
|
320
|
+
}
|
321
|
+
|
322
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
323
|
+
property = description[ :property ]
|
324
|
+
endpoint_options[ property ] = options[ property ] if options.has_key?( property )
|
325
|
+
end
|
326
|
+
|
327
|
+
endpoint = Hoodoo::Client::Endpoint.endpoint_for(
|
328
|
+
resource,
|
329
|
+
version,
|
330
|
+
endpoint_options
|
331
|
+
)
|
332
|
+
|
333
|
+
unless @auto_session_endpoint.nil?
|
334
|
+
remote_discovery_result = Hoodoo::Services::Discovery::ForRemote.new(
|
335
|
+
:resource => resource,
|
336
|
+
:version => version,
|
337
|
+
:wrapped_endpoint => endpoint
|
338
|
+
)
|
339
|
+
|
340
|
+
endpoint = Hoodoo::Client::Endpoint::AutoSession.new(
|
341
|
+
resource,
|
342
|
+
version,
|
343
|
+
:caller_id => @caller_id,
|
344
|
+
:caller_secret => @caller_secret,
|
345
|
+
:session_endpoint => @auto_session_endpoint,
|
346
|
+
:discovery_result => remote_discovery_result
|
347
|
+
)
|
348
|
+
end
|
349
|
+
|
350
|
+
return endpoint
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
end
|