2015-12-09 24 views
0

我正在爲我的支付網關創建校驗和。校驗和應該採用以下格式:爲Ruby中的傳入參數創建校驗和

key|txnid|amount|productinfo|firstname|email|||||||||||salt 

我需要在電子郵件和鹽之間留下11個管道。

在我控制我創建了一個方法:

require 'digest/sha2' 

def getChecksum(key, txnid, amount, productinfo, firstname, email, phone, surl, furl) 
    String str = key + '|' + txnid + '|' + amount + '|' + productinfo + '|' + firstname + '|' + email + '|' + phone + '|' + surl + '|' + furl+ '|'+ '|'+ '|'+ '|'+ '|'+ '|'+ '|'+ '|' + 'salt' 
    Digest::SHA512.hexdigest(str) 
end 

我調用此方法在我的控制器:

hash: getChecksum(
       key: 'key_value', 
       txnid: '4', 
       amount: '2000', 
       productinfo: 'first sales', 
       firstname: 'John', 
       email: '[email protected]', 
       phone: '123456789', 
       surl: 'http://someurl.io', 
       furl: 'http://someurl.io') 

但現在我得到一個「錯誤的參數數目」錯誤:

wrong number of arguments (1 for 9)  
def getChecksum(key, txnid, 
amount, productinfo, firstname, email, phone, surl, furl) 

我認爲所有的參數都被視爲一個參數。有人能告訴我我在這裏做錯了嗎?

+1

Ruby不是Java。我們不需要,或者使用'String str = ...'和'getChecksum'應該是'get_checksum',因爲方法(如變量)是用snake_case寫的。 –

+0

@theTinMan是的......你是對的......但是學到了很多這個單一的問題..謝謝大家的幫助.. – Abhilash

回答

1

讓我們來看看你是如何編寫代碼的,看看我們是否能夠使它更像Ruby,並希望更有生產價值。

你寫這樣的:

首先,ICK。

  • Ruby中的方法和變量是snake_case,而不是camelCase。 ItsAReadabilityThing。
  • 我們沒有使用String str =...來定義變量。 Ruby可以計算出99.99%的時間是什麼類型的變量,所以str =...就足夠了。
  • 想想你如何使用固定字符串和值。'|'是你的分隔符,所以將它定義爲這樣的:

    SEPARATOR = '|' 
    

    而且你需要他們的11種分頻器,這樣定義:

    DIVIDER = SEPARATOR * 11 
    

我寫的代碼更喜歡這個:

require 'digest/sha2' 

SEPARATOR = '|' 
DIVIDER = SEPARATOR * 11 # => "|||||||||||" 

def checksum_1(key, txnid, amount, productinfo, firstname, email, phone, surl, furl) 
    str = [key, txnid, amount, productinfo, firstname, email, phone, surl, furl].join(SEPARATOR) + DIVIDER + 'salt' 
    Digest::SHA512.hexdigest(str) 
end 

但即使這樣做可以改進。

當我們有三個以上的參數時,是時候重構和清理參數列表。有很多方法可以做到這一點,但使用哈希是最常見的:

def checksum_2(params) 
    str = params.values_at(
    :key, :txnid, :amount, :productinfo, :firstname, :email, :phone, :surl, :furl 
).join(SEPARATOR) + DIVIDER + 'salt' 

    Digest::SHA512.hexdigest(str) 
end 

使用values_at是一個很好的方法來提取在哈希鍵的值。它們按照鍵的順序出現在一個數組中。

現在的問題是,一個參數可能會丟失,Ruby不會捕獲它。命名參數是處理這個問題的新熱點,但對於較老的Rubies,或者想知道如何在其他語言中完成它,我們可以查看收到的密鑰,然後查看它們的相關值,如果事情沒有看起來不錯,引發異常而不是回報虛假價值。

爲了方便起見,我將使用Active支持的blank?方法,在覈心擴展發現:

require 'active_support/core_ext/object/blank' 
def checksum_3(params) 
    required_values = [:key, :txnid, :amount, :productinfo, :firstname, :email, :phone, :surl, :furl] 

    missing_keys = required_values - params.keys 
    fail ArgumentError, "Missing keys: #{ missing_keys.map{ |k| ":#{ k }" }.join(', ') }" unless missing_keys.empty? 

    missing_values = required_values.select{ |k| params[k].blank? } 
    fail ArgumentError, "Missing values for: #{ missing_values.map{ |k| ":#{ k }" }.join(', ') }" unless missing_values.empty? 

    str = params.values_at(*required_values).join(SEPARATOR) + DIVIDER + 'salt' 
    Digest::SHA512.hexdigest(str) 
end 

下面是如何調用該方法外觀的各種版本,以及相關的校驗和沿這所返回:

c1 = checksum_1('key_value', '4', '2000', 'first sales', 'John', '[email protected]', '123456789', 'http://someurl.io', 'http://someurl.io') 

c2 = checksum_2(
    key: 'key_value', 
    txnid: '4', 
    amount: '2000', 
    productinfo: 'first sales', 
    firstname: 'John', 
    email: '[email protected]', 
    phone: '123456789', 
    surl: 'http://someurl.io', 
    furl: 'http://someurl.io' 
) 

c3 = checksum_3(
    key: 'key_value', 
    txnid: '4', 
    amount: '2000', 
    productinfo: 'first sales', 
    firstname: 'John', 
    email: '[email protected]', 
    phone: '123456789', 
    surl: 'http://someurl.io', 
    furl: 'http://someurl.io' 
) 

c1 # => "fcf4e21c6e711808a6984824f09552dccc5c4378b55720c88b3abd4a1904931b8d883beaef51edec705a9d8b0ccd3ba898a0d4c05f75bd41fa3b90f0df7b5c79" 
c2 # => "fcf4e21c6e711808a6984824f09552dccc5c4378b55720c88b3abd4a1904931b8d883beaef51edec705a9d8b0ccd3ba898a0d4c05f75bd41fa3b90f0df7b5c79" 
c3 # => "fcf4e21c6e711808a6984824f09552dccc5c4378b55720c88b3abd4a1904931b8d883beaef51edec705a9d8b0ccd3ba898a0d4c05f75bd41fa3b90f0df7b5c79" 

雖然我們仍然有相同數量的信息傳遞,使用散列讓我們看到了每個參數被分配到,導致自記錄代碼,這是一個非常重要的事情r長期維護。此外,哈希不需要特定的參數順序,因此編寫調用它的代碼更容易;我通常知道我需要某些東西,但不記得他們在什麼順序。

這就是我如何寫這種類型的代碼。請參閱「Ruby 2 Keyword Arguments」以獲得關於同一主題的類似文章。

+0

謝謝你花時間把這些放在一起..我現在覺得我理解它就像一陣微風......改變了選擇的答案,因爲這解釋了很多細節...不能感謝更多...祝你有美好的一天... – Abhilash

2

您正在發送一個散列作爲參數,而只需發送值(不帶鍵​​)。也不需要聲明類型String str,您應該查看您的Ruby基礎知識,我猜你是來自另一種語言。

# You are calling this 
getChecksum(key: 'key_value', txnid: '4', ...) 
# which syntactically equals this, a single hash as a parameter 
getChecksum({key: 'key_value', txnid: '4', ...}) 
# Instead, send the values alone 
getChecksum('key_value', '4', ...) 
+0

是的,我從java背景.. – Abhilash

+1

有了這麼多的參數,散列可能是可取的。您可以通過使用關鍵字參數來獲得最好的兩個詞:https://robots.thoughtbot.com/ruby-2-keyword-arguments –

+0

歡迎來到Ruby!你會發現它有趣並且在強大的社區背後準備好幫助。 – Leito

1

這裏是你如何定義的方法與關鍵字參數:

def getChecksum(key:, txnid:, amount:, productinfo:, firstname:, email:, phone:, surl:, furl:) 
    str = key + '|' + txnid + '|' + amount + '|' + productinfo + '|' + firstname + '|' + email + '|' + phone + '|' + surl + '|' + furl+ '|'+ '|'+ '|'+ '|'+ '|'+ '|'+ '|'+ '|' + 'salt' 
    Digest::SHA512.hexdigest(str) 
end 

然後你就可以用哈希調用它像你現在。

我覺得這看起來有點清潔,但:

def get_checksum(key:, txnid:, amount:, productinfo:, firstname:, email:, phone:, surl:, furl:) 
    str = "#{key}|#{txnid}|#{amount}|#{productinfo}|#{firstname}|#{email}|#{phone}|#{surl}|#{furl}||||||||salt" 
    Digest::SHA512.hexdigest(str) 
end 

或許:

def get_checksum(key:, txnid:, amount:, productinfo:, firstname:, email:, phone:, surl:, furl:) 
    str = [ key, txnid, amount, productinfo, firstname, email, phone, surl, furl ].join("|") 
    Digest::SHA512.hexdigest("#{str}||||||||salt") 
end 

您可以瞭解更多關於關鍵字參數,包括如何給關鍵字的默認值,使其可選,這裏:https://robots.thoughtbot.com/ruby-2-keyword-arguments

+0

肯定比我的代碼更好..謝謝.. – Abhilash

+0

這最後的解決方案看起來很優雅,沒有這些管道。謝謝。 – Abhilash