The ELC Community Blog
A knowledge exchange on Ruby on Rails and Agile Development
Liquid Template Tags
by Ryan Garver on April 20, 2008
I've been playing around with Liquid recently and have had a lot of fun extending it for a CMS that we're building. It wasn't obvious how to get started, but Liquid is a pretty lightweight code base and after some digging I was able to figure out how to create new custom tags for use in our templates.
The reason why I needed a custom tag was to build a Gravatar image url. This requires an email to be hashed and composed in to a URL. One of the nice things about Liquid is the fact that it protect you from templates that could do things that you don't want to allow. Unlike ERB, Liquid does not evaluate Ruby code directly. It will recognize tags and defer the evaluation to the tag definition which is usually parameterized. We want to be able to insert a line like this in our code:
1 <img src="{% gravatar_image_url 'jdoe@example.com' size:40 %}" />
When Liquid evaluates that template we want the tag gravatar_image_url to take an email and a list of attributes and output a URL which will show the avatar for the specified icon. For this tag we will start off by creating a class inheriting from Liquid::Tag.
1 module Liquid
2 class GravatarImageUrl < Tag
3 Syntax = /([^\s]+)\s+/
4 def initialize(tag_name, markup, tokens)
5 # ...
6 end
7
8 def render(context)
9 # ...
10 end
11 end
12 end
NOTE: I've seen some plugins and older versions of liquid that don't have the tag_name argument for initialize. In this example the parameter can be dropped and it should work fine.
There are two methods that we need to override: initialize and render. The initialize method is called to parse the arguments and prepare for rendering once the context is established (this would allow for a two pass evaluation and a possibility for some basic caching of state).
1 Syntax = /([^\s]+)\s+/
2 def initialize(markup, tokens)
3 if markup =~ Syntax
4 @email = $1
5 @attributes = {}
6 markup.scan(TagAttributes) do |key, value|
7 @attributes[key] = value
8 end
9 else
10 raise SyntaxError.new("Syntax Error in 'gravatar_image_url' - Valid syntax: gravatar_image_url [email]")
11 end
12 end
The Syntax trick here isn't normally my style, so I should give credit to the authors of Liquid for demonstrating it to me. It simplifies the process of parsing out important pieces from the input stream. The markup parameter is providing the string that follows the tag name. So if we put gravatar_image_url 'jdoe@example.com' size:40, markup would be set to 'jdoe@example.com' size:40. TagAttributes is provided by Liquid along with a number of other helper regular expressions.
1 def render(context)
2 base_url = "http://www.gravatar.com/avatar.php?gravatar_id=#{Digest::MD5.hexdigest(context[@email])}"
3 extended_attrs = @attributes.map{|k,v| "#{URI.encode(k)}=#{URI.encode(v)}"}
4 ([base_url]+extended_attrs).compact.join('&')
5 end
Here is where we get a real taste of the execution context. The first line we are running a MD5 hexdigest on the email, as specified by the Gravatar Docs. We allow for non-literal values here by asking the context tell us what the email actually is. This allows us to do things like: gravatar_image_url post.author.email size:40. The context has enough information to evaluate the post.author.email string and return the value. Incidentally this context trick also allows for some interesting tricks like doing basic math and such.
The last step is to register this Tag definition with a real name with the Liquid::Template handler.
1 Template.register_tag('gravatar_image_url', GravatarImageURL)
And now you have your very own custom Liquid tag!
Comments
Hey thanks! Liquid’s been around for a while now but I’m always missing a bit more throughout examples and how-to’s.
i’m fine good work
perfect design thanks
Very funny pictures
Good article. How would I go about doing something like this:
post.author.email.gravatar_image_url size:40
Is this type of syntax handled with a drop? Can drops take parameters or must I use a tag?
Thanks, Wes
专业翻译公司,位居翻译公司业界前列,拥有分翻译公司,包括南京翻译公司,北京翻译公司,上海翻译公司承接上海业务,上海翻译公司,北京翻译公司承接北京业务,上海翻译公司和北京翻译公司并提供翻译报,广州翻译公司报价,广州翻译公司大全,深圳翻译公司报价,深圳翻译公司服务。
北京华美达翻译公司是由清华、北大的几位专家教授组建而成。管理规范、翻译专业水平高并拥有一大批有经验的专业翻译人员。公司译员大多是毕业于清华、北大、北京外语大学、第二外国语学院等著名大学,都具有多年的翻译经验,具有很高的专业翻译水平。
北京华美达翻译公司以清华大学的自强不息、厚德载物作为优良传统,以“客户至上”为指导思想,为客户提供最周到、最专业的服务,以优质、低价、高效的服务让客户满意,本公司因有一大批优秀的翻译人才而享有盛名,赢得了众多客户的认可和好评。
北京华美达翻译公司提供包括英语翻译、俄语翻译、德语翻译、日语翻译、韩语翻译、法语翻译、西班牙语翻译、阿拉伯语翻译、意大利语翻译、越语翻译、葡萄牙语翻译、匈牙利语翻译、波斯语翻译、等,以及小语种的中外文翻译服务。并且涉及的专业范围广,如:机械设备、电子电气、仪器仪表、计算机、水利工程、医疗医药、生物化学、经济金融、法律、贸易等等及相关领域。同时北京华美达翻译公司提供同传、口译和交传等翻译服务。很多译员曾先后出色的完成一些重要会议、电话及谈判等的同传、口译业务,并赢得广大客户的依赖和好评。
</body> </html>nice http://www.dogpile.com/dogpile/ws/results/Web/http
2F
FEorg
2F_media
2F1
FEhtml/1/417/TopNavigation/Relevance/iq=true/zoom=off/_iceUrlFlag=7?_IceUrl=true gdfhgdg hhttp://search.russiansabroad.com/default.aspx?searchPost=http%3A%2F%2Fperach.org.il%2F_media%2Fcrm_but%2F1%2Fmap.html&submit=Search&startPosition=0&repeatSearch=n gdfh dgfh df http://www.google.com/search?hl=en&newwindow=1&q=http%3A%2F%2Fperach.org.il%2F_media%2Fcrm_but%2F1%2Fmap.html&btnG=Search&aq=f&oq=