aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib/action_web_service/api/base.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionwebservice/lib/action_web_service/api/base.rb')
-rw-r--r--actionwebservice/lib/action_web_service/api/base.rb129
1 files changed, 129 insertions, 0 deletions
diff --git a/actionwebservice/lib/action_web_service/api/base.rb b/actionwebservice/lib/action_web_service/api/base.rb
new file mode 100644
index 0000000000..952c6baa0d
--- /dev/null
+++ b/actionwebservice/lib/action_web_service/api/base.rb
@@ -0,0 +1,129 @@
+module ActionWebService # :nodoc:
+ module API # :nodoc:
+ # A web service API class specifies the methods that will be available for
+ # invocation for an API. It also contains metadata such as the method type
+ # signature hints.
+ #
+ # It is not intended to be instantiated.
+ #
+ # It is attached to web service implementation classes like
+ # ActionWebService::Base and ActionController::Base derivatives by using
+ # ClassMethods#web_service_api.
+ class Base
+ # Whether to transform the public API method names into camel-cased names
+ class_inheritable_option :inflect_names, true
+
+ # If present, the name of a method to call when the remote caller
+ # tried to call a nonexistent method. Semantically equivalent to
+ # +method_missing+.
+ class_inheritable_option :default_api_method
+
+ # Disallow instantiation
+ private_class_method :new, :allocate
+
+ class << self
+ # API methods have a +name+, which must be the Ruby method name to use when
+ # performing the invocation on the web service object.
+ #
+ # The signatures for the method input parameters and return value can
+ # by specified in +options+.
+ #
+ # A signature is an array of one or more parameter specifiers.
+ # A parameter specifier can be one of the following:
+ #
+ # * A symbol or string of representing one of the Action Web Service base types.
+ # See ActionWebService::Signature for a canonical list of the base types.
+ # * The Class object of the parameter type
+ # * A single-element Array containing one of the two preceding items. This
+ # will cause Action Web Service to treat the parameter at that position
+ # as an array containing only values of the given type.
+ # * A Hash containing as key the name of the parameter, and as value
+ # one of the three preceding items
+ #
+ # If no method input parameter or method return value signatures are given,
+ # the method is assumed to take no parameters and/or return no values of
+ # interest, and any values that are received by the server will be
+ # discarded and ignored.
+ #
+ # Valid options:
+ # [<tt>:expects</tt>] Signature for the method input parameters
+ # [<tt>:returns</tt>] Signature for the method return value
+ # [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value
+ def api_method(name, options={})
+ validate_options([:expects, :returns, :expects_and_returns], options.keys)
+ if options[:expects_and_returns]
+ expects = options[:expects_and_returns]
+ returns = options[:expects_and_returns]
+ else
+ expects = options[:expects]
+ returns = options[:returns]
+ end
+ expects = canonical_signature(expects)
+ returns = canonical_signature(returns)
+ if expects
+ expects.each do |param|
+ klass = WS::BaseTypes.canonical_param_type_class(param)
+ klass = klass[0] if klass.is_a?(Array)
+ if klass.ancestors.include?(ActiveRecord::Base)
+ raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects")
+ end
+ end
+ end
+ name = name.to_sym
+ public_name = public_api_method_name(name)
+ info = { :expects => expects, :returns => returns }
+ write_inheritable_hash("api_methods", name => info)
+ write_inheritable_hash("api_public_method_names", public_name => name)
+ end
+
+ # Whether the given method name is a service method on this API
+ def has_api_method?(name)
+ api_methods.has_key?(name)
+ end
+
+ # Whether the given public method name has a corresponding service method
+ # on this API
+ def has_public_api_method?(public_name)
+ api_public_method_names.has_key?(public_name)
+ end
+
+ # The corresponding public method name for the given service method name
+ def public_api_method_name(name)
+ if inflect_names
+ name.to_s.camelize
+ else
+ name.to_s
+ end
+ end
+
+ # The corresponding service method name for the given public method name
+ def api_method_name(public_name)
+ api_public_method_names[public_name]
+ end
+
+ # A Hash containing all service methods on this API, and their
+ # associated metadata.
+ def api_methods
+ read_inheritable_attribute("api_methods") || {}
+ end
+
+ private
+ def api_public_method_names
+ read_inheritable_attribute("api_public_method_names") || {}
+ end
+
+ def validate_options(valid_option_keys, supplied_option_keys)
+ unknown_option_keys = supplied_option_keys - valid_option_keys
+ unless unknown_option_keys.empty?
+ raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}")
+ end
+ end
+
+ def canonical_signature(signature)
+ return nil if signature.nil?
+ signature.map{|spec| WS::BaseTypes.canonical_param_type_spec(spec)}
+ end
+ end
+ end
+ end
+end