diff options
author | John Keiser <john@johnkeiser.com> | 2015-12-13 12:34:50 -0800 |
---|---|---|
committer | John Keiser <john@johnkeiser.com> | 2015-12-13 12:34:50 -0800 |
commit | f08d833465d9d2ea083d12a66958753afa2b1c7e (patch) | |
tree | de01dc2a2cf8cbb04a64b0d22fd4735a98bcb96e | |
parent | 7814a405d629b612cd0b93266db79e2427f59d7d (diff) | |
parent | 50b463e33a2ea6645f3d6fcee836b6f88842bd32 (diff) | |
download | chef-f08d833465d9d2ea083d12a66958753afa2b1c7e.tar.gz |
Merge branch 'jk/action-class-do'
-rw-r--r-- | lib/chef/resource.rb | 40 | ||||
-rw-r--r-- | spec/integration/recipes/resource_action_spec.rb | 75 |
2 files changed, 98 insertions, 17 deletions
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index f969ccd84c..a7b1f63463 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -1172,14 +1172,18 @@ class Chef # using `action :x do ... end`, then there is no need for this class and # `action_class` will be `nil`. # + # If a block is passed, the action_class is always created and the block is + # run inside it. + # # @api private # - def self.action_class - @action_class || - # If the superclass needed one, then we need one as well. - if superclass.respond_to?(:action_class) && superclass.action_class - declare_action_class - end + def self.action_class(&block) + return @action_class if @action_class && !block + # If the superclass needed one, then we need one as well. + if block || (superclass.respond_to?(:action_class) && superclass.action_class) + @action_class = declare_action_class(&block) + end + @action_class end # @@ -1189,19 +1193,21 @@ class Chef # If a block is passed, it is run inside the action_class. # # @api private - def self.declare_action_class - return @action_class if @action_class - - if superclass.respond_to?(:action_class) - base_provider = superclass.action_class - end - base_provider ||= Chef::Provider + def self.declare_action_class(&block) + @action_class ||= begin + if superclass.respond_to?(:action_class) + base_provider = superclass.action_class + end + base_provider ||= Chef::Provider - resource_class = self - @action_class = Class.new(base_provider) do - include ActionClass - self.resource_class = resource_class + resource_class = self + Class.new(base_provider) do + include ActionClass + self.resource_class = resource_class + end end + @action_class.class_eval(&block) if block + @action_class end # diff --git a/spec/integration/recipes/resource_action_spec.rb b/spec/integration/recipes/resource_action_spec.rb index fe6b4083f1..0ea67ea5f2 100644 --- a/spec/integration/recipes/resource_action_spec.rb +++ b/spec/integration/recipes/resource_action_spec.rb @@ -425,6 +425,81 @@ describe "Resource.action" do }.to raise_error(/Property template of has_property_named_template\[hi\] cannot be passed a block! If you meant to create a resource named template instead, you'll need to first rename the property./) end end + + context "When a resource declares methods in action_class and declare_action_class" do + class DeclaresActionClassMethods < Chef::Resource + use_automatic_resource_name + property :x + action :create do + new_resource.x = a + b + c + d + end + action_class do + def a + 1 + end + end + declare_action_class do + def b + 2 + end + end + action_class do + def c + 3 + end + end + declare_action_class do + def d + 4 + end + end + end + + it "the methods are not available on the resource" do + expect { DeclaresActionClassMethods.new('hi').a }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').b }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').c }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').d }.to raise_error(NameError) + end + + it "the methods are available to the action" do + r = nil + expect_recipe { + r = declares_action_class_methods 'hi' + }.to emit_no_warnings_or_errors + expect(r.x).to eq(10) + end + + context "And a subclass also creates a method" do + class DeclaresActionClassMethodsToo < DeclaresActionClassMethods + use_automatic_resource_name + action :create do + new_resource.x a+b+c+d+e + end + action_class do + def e + 5 + end + end + end + + it "the methods are not available on the resource" do + expect { DeclaresActionClassMethods.new('hi').a }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').b }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').c }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').d }.to raise_error(NameError) + expect { DeclaresActionClassMethods.new('hi').e }.to raise_error(NameError) + end + + it "the methods are available to the action" do + r = nil + expect_recipe { + r = declares_action_class_methods_too 'hi' + }.to emit_no_warnings_or_errors + expect(r.x).to eq(15) + end + end + end end end |