Shopify/liquid — pull request #269 by jgelo (2013-10-10 22:29:08+00:00)
Title: add support for drops with dynamically added methods

I'm using Drops as a sort of OpenStruct and ran into an issue when adding different methods to the same class, it's likely a unique use case but you never know. {{gift.desc}} in the example below should return 'description' but returns nil. Since item.name was called first, its InvoiceItem methods ('name' and 'amount') were cached by Drop.invokable? and I'm unable to access gift.desc.

```ruby
class Invoice < Liquid::Drop
class InvoiceItem < Liquid::Drop
def initialize(attrs)
attrs.each do |k, v|
# Create an attr_reader for each given attr
instance_variable_set("@#{k}", v)
self.class.class_eval "attr_reader k"
end
end
end

def items
[InvoiceItem.new(:name => 'item', :amount => '25.00')]
end

def gifts
[InvoiceItem.new(:name => 'gift', :amount => '50.00', :desc => 'description')]
end
end

str = '{% for item in invoice.items %}{% assign name = item.name %}{% endfor %}{% for gift in invoice.gifts %}{{gift.desc}}{% endfor %}'
tpl = Liquid::Template.parse(str)
assert_equal 'description', tpl.render('invoice' => Invoice.new)
```