将变量传递给Liquid模板中的模型实例方法
本周末我一直在使用Liquid模板引擎,我不知道以下是否可能。将变量传递给Liquid模板中的模型实例方法
假设我在Blog
模型中有方法,我可以传递一个整数来得到最新的N个帖子。是否可以在液体模板中使用该方法?
例如:
class Blog
has_many :posts
def latest_posts(n)
posts.latest(n) # using a named scope
end
def to_liquid(*args)
{
'all_posts' => posts.all, # allows me to use {% for posts in blog.all_posts %}
'last_post' => post.last, # allows me to use {% assign recent = blog.last_post %}
'latest_posts' => posts.latest_posts(args[0]) # how do I pass variables to this?
}
end
end
在上面的简单的例子,在我的液体模板,我可以使用blog.all_posts
和blog.last_post
,但不知道我会怎么做类似的东西blog.latest_posts: 10
。
任何人都可以指出我的方向是正确的吗?
我想到的一个想法是创建一个Liquid过滤器,并将Blog对象和一个整数传递给它。喜欢的东西:
{% for post in blog | latest_posts(10) %}
- ,但还没有试过,但因为觉得我在黑暗中刺伤位左右。希望得到更多有经验的Liquid用户的帮助。
回答我自己的问题,我在这里找到了一个解决方案,记录在Liquid groups pages。
实质上,我需要为最新的帖子创建一个下拉菜单 - LatestPostsDrop
- 以及一种使用before_method
方法将变量传递给它的种类。下面是完整的解决方案:
class Blog
has_many :posts
def latest_posts
LatestPostsDrop.new(posts)
end
def to_liquid
{
'all_posts' => posts.all,
'last_post' => post.last,
'latest_posts' => latest_posts
}
end
end
class LatestPostsDrop < Liquid::Drop
def initialize(posts)
@posts = posts
end
def before_method(num)
@posts.latest(num) # Post.latest is a named scope
end
end
做上述,可以让你使用类似通过任何数量的最新帖子迭代:
{% for post in blog.latest_posts.10 %} # the last attribute can be any integer
<p>{{ post.title }}</p>
{% endfor %}
这似乎有点哈克,但它的工作原理:)
我认为液体是一个梦幻般的模板系统。恭喜调查/使用它。
默认情况下,模型的任何方法都不可用于液体模板。这是一件好事。然后指定哪些方法可用。 (白名单。)
我使用邮件列表上发送的Module的扩展名。下面是完整的扩展。它通过向类和模块添加一个简单的#liquid_methods方法来处理Liquid :: Drop的创建。
然后,在你的模型,只是做:
class Blog
# id
# name
has_many :posts
def latest_posts(n)
posts.latest(n) # using a named scope
end
def latest_10_posts;latest_posts(10); end
liquid_methods :id, :name, :posts, :latest_10_posts
end
我不知道怎么随便/如果你能通过PARAMS成的下降。在Liquid邮件列表上询问。我想你可以。
补充:我现在重读你的问题,看看你真的想在参数去的方法来发送。您可以向Liquid过滤器发送多个参数/参数。所以你可以有一个过滤器:
# Define as a Liquid filter
def latest_posts(blog, n)
blog.latest(n)
end
# then call the filter in a template:
{{ blog2 | latest_posts: 10 }}
# Note that the second param is after the filter name.
在这个例子中,还要记住你还需要在Post类中声明液体方法。
这里是模块扩展。
# By dd -- http://groups.google.com/group/liquid-templates/browse_thread/thread/bf48cfebee9fafd9
# This extension is usesd in order to expose the object of the implementing class
# to liquid as it were a Drop. It also limits the liquid-callable methods of the instance
# to the allowed method passed with the liquid_methods call
# Example:
#
# class SomeClass
# liquid_methods :an_allowed_method
#
# def an_allowed_method
# 'this comes from an allowed method'
# end
# def unallowed_method
# 'this will never be an output'
# end
# end
#
# if you want to extend the drop to other methods you can define more methods
# in the class <YourClass>::LiquidDropClass
#
# class SomeClass::LiquidDropClass
# def another_allowed_method
# 'and this is another allowed method'
# end
# end
# end
#
# usage:
# @something = SomeClass.new
#
# template:
# {{something.an_allowed_method}}{{something.unallowed_method}}{{something.another_allowed_method}}
#
# output:
# 'this comes from an allowed method and this is another allowed method'
#
# You can also chain associations, by adding the liquid_method calls in the
# association models.
#
class Module
def liquid_methods(*allowed_methods)
drop_class = eval "class #{self.to_s}::LiquidDropClass < Liquid::Drop; self; end"
define_method :to_liquid do
drop_class.new(self)
end
drop_class.class_eval do
allowed_methods.each do |sym|
define_method sym do
@object.send sym
end
end
def initialize(object)
@object = object
end
end
end
end
嗨拉里,感谢您的意见。我尝试了一下你的建议,但不能令人满意地工作。 '{{blog | latest_posts:10}}'确实会返回最近的10个帖子。然而,我无法解决如何遍历它们:'{%for {blog | latest_posts:10}%}(或者这个主题的变化)只是没有遍历帖子。 但是,我发现[解决方法](http://groups.google.com/group/liquid-templates/browse_thread/thread/90ae684e754b6de5/1b080bcff95ed59d?lnk=gst&q=pass+variable+to+drop#1b080bcff95ed59d)我将在下面的答案... – aaronrussell 2010-08-29 20:07:05
我发现我需要将过滤器的结果存储在一个变量,然后我可以迭代变量:'{%assign latest_blog_posts = blog | latest_posts:10%}'then'{%for post_blog_posts%} ...' – 2013-11-24 00:00:29
感谢您对before_method的信息。我同意这有点冒险,但请记住Liquid的重点是模板,而不是模板背后的机制。其目的是让其他人可以仅使用模板语言以安全的方式制作有用/复杂的数据视图。我认为它非常好 - 我的客户和他们的承包商都使用Liquid模板和我的SAAS数据。 – 2010-08-31 17:53:02