Skip to content

Commit

Permalink
Extract Granite::Util to granite & use it in BasePrecondition (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrius Chamentauskas committed May 28, 2021
1 parent 6ad65c6 commit 514b7a0
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 5 deletions.
1 change: 1 addition & 0 deletions lib/granite.rb
Expand Up @@ -4,6 +4,7 @@
require 'granite/version'
require 'granite/config'
require 'granite/context'
require 'granite/util'

module Granite
def self.config
Expand Down
5 changes: 1 addition & 4 deletions lib/granite/action/preconditions/base_precondition.rb
Expand Up @@ -9,10 +9,7 @@ def initialize(*args, &block)
end

def execute!(context)
return if @options[:if] && !context.instance_exec(&@options[:if])
return if @options[:unless] && context.instance_exec(&@options[:unless])

_execute(context)
_execute(context) if context.conditions_satisfied?(@options)
end

private
Expand Down
1 change: 1 addition & 0 deletions lib/granite/base.rb
Expand Up @@ -18,6 +18,7 @@ module Base
include ActiveData::Model::Primary
include ActiveModel::Validations::Callbacks

include Granite::Util
include Granite::Translations
include Granite::Represents
end
Expand Down
51 changes: 51 additions & 0 deletions lib/granite/util.rb
@@ -0,0 +1,51 @@
module Granite
module Util
extend ActiveSupport::Concern

# Evaluates value and returns result based on what was passed:
# - if Proc was passed, then executes it in context of self
# - if Symbol was passed, then calls a method with that name and returns result
# - otherwise just returns the value itself
# @param value [Object] value to evaluate
# @return [Object] result of evaluation
def evaluate(value)
case value
when Proc
evaluate_proc(value)
when Symbol
evaluate_symbol(value)
else
value
end
end

# Evaluates `if` or `unless` conditions present in the supplied
# `options` being it a symbol or callable.
#
# @param [Hash] options The method options to evaluate.
# @option options :if method name or callable
# @option options :unless method name or callable
# @return [Boolean] whether conditions are satisfied
def conditions_satisfied?(options)
fail ArgumentError, 'You cannot specify both if and unless' if options.key?(:if) && options.key?(:unless)

if options.key?(:if)
evaluate(options[:if])
elsif options.key?(:unless)
!evaluate(options[:unless])
else
true
end
end

private

def evaluate_proc(value)
instance_exec(&value)
end

def evaluate_symbol(value)
__send__(value)
end
end
end
2 changes: 1 addition & 1 deletion lib/granite/version.rb
@@ -1,3 +1,3 @@
module Granite
VERSION = '0.9.7'.freeze
VERSION = '0.9.8'.freeze
end
65 changes: 65 additions & 0 deletions spec/lib/granite/util_spec.rb
@@ -0,0 +1,65 @@
RSpec.describe Granite::Util do
subject(:action) { DummyAction.new('John') }

before do
stub_class(:DummyAction, Object) do
include Granite::Util

attr_accessor :name

def initialize(name)
@name = name
end
end
end

describe '#evaluate' do
subject { action.evaluate(target) }
let(:target) { 'Peter' }

it { is_expected.to eq('Peter') }

context 'when symbol is passed' do
let(:target) { :name }

it { is_expected.to eq('John') }
end

context 'when lambda is passed' do
let(:target) { -> { name } }

it { is_expected.to eq('John') }
end
end

describe '#conditions_satisfied?' do
subject { action.conditions_satisfied?(**conditions) }
let(:conditions) { {if: -> { name == 'John' }} }

it { is_expected.to be_truthy }

context 'when if condition is satisfied' do
before { action.name = 'Peter' }

it { is_expected.to be_falsey }
end

context 'when unless condition is passed' do
let(:conditions) { {unless: :name} }

it { is_expected.to be_falsey }
end

context 'when no condition is passed' do
let(:conditions) { {} }

it { is_expected.to be_truthy }
end

context 'when both if & unless are passed' do
let(:conditions) { {if: :name, unless: :name} }

it { expect { subject }.to raise_error(ArgumentError) }
end
end
end

0 comments on commit 514b7a0

Please sign in to comment.