ChaelCodes/HuntersKeepers

View on GitHub
app/services/improve_hunter.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

# This is the base class for improving a Hunter. All
# services that utilize this class belong in /services/improves
class ImproveHunter
  def self.for(improvement)
    return ImproveHunter unless improvement.type
    improvement.type.gsub('Improvements', 'Improves').constantize
  end

  # This will initialize @hunters_improvement,
  # @hunter, @improvement, and @improvable.
  # Any setup that all improve services need will be
  # handled here.
  # @param hunters_improvement
  def initialize(hunters_improvement)
    @hunters_improvement = hunters_improvement
    @improvement = hunters_improvement.improvement
    @hunter = hunters_improvement.hunter
    @improvable = hunters_improvement.improvable
  end

  # This method is overridden and used to
  # update and improve the hunter in subclasses
  # returns false if the hunter/improvement/improvable
  # combination is invalid
  # returns a truthy value otherwise
  def improve
    return false unless valid?
    true
  end

  # All improve services should extend this method
  # to apply their own constraints, and if they extend
  # the last check should be `@hunters_improvement.errors.none?`
  # This validations checks the hunter is authorized to use
  # the improvement, and that the hunter is of sufficient level
  # for advanced improvements.
  def valid?
    check(:hunter_playbook_mismatch?, :hunter,
          "does not match improvement playbook: #{@improvement.playbook.name}")
    check(:hunter_not_advanced?, :hunter,
          'is not qualified for advanced improvements')
    @hunters_improvement.errors.none?
  end

  def hunter_not_advanced?
    @improvement.advanced && !Improvement.advanced_eligible?(@hunter)
  end

  def hunter_playbook_mismatch?
    @hunter.playbook != @improvement.playbook
  end

  def check(check, attribute, message)
    @hunters_improvement.errors.add(attribute, message) if send check
  end
end