require 'active_remote/serializers/protobuf'

module ActiveRemote
  module RPC
    def self.included(klass)
      klass.class_eval do
        extend ::ActiveRemote::RPC::ClassMethods
        include ::ActiveRemote::Serializers::Protobuf
      end
    end

    module ClassMethods
      # Return a protobuf request object for the given rpc request.
      #
      def request(rpc_method, attributes)
        message_class = request_type(rpc_method)
        build_message(message_class, attributes)
      end

      # Return the class applicable to the request for the given rpc method.
      #
      def request_type(rpc_method)
        service_class.rpcs[_service_name][rpc_method].request_type
      end
    end

    # Invoke an RPC call to the service for the given rpc method.
    # Returns a boolean indicating success or failure.
    #
    def _execute(rpc_method, request_args)
      @last_request = request_args
      @last_request = request(rpc_method, request_args) if request_args.is_a?(Hash)

      _service_class.client.__send__(rpc_method, @last_request) do |c|

        # In the event of service failure, raise the error.
        c.on_failure do |error|
          raise ActiveRemoteError, error.message
        end

        # In the event of service success, assign the response.
        c.on_success do |response|
          @last_response = response
        end
      end
    end

  private

    # Return a protobuf request object for the given rpc call.
    def request(rpc_method, attributes)
      self.class.request(rpc_method, attributes)
    end
  end
end

require 'active_remote/serializers/protobuf'

module ActiveRemote
  module RPC
    def self.included(klass)
      klass.class_eval do
        extend ::ActiveRemote::RPC::ClassMethods
        include ::ActiveRemote::Serializers::Protobuf
      end
    end

    module ClassMethods
      # Return a protobuf request object for the given rpc request.
      #
      def request(rpc_method, attributes)
        message_class = request_type(rpc_method)
        build_message(message_class, attributes)
      end

      # Return the class applicable to the request for the given rpc method.
      #
      def request_type(rpc_method)
        service_class.rpcs[service_class][rpc_method].request_type
      end
    end

    # Invoke an RPC call to the service for the given rpc method.
    # Returns a boolean indicating success or failure.
    #
    def _execute(rpc_method, request_args)
      @last_request = request_args
      @last_request = request(rpc_method, request_args) if request_args.is_a?(Hash)

      _service_class.client.__send__(rpc_method, @last_request) do |c|

        # In the event of service failure, raise the error.
        c.on_failure do |error|
          raise ActiveRemoteError, error.message
        end

        # In the event of service success, assign the response.
        c.on_success do |response|
          @last_response = response
        end
      end
    end

  private

    # Return a protobuf request object for the given rpc call.
    def request(rpc_method, attributes)
      self.class.request(rpc_method, attributes)
    end
  end
end

Use the service class when inspecting RPC endpoints, not the service name.
Use the service class when inspecting RPC endpoints, not the service name.