Only a small subset of Puppet functions were available on the scope in
templates.  This had people doing workarounds like:

    inline_template("<%= Puppet::Parser::Functions.autoloader.loadall; 
scope.function_extlookup(['hello world']) %>")

Rather than need to know these workarounds like needing to load all
templates, the scope object now uses method_missing to find the function
if available.

Paired-with: Nick Lewis <n...@puppetlabs.com>
Signed-off-by: Matt Robinson <m...@puppetlabs.com>
---
Local-branch: ticket/2.7.x/4549-functions_in_templates
 lib/puppet/parser/scope.rb     |   10 ++++++++++
 spec/unit/parser/scope_spec.rb |   20 ++++++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb
index ed67cd1..746cfbd 100644
--- a/lib/puppet/parser/scope.rb
+++ b/lib/puppet/parser/scope.rb
@@ -418,6 +418,16 @@ class Puppet::Parser::Scope
     environment.known_resource_types.find_definition(namespaces, 
type.to_s.downcase)
   end
 
+  def method_missing(method, *args, &block)
+    method.to_s =~ /^function_(.*)$/
+    super unless $1
+    super unless Puppet::Parser::Functions.function($1)
+
+    # Calling .function(name) adds "function_#{name}" as a callable method on
+    # self if it's found, so now we can just send it
+    send(method, *args)
+  end
+
   def resolve_type_and_titles(type, titles)
     raise ArgumentError, "titles must be an array" unless titles.is_a?(Array)
 
diff --git a/spec/unit/parser/scope_spec.rb b/spec/unit/parser/scope_spec.rb
index 5308856..67f0db0 100755
--- a/spec/unit/parser/scope_spec.rb
+++ b/spec/unit/parser/scope_spec.rb
@@ -52,6 +52,26 @@ describe Puppet::Parser::Scope do
     Puppet::Parser::Scope.ancestors.should 
include(Puppet::Resource::TypeCollectionHelper)
   end
 
+  describe "when missing methods are called" do
+    before :each do
+      @env      = Puppet::Node::Environment.new('testing')
+      @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new('foo', 
:environment => @env))
+      @scope    = Puppet::Parser::Scope.new(:compiler => @compiler)
+    end
+
+    it "should load and call the method if it looks like a function and it 
exists" do
+      @scope.function_sprintf(["%b", 123]).should == "1111011"
+    end
+
+    it "should raise NoMethodError if the method doesn't look like a function" 
do
+      expect { @scope.sprintf(["%b", 123]) }.should raise_error(NoMethodError)
+    end
+
+    it "should raise NoMethodError if the method looks like a function but 
doesn't exist" do
+      expect { @scope.function_fake_bs(['cows']) }.should 
raise_error(NoMethodError)
+    end
+  end
+
   describe "when initializing" do
     it "should extend itself with its environment's Functions module as well 
as the default" do
       env = Puppet::Node::Environment.new("myenv")
-- 
1.7.3.1

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to puppet-dev@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to