From e6c14f19036a9211b7abfc1f11f14f3dc6335dd4 Mon Sep 17 00:00:00 2001 From: Thibault Jouan Date: Sat, 3 Aug 2013 14:45:14 +0000 Subject: [PATCH] Implement basic task actions API: * Add Action base class; * Implement Task::DSL.define_action(keyword, klass); * Add Task::DSL#actions accessor; * Apply task DSL actions when Task instances are evaluated. --- lib/producer/core.rb | 1 + lib/producer/core/action.rb | 12 +++++++++++ lib/producer/core/task.rb | 4 +++- lib/producer/core/task/dsl.rb | 14 ++++++++++++- spec/producer/core/action_spec.rb | 21 +++++++++++++++++++ spec/producer/core/task/dsl_spec.rb | 32 +++++++++++++++++++++++++++++ spec/producer/core/task_spec.rb | 11 +++++++++- 7 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 lib/producer/core/action.rb create mode 100644 spec/producer/core/action_spec.rb diff --git a/lib/producer/core.rb b/lib/producer/core.rb index c268636..3e8ceb0 100644 --- a/lib/producer/core.rb +++ b/lib/producer/core.rb @@ -1,3 +1,4 @@ +require 'producer/core/action' require 'producer/core/cli' require 'producer/core/env' require 'producer/core/errors' diff --git a/lib/producer/core/action.rb b/lib/producer/core/action.rb new file mode 100644 index 0000000..d4f4bd2 --- /dev/null +++ b/lib/producer/core/action.rb @@ -0,0 +1,12 @@ +module Producer + module Core + class Action + attr_accessor :env, :arguments + + def initialize(env, *args) + @env = env + @arguments = args + end + end + end +end diff --git a/lib/producer/core/task.rb b/lib/producer/core/task.rb index 0c97cd7..5e7440d 100644 --- a/lib/producer/core/task.rb +++ b/lib/producer/core/task.rb @@ -9,7 +9,9 @@ module Producer end def evaluate(env) - DSL.new(&@block).evaluate(env) + dsl = DSL.new(&@block) + dsl.evaluate(env) + dsl.actions.map(&:apply) end end end diff --git a/lib/producer/core/task/dsl.rb b/lib/producer/core/task/dsl.rb index 227182d..389425f 100644 --- a/lib/producer/core/task/dsl.rb +++ b/lib/producer/core/task/dsl.rb @@ -2,11 +2,23 @@ module Producer module Core class Task class DSL + class << self + def define_action(keyword, klass) + define_method(keyword) do |*args| + @actions << klass.new(@env, *args) + end + end + end + + attr_accessor :actions + def initialize(&block) - @block = block + @block = block + @actions = [] end def evaluate(env) + @env = env instance_eval &@block rescue ConditionNotMetError rescue NameError => e diff --git a/spec/producer/core/action_spec.rb b/spec/producer/core/action_spec.rb new file mode 100644 index 0000000..848faf3 --- /dev/null +++ b/spec/producer/core/action_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +module Producer::Core + describe Action do + let(:env) { double 'env' } + let(:arguments) { [:some, :arguments] } + subject(:action) { Action.new(env, *arguments) } + + describe '#env' do + it 'returns the assigned env' do + expect(action.env).to eq env + end + end + + describe '#arguments' do + it 'returns the assigned arguments' do + expect(action.arguments).to eq arguments + end + end + end +end diff --git a/spec/producer/core/task/dsl_spec.rb b/spec/producer/core/task/dsl_spec.rb index bf7cc37..0fde620 100644 --- a/spec/producer/core/task/dsl_spec.rb +++ b/spec/producer/core/task/dsl_spec.rb @@ -2,9 +2,23 @@ require 'spec_helper' module Producer::Core describe Task::DSL do + let(:block) { proc { } } let(:env) { double('env') } subject(:dsl) { Task::DSL.new &block } + describe '.define_action' do + it 'defines a new action keyword' do + Task::DSL.define_action(:some_action, Object) + expect(dsl).to respond_to :some_action + end + end + + describe '#initialize' do + it 'has no action' do + expect(dsl.actions).to eq [] + end + end + describe '#evaluate' do let(:block) { proc { throw :task_code } } @@ -13,6 +27,24 @@ module Producer::Core .to throw_symbol :task_code end + context 'when a defined keyword action is called' do + let(:some_action_class) { Class.new(Action) } + let(:block) { proc { some_action } } + + before do + Task::DSL.define_action(:some_action, some_action_class) + dsl.evaluate(env) + end + + it 'registers the action' do + expect(dsl.actions.first).to be_an Action + end + + it 'provides the env to the registered action' do + expect(dsl.actions.first.env).to eq env + end + end + context 'when given block is invalid' do it 'raises a TaskEvaluationError on NameError' do dsl = Task::DSL.new { invalid_action } diff --git a/spec/producer/core/task_spec.rb b/spec/producer/core/task_spec.rb index ff55340..c5856b7 100644 --- a/spec/producer/core/task_spec.rb +++ b/spec/producer/core/task_spec.rb @@ -21,11 +21,20 @@ module Producer::Core end it 'evaluates the task DSL sandbox' do - dsl = double('task dsl') + dsl = double('task DSL').as_null_object allow(Task::DSL).to receive(:new) { dsl } expect(dsl).to receive(:evaluate).with(env) task.evaluate(env) end + + it 'applies DSL sandbox actions' do + dsl = double('task DSL').as_null_object + allow(Task::DSL).to receive(:new) { dsl } + action = double('action') + allow(dsl).to receive(:actions) { [action] } + expect(action).to receive(:apply) + task.evaluate(env) + end end end end