Destroyed Using Liquid without Rails (textile)

anke1460
2011-09-20 06:52:08 -07:00
parent e48c69deea
commit a5e0fbf7e2
-115
@@ -1,115 +0,0 @@
Want to use Liquid along with some plain old Ruby code?
First, of course, you need to tell Ruby about the Liquid library.
Assuming that you're in the @liquid@ directory, as cloned from GitHub,
just @require 'lib/liquid'@.
The big secret, however, is creating a @to_liquid@ method for any classes you want Liquid to access.
Let's say you have a Product class:
<pre>
class Product
attr_accessor :name, :price
def initialize(name,price)
@name = name
@price = price
end
end
</pre>
And you have a chunk of text that you want to Liquidize by inserting some details about your products:
<pre>
sentence = "I'm running to the store with {{ product.price }} dollars in my pocket "
sentence += "to buy a {{ product.name }}."
</pre>
And you create a product and parse the sentence:
<pre>
my_purchase = Product.new('box of sausages', 20)
puts Liquid::Template.parse(sentence).render('product' => my_purchase)
</pre>
You excitedly execute your code, expecting to see your beautiful new sentence, but instead you get:
<pre>
I'm running to the store with Liquid error:
undefined method `to_liquid' for #<Product:0x1388c08 ...
</pre>
@to_liquid@ ???
Where did that come from?
Turns out you need to add a method to your class that returns your instance variables as part of a hash.
(Liquid was built to be very paranoid about not letting people access something they're not supposed to,
so you need to explicitly let Liquid know how to access everything in your object.)
So, we update the @Product@ class description to include that method:
<pre>
class Product
attr_accessor :name, :price
def initialize(name, price)
@name = name
@price = price
end
def to_liquid
{ "name" => self.name,
"price" => self.price }
end
end
</pre>
Run that again and presto:
<pre>
I'm running to the store with 20 dollars in my pocket to buy a box of sausages.
</pre>
However, that's a bit verbose, so you may want to use @liquid_methods@, instead:
<pre>
class Product
attr_accessor :name, :price
liquid_methods :name, :price
def initialize(name, price)
@name = name
@price = price
end
end
</pre>
(Thanks to "Tom's":http://github.com/mojombo "Jekyll":http://github.com/mojombo/jekyll/tree/master/lib/jekyll/post.rb#L122-128 code for helping me figuring this out.)
h2. A bit more detail
Every variable rendered by liquid must either:
* implement a @to_liquid@ method; or
* be a Proc. This is called with the @Liquid::Context@ as a parameter and must return an object which responds to @to_liquid@
Liquid defines @to_liquid@ for the following standard classes: String, Array, Hash, Numeric, Time, DateTime, Date, TrueClass, FalseClass, NilClass. For each of these, @to_liquid@ just returns the object itself. <em>(See: lib/liquid/extensions.rb)</em>
If the value returned by @to_liquid@ is inserted into the output, it will be further converted with @to_s@ <em>(actually this is done implicitly by Array#join - see lib/liquid/template.rb)</em>
When used in a chained expression like @foo.bar@ or @foo['bar']@, the result of @to_liquid@ on the left-hand subexpression must either:
* respond to @has_key?@ and @[]@ (i.e. duck-type like a Hash); or
* respond to @fetch@ and @[]@ with an Integer argument (i.e. duck-type like an Array); or
* respond to @size@ or @first@ or @last@
In each case, the object returned after applying the right-hand subexpression must also respond to @to_liquid@ or be a Proc which returns an object that responds to @to_liquid@. In the latter case, it will only be called if the previous element in the chain also responds to @[]=@ - that is, if the value can be cached in the parent object.
<em>(See: lib/liquid/context.rb)</em>
<pre>
>> assigns = {"foo"=>{"bar"=>{"baz"=>lambda { |x| Time.now } }}}
=> {"foo"=>{"bar"=>{"baz"=>#<Proc:0xb7cd9af8@(irb):11>}}}
>> t = Liquid::Template.parse("{{ foo.bar.baz }}")
=> #<Liquid::Template:0xb7d2e738 ... >
>> t.render(assigns)
=> "Fri Jun 05 11:23:56 +0100 2009"
>> assigns
=> {"foo"=>{"bar"=>{"baz"=>Fri Jun 05 11:23:56 +0100 2009}}}
</pre>