Skip to content

Instantly share code, notes, and snippets.

@sebglazebrook
Last active February 4, 2018 00:40
Show Gist options
  • Save sebglazebrook/50aec324cfcb0b7f1c9a094580faa71a to your computer and use it in GitHub Desktop.
Save sebglazebrook/50aec324cfcb0b7f1c9a094580faa71a to your computer and use it in GitHub Desktop.
Controlling the API of modules in Ruby
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