Last active
February 4, 2018 00:40
-
-
Save sebglazebrook/50aec324cfcb0b7f1c9a094580faa71a to your computer and use it in GitHub Desktop.
Controlling the API of modules in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "payment_service/authorize_payment" # This defines PaymentService::AuthorizePayment class | |
require "payment_service/authorization_error" # This defines PaymentService::AuthorizatonError class | |
require "payment_service/successful_authorization_workflow" # This defines PaymentService::SuccessfulAuthorizationWorkflow class | |
require "payment_service/payment_repository" # This defines PaymentService::PaymentRepository class | |
module PaymentService | |
def self.authorize_payment(token) | |
response = AuthorizePayment.new(token).execute | |
if response.success? | |
SuccessfulAuthorizationWorkflow.new(response.body) | |
else | |
AuthorizationError.new(response.body) | |
end | |
end | |
# The below makes all constances to the module private and only accessible from the module itself | |
# unless you do ruby hackery to bypass it | |
private_constant(*self.constants) | |
end | |
token = "my-awesome-token" | |
PaymentService.authorize_payment(token) # => this works | |
PaymentService::AuthorizePayment.new(token).execute) # => this doesn't work as it's private to the module | |
# This way to can control your external API and clarify the boundry between domains | |
# Inside the PaymentService a user could be differnt to a user in the main application domain | |
# The thing to watch out for is sending in/using objects from a different domain | |
# For example if you want to fetch a payment for a user, don't send in the main application domain's user | |
# use the adapter pattern to adapt the application domain's user to the PaymentService domain's user | |
module PaymentService | |
def self.payments_for_user(user) | |
PaymentRepository.for_user(user) | |
end | |
end | |
# Now let's call if from the main application's domain | |
user = User.first # fetches a user from the main application's domain | |
payment_service_user = PaymentServiceUserAdapter.convert(user) # <= this returns a user that suits the interface of the PaymentService | |
PaymentService.payments_for_user(payment_service_user) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment