Unfortunately, Rails teaches people to believe that :name and 'name' are the
same thing. They are not :-(
You need to return {'name'=>name} from your to_liquid method, and you need
to pass {'user'=> ...} not {:user=> ...} into render.
$ irb --simple-prompt
>> require 'liquid'
=> true
>> class Foo; def to_liquid; {"name"=>"boing"}; end; end
=> nil
>> tmpl = Liquid::Template.parse "Hi {{ user.name }}"
=> #<Liquid::Template:0xb7bb42a4 @root=#<Liquid::Document:0xb7bb427c
@nodelist=["Hi ", #<Liquid::Variable:0xb7bb3ef8 @filters=[], @markup="
user.name ", @name="user.name">]>>
>> tmpl.render :user=>Foo.new
=> "Hi "
>> tmpl.render 'user'=>Foo.new
=> "Hi boing"
>>
Also, you don't appear to be using your UserDrop class at all, so you can
delete it entirely. A Drop is a shortcut for building an object where, when
liquid calls obj['name'], it invokes the obj.name public instance method
instead. Since you are already returning a Hash, then obj['name'] already
returns the value of interest directly.
HTH,
Brian.
Which objects are available in the template is simply the set of objects you
pass to the render() call.
Which methods are available on each object is a little more difficult. When
Liquid evaluates an expression of the form foo.bar, it requires only two
methods: 'has_key?' and '[]'
So I'd suggest that you make sure that all your objects respond to a 'keys'
method as well, which lists the available keys. A Hash does this already of
course. If you're subclassing from Liquid::Drop, then
def keys
self.class.public_instance_methods.map { |m| m.to_s }
end
If you look at the source of Liquid::Drop, you'll see that this is the how
it decides whether a method can be directly invoked or not.
However, a Liquid::Drop can actually accept *any* method name. Any unknown
method name is passed to the before_method method.
Brian.