Reputation: 524
I have a large backend API for my native app that's built in Sinatra, that also serves some admin web pages. I'm trying to dry up the codebase and refactor code into classes inside the lib directory.
My API clients expect a status and a message, such as 200 OK, or 404 Profile Not Found. I'd usually do this with something like halt 404, 'Profile Not Found'
.
What's the easiest way of halt
ing with an HTTP status code and a message from inside a class?
Old Wet Code
post '/api/process_something'
halt 403, 'missing profile_id' unless params[:profile_id].present?
halt 404, 'offer not found' unless params[:offer_id].present?
do_some_processing
200
end
New Dry Code
post '/api/process_something'
offer_manager = OfferManager.new
offer_manager.process_offer(params: params)
end
offer_manager.rb
class OfferManager
def process_offer(params:)
# halt 403, 'missing profile_id' unless params[:profile_id].present?
# halt 404, 'offer not found' unless params[:offer_id].present?
# halt doesn't work from in here
do_some_processing
200
end
end
Upvotes: 1
Views: 1306
Reputation: 15967
This question is probably better for CodeReview but one approach you can see in an OO design here is a 'halt' path and a 'happy' path. Your class just needs to implement a few methods to help this be consistent across all your sinatra routes and methods.
Here's one approach, and it would be easy to adopt this kind of interface across other classes using inheritance.
post '/api/process_something' do
offer_manager = OfferManager.new(params)
# error guard clause
halt offer_manager.status, offer_manager.halt_message if offer_manager.halt?
# validations met, continue to process
offer_manager.process_offer
# return back 200
offer_manager.status
end
class OfferManager
attr_reader :status, :params, :halt_message
def initialize(params)
@params = params
validate_params
end
def process_offer
do_some_processing
end
def halt?
# right now we just know missing params is one error to halt on but this is where
# you could implement more business logic if need be
missing_params?
end
private
def validate_params
if missing_params?
@status = 404
@halt_message = "missing #{missing_keys.join(", ")} key(s)"
else
@status = 200
end
end
def do_some_processing
# go do other processing
end
def missing_params?
missing_keys.size > 0
end
def missing_keys
expected_keys = [:profile_id, :offer_id]
params.select { |k, _| !expected_keys.has_key?(k) }
end
end
Upvotes: 1