link_to_unless问题

时间:2011-04-20 15:16:51

标签: ruby-on-rails ruby

我在视图中有这个RoR片段:

<%= link_to_unless(@posts_pages[:previous].nil?, 
  "Previous", 
  blog_with_page_path(:page_num => @posts_pages[:previous])) %>

这里blog_with_page是一个命名路线。如果@posts_pages[:previous].nil?false(正如预期的那样)并且链接生成正确,则代码段有效。但是,当@posts_pages[:previous].nil?true时,我收到错误,告诉我无法使用"Previous"生成路由,而不是简单地返回:page_num=>nil字符串。这是预期的行为吗?如果满足条件,则不应评估路径代码,是否应该进行评估? 这是完整的错误: blog_with_page_url failed to generate from {:page_num=>nil, :action=>"show", :controller=>"pages"}, expected: {:action=>"show", :controller=>"pages"}, diff: {:page_num=>nil}

我一直在查看link_to_unless代码,我不明白为什么我会收到错误,因为它应该只返回名称:

# File actionpack/lib/action_view/helpers/url_helper.rb, line 394
  def link_to_unless(condition, name, options = {}, html_options = {}, &block)
    if condition
      if block_given?
        block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block)
      else
        name
      end
    else
      link_to(name, options, html_options)
    end
  end

我正在使用Rails 2.3.11和Ruby 1.8.7

干杯!

4 个答案:

答案 0 :(得分:2)

由于Ruby不是一种惰性语言,因此blog_with_page_path(:page_num => @posts_pages[:previous])会在您调用它时立即对其进行评估,无论该值是否被link_to_unless使用。

答案 1 :(得分:1)

鉴于解决您问题的其他各种答案,为什么不尝试这个作为您的解决方案:

link_to( "Previous", blog_with_page_path(:page_num => @posts_pages[:previous]) ) unless @posts_pages[:previous].nil?

这将首先评估“除非”条件,在@post_pages[:previous]为零时免除伪造link_to。

- 编辑 -

正如评论中指出的那样,既然你需要字符串,那么最简单的方法就是三元组:

@posts_pages[:previous].nil? ? "Previous" : link_to( "Previous", blog_with_page_path(:page_num => @posts_pages[:previous]) )

答案 2 :(得分:0)

它看起来像一个bug。此代码不是“懒惰”,因此它执行所有语句。所以你可以采取三种方式:

  1. 补丁
  2. 简化if .. else
  3. 哈哈:
  4. 喜欢这个

    <%= link_to_unless(@posts_pages[:previous].nil?, 
      "Previous", 
      blog_with_page_path(:page_num => @posts_pages[:previous] || 0)) %>
    

    您可以设置任何数字,而不是0,而不会设置

答案 3 :(得分:0)

函数参数总是在函数运行之前计算,无论是否需要它们:

ree-1.8.7-2011.03 :005 > def print_unless(condition, thing_to_print)
ree-1.8.7-2011.03 :006?>   puts "I started executing"
ree-1.8.7-2011.03 :007?>   puts thing_to_print unless condition
ree-1.8.7-2011.03 :008?>   end
 => nil 
ree-1.8.7-2011.03 :009 > print_unless(true, 1/0)
ZeroDivisionError: divided by 0
    from (irb):9:in `/'
    from (irb):9
    from :0