2013-11-21 177 views
2

現在,我覺得像一個非常醜陋的方式來設置一個變量的值取決於它是否返回一個空字符串。下面是有問題的方法(它使用Nokogiri,但這對這個問題並不重要)。嵌套的Ruby方式如果聲明

def get_let(response) 
    if response.css('A').empty? 
     if response.css('B').empty? 
      let = '' 
     end 
     let = response.css('B') 
    else 
     let = response.css('A') 
    end 

    return let 
end 
+0

你的問題是什麼? – sawa

回答

4
def get_let(response) 
    let = response.css('A') 
    let = response.css('B') if let.empty? 
    let = '' if let.empty? 
end 
2

刪除回報,令:

def get_let(response) 
    if response.css('A').empty? 
     response.css('B').empty? ? '' : response.css('B') 
    else 
     response.css('A') 
    end 
end 

或使用收藏:

def get_let(response) 
    ['A', 'B'].map { |l| response.css(l) }.find { |items| !items.empty? } || '' 
end 

可避免重複計算的CSS選擇器。

+0

如果response.css('A')和response.css('B')都是空的,那麼對於'find'的默認參數會引發這個異常:對於「」:String''調用'NoMethodError:undefined method'。 'find'及其別名'detect'需要一個參數:1)是'nil',或者2)響應'call'。查看我的答案,瞭解收集方法的一些替代實現。 –

+0

不錯,忘了那個。 –

0

我會做這樣的事情,非常明確地發生了什麼事情,沒有分支邏輯來跟蹤推理它。

def get_let(response) 
    return '' if response.css('A').empty? && response.css('B').empty? 
    return response.css('B') if response.css('A').empty? 
    return response.css('A') if response.css('B').empty? 
end 
0

你不需要let - 只是它返回的if/else塊的結果...我寧願把它像這樣因爲它更容易比ternaries閱讀...

def get_let(response) 
    if response.css('A').empty? 
    if response.css('B').empty? 
     '' 
    else 
     response.css('B') 
    end 
    else 
    response.css('A') 
    end 
end 
+0

這種方法的兩個缺點是它有多個回報,並且回報是隱含的。如果你有一個方法有多個返回點,我建議使用'return'關鍵字來明確它們。我知道'return'通常不是Rubyish,但在這種情況下我會做一個例外,因爲使用它會澄清代碼。 –

0
def get_let(response) 
    case 
    when !response.css('A').empty? 
     response.css('A') 
    when response.css('A').empty? && !response.css('B').empty? 
     response.css('B') 
    else 
    '' 
    end 
end 
3

這是不太@ sethcall的回答是可讀的,但它應該是相當可讀,如果你知道一些紅寶石成語:

def get_let(response) 
    responses = [response.css('A'), response.css('B')] 
    responses.detect { |response| !response.empty? } || '' 
end 

detect返回塊不返回false的第一個結果。這有避免條件的優點,如果這是你要做的事情。如果你想在上面的回答沒有||做,你可以這樣做:

def get_let(response) 
    responses = [response.css('A'), response.css('B')] 
    responses.detect(-> { '' }) { |response| !response.empty? } 
end 

我沒有找到第二個解決方案是幾乎與第一個解決方案那樣直觀,但。如果你可以指定一個空字符串作爲參數,那將是非常棒的。然而,detect及其別名find的參數必須是nil或響應call方法的內容,例如lambda或proc。實際上沒有理由通過nil,因爲這是默認值。

如果你知道爲確保response.css方法不會與它nilfalse值返回一個數組,你可以嘗試這種解決方案:

​​

見紅寶石文檔閱讀更多有關how detect works 。這裏是docs on any?

+1

如果您使用Rails或ActiveSupport,可以將它縮短爲'respond.detect(&:present)|| 「」' –