From 7acdac2a1c771c92fb04fd208d11dae5aa7054dc Mon Sep 17 00:00:00 2001 From: "Mark H. Wilkinson" Date: Wed, 9 Jul 2008 08:23:51 +0100 Subject: [PATCH] Fix attribute expansion to index only once in all cases. Also drop array. syntax --- lib/liquid/context.rb | 58 ++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 0e1163f..69b7664 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -188,44 +188,30 @@ module Liquid if object = find_variable(first_part) parts.each do |part| + part = resolve($1) if part_resolved = (part =~ square_bracketed) - # If object is a hash we look for the presence of the key and if its available - # we return it + # If object is a hash- or array-like object we look for the + # presence of the key and if its available we return it + if object.respond_to?(:[]) and + ((object.respond_to?(:has_key?) and object.has_key?(part)) or + (object.respond_to?(:fetch) and part.is_a?(Integer))) - if part =~ square_bracketed - part = resolve($1) + # if its a proc we will replace the entry with the proc + res = object[part] + res = object[part] = res.call(self) if res.is_a?(Proc) and object.respond_to?(:[]=) + object = res.to_liquid - object[pos] = object[part].call(self) if object[part].is_a?(Proc) and object.respond_to?(:[]=) - object = object[part].to_liquid + # Some special cases. If the part wasn't in square brackets and + # no key with the same name was found we interpret following calls + # as commands and call them on the current object + elsif !part_resolved and object.respond_to?(part) and ['size', 'first', 'last'].include?(part) + object = object.send(part.intern).to_liquid + + # No key was present with the desired value and it wasn't one of the directly supported + # keywords either. The only thing we got left is to return nil else - - # Hash - if object.respond_to?(:has_key?) and object.has_key?(part) - - # if its a proc we will replace the entry in the hash table with the proc - res = object[part] - res = object[part] = res.call(self) if res.is_a?(Proc) and object.respond_to?(:[]=) - object = res.to_liquid - - # Array - elsif object.respond_to?(:fetch) and part =~ /^\d+$/ - pos = part.to_i - - object[pos] = object[pos].call(self) if object[pos].is_a?(Proc) and object.respond_to?(:[]=) - object = object[pos].to_liquid - - # Some special cases. If no key with the same name was found we interpret following calls - # as commands and call them on the current object - elsif object.respond_to?(part) and ['size', 'first', 'last'].include?(part) - - object = object.send(part.intern).to_liquid - - # No key was present with the desired value and it wasn't one of the directly supported - # keywords either. The only thing we got left is to return nil - else - return nil - end + return nil end # If we are dealing with a drop here we have to @@ -235,11 +221,5 @@ module Liquid object end - - private - - def execute_proc(proc) - proc.call(self) - end end end