Created
October 27, 2017 12:57
-
-
Save joshuapaling/e57b59aab5afd1257ed56232e5016a97 to your computer and use it in GitHub Desktop.
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
# Here's the code that's a candidate for refactor, I'm just trying | |
# to get a sense of if dry monads are a good fit or if this isn't really | |
# complex or nested-ifs enough to make it really worth it. | |
# I'm more just checking out dry monads for fun (and potential profit!) rather than | |
# trying to solve an immediate pain point. | |
# | |
# Context is: it's an Employee Relationship Management system. | |
# Employees earn points for doing things. Periodically, the company holds | |
# a "flash sale" where they can redeem those points for rewards. | |
# | |
# An employee clicks "redeem". It: | |
# a) checks that they can in fact redeem the reward (there's a sale on, etc) | |
# b) adds the reward | |
# c) Rewarders::RedeemPointsRewarder basically just adds a transaction record | |
# to deduct points (rewards points are event sourced) | |
# d) it returns the employee's updated profile (which will include their new points balance) | |
# and their recent rewards transactions (which will include the most recent one) | |
# That last step's a bit clunky - creating a reward and returning different data - | |
# the reasoning for it is more clear when you see the UI, | |
# but that's kinda beside the point in this context. | |
# I'm not expecting you to re-write this or anything, just even a | |
# "yeah, try refactor that with dry monads" | |
# or "nah, bad example" would be great. | |
# | |
# FYI, I don't really care about all the error messages - if I just return | |
# the first one that comes up, that's enough. | |
# | |
# I've never used Monads before, in any context. | |
# | |
# Aside: if you have opinions on if it's OK for a rest-ful-ish API to return | |
# updated records that aren't the same resource/type as the endpoint itself | |
# (ie, in this case creating a reward_order and returning a `profile` and `recent_points`, which is the employee's last 5 transactions) | |
# because it's the easiest thing for the client to get back and save it making | |
# more API calls, I'd be keen to hear them! Was saving that as a question to | |
# ask peeps next Ruby meetup. | |
module API | |
class RewardOrdersController < API::BaseController | |
def create | |
errors = [] | |
@flash_sale = FlashSale.current_sale | |
if !@flash_sale | |
errors << 'Cannot order rewards when no sale is on' | |
end | |
# Employees under performance review cannot receive points | |
if !current_employee.no_performance_issues? | |
errors << 'Cannot order rewards when there are performance issues' | |
end | |
# Deboarding / inactive employees can't receive points | |
if current_employee.deboarding? || current_employee.inactive? | |
errors << 'Cannot order rewards if deboarding or inactive' | |
end | |
employee = Employee.select("id, #{Employee.rewards_points_balance_sql} as reward_points_balance").find(current_employee.id) | |
reward = Reward.find(reward_order_params[:reward_id]) | |
if employee.reward_points_balance < reward.cost_in_points | |
errors << 'Cannot order reward - insufficient points' | |
end | |
if errors.empty? | |
order = RewardOrder.new(reward_order_params) | |
order.employee = current_employee | |
order.flash_sale = @flash_sale | |
order.save! | |
Rewarders::RedeemPointsRewarder.new(current_employee.id).call(order) | |
# re-fetch with updated points balance | |
employee = Employee.find_for_profile(current_employee.id) | |
employee_json = ActionController::Base.new.view_context.render(template: "api/profiles/show.json.jbuilder", locals: { employee: employee }) | |
result = { | |
recent_points: RewardPointTrx.recent_points(current_employee.id), | |
profile: JSON.parse(employee_json) | |
} | |
render json: result, status: 201 | |
else | |
render json: errors, status: 422 | |
end | |
end | |
private | |
# Never trust parameters from the scary internet, only allow the white list through. | |
def reward_order_params | |
params.permit(:reward_id) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment