summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Keiser <john@johnkeiser.com>2015-12-11 15:40:18 -0800
committerJohn Keiser <john@johnkeiser.com>2015-12-11 15:40:18 -0800
commit83a1df9786ab19967925b7e4b35a414ec6ff9d57 (patch)
tree57d5977ef00eaf73b27492f8ee9dda3253f4a2b9
parent7814a405d629b612cd0b93266db79e2427f59d7d (diff)
downloadchef-83a1df9786ab19967925b7e4b35a414ec6ff9d57.tar.gz
Implement action_class do ... end
-rw-r--r--lib/chef/resource.rb40
-rw-r--r--spec/integration/recipes/resource_action_spec.rb31
2 files changed, 54 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..a55ea72b3f 100644
--- a/spec/integration/recipes/resource_action_spec.rb
+++ b/spec/integration/recipes/resource_action_spec.rb
@@ -425,6 +425,37 @@ 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 :hi do
+ new_resource.x = a + b
+ end
+ action_class do
+ def a
+ 1
+ end
+ def b
+ 2
+ 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)
+ 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(3)
+ end
+ end
end
end