Skip to content

Instantly share code, notes, and snippets.

@vitaly-pushkar
Last active November 27, 2020 05:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vitaly-pushkar/ec86b0149500f6441b3d025185d01bcd to your computer and use it in GitHub Desktop.
Save vitaly-pushkar/ec86b0149500f6441b3d025185d01bcd to your computer and use it in GitHub Desktop.
From the blog post "Error Handling with Either Monads in Ruby"
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
@wbotelhos
Copy link

I think the user.update(data) should be in place of the user.save, since update already saves the object and returns a boolean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment