2011-04-20 35 views
2

我在一個視圖中有這樣的回報率片段:link_to_unless問題

<%= 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}

我一直在尋找的代碼,我不明白爲什麼我得到的錯誤,因爲它應該簡單地返回名稱:

# 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 

我m使用Rails 2.3.11和Ruby 1.8.7

乾杯!

回答

2

由於Ruby是不是一個懶惰的語言,blog_with_page_path(:page_num => @posts_pages[:previous])被你稱之爲儘快評估,無論這個值是否曾經被使用。

0

它看起來像一個錯誤。這段代碼不是「懶惰」的,所以它執行所有語句。所以,你可以去以下三種方式:

  1. 修補它
  2. 進行簡單if .. else
  3. 發起Hack:

喜歡這個

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

相反的0你可以設置任意數量的,它永遠不會被設置

+0

不是一個錯誤。這是語言的工作原理。 – 2011-04-20 15:31:38

+1

Ehm ...這不是一個語言錯誤,但在Rails中有很多「懶惰」的東西,所以這是一個很好的候選者,可以被重構爲懶惰的東西。 – fl00r 2011-04-20 15:32:38

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 
1

鑑於這說明你的問題的各種其他的答案,爲什麼不試試這爲您的解決方案:

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

這將首先評估「除非」條件,省去您僞造的link_to時@post_pages[:previous]爲零。

- 編輯 -

正如評論指出的那樣,因爲你需要的字符串後面也許最簡單的方法就是三元:

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

但它不會返回「Previous」字符串。所以你應該在這裏使用完整的'if..else' – fl00r 2011-04-20 15:36:57

+0

謝謝,我會用三元組。根據@rshallit [在他的回答](http://stackoverflow.com/questions/5732689/link-to-unless-problem/5732870#5732870)你的第一個解決方案也不會工作。 – brafales 2011-04-20 17:49:00

+0

@brafales我是她。 :) – 2011-04-20 18:45:54