Class: BlogRPC::BasicHandler

Inherits:
XMLRPC::Service::BasicInterface
  • Object
show all
Defined in:
lib/blogrpc/basic_handler.rb

Overview

A very simple RPC interface where you can declare methods by calling rpc “methodThis” :in => [:bool], :out => :bool { truth } and it creates method_this(some_bool) in Ruby and wires it in

Direct Known Subclasses

SampleHandler

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(prefix = nil) ⇒ BasicHandler

The standard initializer for such a service accepts a prefix, but we will override that



33
34
35
# File 'lib/blogrpc/basic_handler.rb', line 33

def initialize(prefix = nil)
  @prefix = 'mt'
end

Instance Attribute Details

#envObject

Will contain the Rack application environment



29
30
31
# File 'lib/blogrpc/basic_handler.rb', line 29

def env
  @env
end

Class Method Details

.rpc(methName, options, &blk) ⇒ Object

Generate an RPC method uisng a block. Accepts two parameters :in is for the input argument types (should be array) and :out for what it will return. The block defines the method.



63
64
65
66
67
68
69
70
71
# File 'lib/blogrpc/basic_handler.rb', line 63

def self.rpc(methName, options, &blk)
  ruby_method = methName.split(/\./).pop.gsub(/([A-Z])/) { |m| '_' + m.downcase }
  define_method(ruby_method, &blk)
  
  options = {:in => []}.merge(options)
  iface, method = methName.split(/\./)
  @rpc_methods_and_signatures ||= {}
  @rpc_methods_and_signatures[ruby_method] = [ methName, "#{options[:out]} #{method}(#{options[:in].join(', ')})" ]
end

.rpc_methods_and_signaturesObject

Will return a union of all of the methods defined using rpc() in this class and all of it’s ancestors.



39
40
41
42
43
44
45
46
47
# File 'lib/blogrpc/basic_handler.rb', line 39

def self.rpc_methods_and_signatures
  # Climb up the class chain
  methods_and_signatures_in_ancestor_chain = {}
  ancestors.reverse.each do | ancestor_module |
    in_ancestor = ancestor_module.instance_variable_get('@rpc_methods_and_signatures') || {}
    methods_and_signatures_in_ancestor_chain.merge!(in_ancestor)
  end
  methods_and_signatures_in_ancestor_chain.merge(@rpc_methods_and_signatures || {})
end

Instance Method Details

#get_methods(obj, delim) ⇒ Object

This is the magic wand. The docs of XMLRPC never explain where the fuck does obj actually ever come from, moreover - here WE are the object (the server sends a nil, anyways). What is important is that this method returns a set of method signatures that XMLRPC will call on our object when processing the request. Delim is omitted since internally we differentiate our namespaced methods anyway (mt. prefix for MovableType and wp. for Wordpress..)



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/blogrpc/basic_handler.rb', line 78

def get_methods(obj, delim)
  meths = []
  self.class.rpc_methods_and_signatures.each_pair do | ruby_method, details |
    # And bind the method
    meths.unshift [
      details[0], # method name (in XMLRPC terms) including prefix, like "mt.getPost"
      method(ruby_method).to_proc, # the method itself, a callable Proc
      details[1], # signature, like "getPost(string, string, int)"
      (details[2] || "Just a method") # method help
    ]
  end
  meths
end

#handle_request(post_payload) ⇒ Object

Pass your XML request here and get the result (the request is the raw HTTP POST body, the way to get to it differs per framework/server)

huge_xml_blob = MiniInterface.new.handle_request(StringIO.new(post_data))


54
55
56
57
58
# File 'lib/blogrpc/basic_handler.rb', line 54

def handle_request(post_payload)
  s = XMLRPC::BasicServer.new
  s.add_handler self
  s.process(post_payload.respond_to?(:read) ? post_payload : StringIO.new(post_payload) )
end