Last active
November 27, 2020 05:13
-
-
Save vitaly-pushkar/ec86b0149500f6441b3d025185d01bcd to your computer and use it in GitHub Desktop.
From the blog post "Error Handling with Either Monads 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
class UserUpdater | |
include Dry::Monads[:result] | |
attr_reader :user_model, :mailer | |
def initialize(user_model, mailer) | |
@user_model = user_model | |
@mailer = mailer | |
end | |
# The main method in this class. Ignore the "Pyramid of Doom" for now. | |
def call(fields) | |
validate_fields(fields).bind do |fields| | |
validate_email(fields['email']).bind do |email| | |
find_user(fields['id']).bind do |user| | |
update_user(user, {name: fields['name'], email: fields['email']}).bind do |user| | |
send_email(user, :profile_updated).bind do |sent| | |
Success(user) | |
end | |
end | |
end | |
end | |
end | |
end | |
private | |
# Keeping validations and other methods here simple for the purpose of this example | |
def validate_fields(fields) | |
if fields['name'] && fields['email'] | |
Success(fields) | |
else | |
Failure(:missing_fields) | |
end | |
end | |
def validate_email(email) | |
if email =~ URI::MailTo::EMAIL_REGEXP | |
Success(email) | |
else | |
Failure(:invalid_email) | |
end | |
end | |
def find_user(id) | |
user = user_model.find_by(id: id) | |
if user | |
Success(user) | |
else | |
Failure(:user_not_found) | |
end | |
end | |
def update_user(user, data) | |
user.update(data) | |
if user.save | |
Success(user) | |
else | |
Failure(:user_update_failed) | |
end | |
end | |
def send_email(email, reason) | |
result = mailer.deliver!(email, template: reason) | |
if result | |
Success() | |
else | |
Failure(:send_email_failed) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think the
user.update(data)
should be in place of theuser.save
, since update already saves the object and returns a boolean.