Skip to content

Commit

Permalink
Look for handlers in both the fully-qualified namespace, or root name…
Browse files Browse the repository at this point in the history
…space.

Many projects only ever use services in one namespace, but we'll respect them if you want them.
  • Loading branch information
danielmorrison committed Sep 12, 2024
1 parent f8b5d53 commit 568066b
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 2 deletions.
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,26 @@ end

Each handler method should return the appropriate Protobuf, or a `Twirp::Error`.

TODO: Give more examples of both
#### Packages and Namespacing

Handlers can live in directories that reflect the service's package. For example, `haberdasher.proto` defines:

```protobuf
package twirp.example.haberdasher;
```

You can use the full path, or because many projects have only one namespace, we also let you skip the namespace for simplicity:

We look for the handler in either location:

`app/handlers/twirp/example/haberdasher/haberdasher_service_handler.rb` defines `Twirp::Example::Haberdasher::HaberdasherServiceHandler`

or

`app/handlers/haberdasher_service_handler.rb` defines `HaberdasherServiceHandler`


TODO: Give more examples of handlers

### Familiar Callbacks

Expand Down
8 changes: 7 additions & 1 deletion lib/twirp/rails/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ module Twirp
module Rails
class Dispatcher
def initialize(service_class)
@service_handler = "#{service_class.service_name}Handler".constantize
# Check for a handler in the service's namespace, or in the root namespace
# e.g. Twirp::Example::Cobbler::CobblerHandler or ::CobblerHandler
@service_handler = if Object.const_defined?("#{service_class.module_parent}::#{service_class.service_name}Handler")
"#{service_class.module_parent}::#{service_class.service_name}Handler".constantize
else
"#{service_class.service_name}Handler".constantize
end
end

def respond_to_missing?(method, *)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Twirp
module Example
module Cobbler
class CobblerHandler < Twirp::Rails::Handler
def make_shoe
# We can return a Twirp::Error when appropriate
if request.inches < 12
return Twirp::Error.invalid_argument("is too small", argument: "inches")
end

# Build the reponse
Twirp::Example::Cobbler::Shoe.new(
inches: request.inches,
name: "Pork Pie",
color: "Tan"
)
end
end
end
end
end
20 changes: 20 additions & 0 deletions spec/rails_app/lib/twirp/example/cobbler/cobbler_pb.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions spec/rails_app/lib/twirp/example/cobbler/cobbler_twirp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

# Generated by the protoc-gen-twirp_ruby gem v1.1.1. DO NOT EDIT!
# source: twirp/example/cobbler/cobbler.proto

require "twirp"
require_relative "cobbler_pb"

module Twirp
module Example
module Cobbler
class CobblerService < ::Twirp::Service
package "twirp.example.cobbler"
service "Cobbler"
rpc :MakeShoe, Size, Shoe, ruby_method: :make_shoe
end

class CobblerClient < ::Twirp::Client
client_for CobblerService
end
end
end
end
23 changes: 23 additions & 0 deletions spec/rails_app/proto/twirp/example/cobbler/cobbler.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// A close copy of haberdasher.proto
// We're putting this in /proto/twirp/example/ so that we can test namespace handling
syntax = "proto3";

package twirp.example.cobbler;

// Cobbler service makes shoes for clients.
service Cobbler {
// MakeShoe produces a shoe of mysterious, randomly-selected color!
rpc MakeShoe(Size) returns (Shoe);
}

// Size of a Shoe, in inches.
message Size {
int32 inches = 1; // must be > 0
}

// A Shoe is a piece of footwear made by a Cobbler.
message Shoe {
int32 inches = 1;
string color = 2; // anything but "invisible"
string name = 3; // i.e. "oxford"
}

0 comments on commit 568066b

Please sign in to comment.