diff --git a/History.txt b/History.txt index 16345a9..2d6dbd0 100644 --- a/History.txt +++ b/History.txt @@ -1,3 +1,8 @@ +== 0.8.5 + +* Minor enhancements + * Added support for append_args and multiple prepend arguments. + == 0.8.4 2011-06-15 * Minor enhancements diff --git a/README.rdoc b/README.rdoc index 10955cd..5633eb3 100644 --- a/README.rdoc +++ b/README.rdoc @@ -65,6 +65,19 @@ You can look at the tests for an idea of how to declare things. If you have more http://zenadmin.org/community +== TRICKS: + +If you define your own 'safe_method_type' resolution methods, or you define a method by providing a symbol (method executed to get type), you can use the special :prepend_args and :append_args elements in the type response. You need to provide a TypedString or an array of TypedString and these elements will be inserted in the final method. This can be used to provide default values: + + safe_method_type [:parse_date, String] => :get_parse_date + + def get_parse_date(signature) + {:class => Time, :append_args => RubyLess::TypedString.new('visitor.tz', :class => TZInfo::Timezone)} + end + + # parse_date('2003-12-01') + # ==> parse_date('2003-12-01', visitor.tz) + == WARNING: Changing the safe methods during runtime removes the cache for all classes and diff --git a/lib/ruby_less/info.rb b/lib/ruby_less/info.rb index 32b823f..9920683 100644 --- a/lib/ruby_less/info.rb +++ b/lib/ruby_less/info.rb @@ -1,3 +1,3 @@ module RubyLess - VERSION = '0.8.4' + VERSION = '0.8.5' end \ No newline at end of file diff --git a/lib/ruby_less/processor.rb b/lib/ruby_less/processor.rb index 85f9f08..7ab6233 100644 --- a/lib/ruby_less/processor.rb +++ b/lib/ruby_less/processor.rb @@ -400,6 +400,9 @@ def get_lit_class(lit) def args_with_prepend(args, opts) if prepend_args = opts[:prepend_args] + if prepend_args.kind_of?(Array) + prepend_args = array_to_arguments(prepend_args) + end if args prepend_args.append_argument(args) args = prepend_args @@ -408,6 +411,17 @@ def args_with_prepend(args, opts) end end + if append_args = opts[:append_args] + if append_args.kind_of?(Array) + append_args = array_to_arguments(append_args) + end + if args + args.append_argument(append_args) + else + args = append_args + end + end + if append_hash = opts[:append_hash] last_arg = args.list.last unless last_arg.klass.kind_of?(Hash) @@ -422,5 +436,13 @@ def args_with_prepend(args, opts) end args end + + def array_to_arguments(args) + code = t('') + args.each do |arg| + code.append_argument(arg) + end + code + end end end diff --git a/rubyless.gemspec b/rubyless.gemspec index 5b9c260..d801ce1 100644 --- a/rubyless.gemspec +++ b/rubyless.gemspec @@ -5,11 +5,11 @@ Gem::Specification.new do |s| s.name = %q{rubyless} - s.version = "0.8.4" + s.version = "0.8.5" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Gaspard Bucher"] - s.date = %q{2011-06-15} + s.date = %q{2011-06-16} s.description = %q{RubyLess is an interpreter for "safe ruby". The idea is to transform some "unsafe" ruby code into safe, type checked ruby, eventually rewriting some variables or methods.} s.email = %q{gaspard@teti.ch} s.extra_rdoc_files = [ diff --git a/test/RubyLess/basic.yml b/test/RubyLess/basic.yml index 1de0d1f..30f9971 100644 --- a/test/RubyLess/basic.yml +++ b/test/RubyLess/basic.yml @@ -118,10 +118,25 @@ instance_variable: tem: "node.mazette" res: "Mazette !" -prepend_arg: - src: "prepend_test(4)" - tem: "add(10, 4)" - res: "14" +prepend_one: + src: "prepend_one(4) + prepend_one" + tem: "(add(10, 4)+add(10))" + res: "24" + +prepend_many: + src: "prepend_many(4) + prepend_many" + tem: "(add(10, 20, 4)+add(10, 20))" + res: "64" + +append_one: + src: "append_one(4) + append_one" + tem: "(add(4, 10)+add(10))" + res: "24" + +append_many: + src: "append_many(4) + append_many" + tem: "(add(4, 10, 20)+add(10, 20))" + res: "64" safe_property: src: "dog_name" diff --git a/test/RubyLess_test.rb b/test/RubyLess_test.rb index 4d55eaf..6dbcad6 100644 --- a/test/RubyLess_test.rb +++ b/test/RubyLess_test.rb @@ -98,8 +98,14 @@ def safe_const_type(constant) # Example to dynamically rewrite method calls during compilation def safe_method_type(signature, receiver = nil) unless res = super - if signature == ['prepend_test', Number] + if signature == ['prepend_one'] || signature == ['prepend_one', Number] res ={:class => Number, :prepend_args => RubyLess::TypedString.new('10', :class => Number), :method => 'add'} + elsif signature == ['prepend_many'] || signature == ['prepend_many', Number] + res ={:class => Number, :prepend_args => [RubyLess::TypedString.new('10', :class => Number), RubyLess::TypedString.new('20', :class => Number)], :method => 'add'} + elsif signature == ['append_one'] || signature == ['append_one', Number] + res ={:class => Number, :append_args => RubyLess::TypedString.new('10', :class => Number), :method => 'add'} + elsif signature == ['append_many'] || signature == ['append_many', Number] + res ={:class => Number, :append_args => [RubyLess::TypedString.new('10', :class => Number), RubyLess::TypedString.new('20', :class => Number)], :method => 'add'} elsif context && res = context[:node_class].safe_method_type(signature) # try to execute method in the current var "var.method" res = res[:class].call(self, signature) if res[:class].kind_of?(Proc) @@ -145,8 +151,8 @@ def str "str" end - def add(a,b) - a+b + def add(*args) + args.inject(0) {|s,a| s+a} end def vowel_count(str) diff --git a/test/typed_string_test.rb b/test/typed_string_test.rb index c87ac0e..c30abc8 100644 --- a/test/typed_string_test.rb +++ b/test/typed_string_test.rb @@ -11,9 +11,16 @@ class TypedStringTest < Test::Unit::TestCase should 'render with name' do assert_equal 'foo', subject.to_s end - + should 'return class of content on klass' do assert_equal Number, subject.klass end + + should 'maintain opts on dup' do + other = subject.dup + assert_equal TypedString, other.class + assert_equal subject.opts, other.opts + assert_equal subject.opts.object_id, other.opts.object_id + end end end