2010-08-29 106 views
6

本週末我一直在使用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_postsblog.last_post,但不知道我會怎麼做類似的東西blog.latest_posts: 10

任何人都可以指出我的方向是正確的嗎?

我想到的一個想法是創建一個Liquid過濾器,並將Blog對象和一個整數傳遞給它。喜歡的東西:

{% for post in blog | latest_posts(10) %} 
  • ,但還沒有試過,但因爲覺得我在黑暗中刺傷位左右。希望得到更多有經驗的Liquid用戶的幫助。

回答

9

回答我自己的問題,我在這裏找到了一個解決方案,記錄在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 %} 

這似乎有點哈克,但它的工作原理:)

+1

感謝您對before_method的信息。我同意這有點冒險,但請記住Liquid的重點是模板,而不是模板背後的機制。其目的是讓其他人可以僅使用模板語言以安全的方式製作有用/複雜的數據視圖。我認爲它非常好 - 我的客戶和他們的承包商都使用Liquid模板和我的SAAS數據。 – 2010-08-31 17:53:02

5

我認爲液體是一個夢幻般的模板系統。恭喜調查/使用它。

默認情況下,模型的任何方法都不可用於液體模板。這是一件好事。然後指定哪些方法可用。 (白名單。)

我使用郵件列表上發送的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 
+0

嗨拉里,感謝您的意見。我嘗試了一下你的建議,但不能令人滿意地工作。 '{{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

+0

我發現我需要將過濾器的結果存儲在一個變量,然後我可以迭代變量:'{%assign latest_blog_posts = blog | latest_posts:10%}'then'{%for post_blog_posts%} ...' – 2013-11-24 00:00:29

相關問題