2012-11-25 39 views
3

我寫了一個非常簡單的用戶類。實例變量電子郵件有一個閱讀器訪問器和我自己的作者訪問器,用正則表達式驗證電子郵件地址。通過操作繞過編寫器訪問器而不是分配

class User 
    attr_reader :email 

    def email=(value) 
     if (value =~ /^[a-z\d\-\_\+\.][email protected]([a-z\d\-]+\.)+[a-z]+$/) 
      @email = value 
     else 
      # bonus question: is ArgumentError the right error type to use here? 
      raise ArgumentError, "#{value} is not a valid email address." 
     end 
    end 
end 

我寫了下面的測試:

require 'test/unit' 
require_relative '../lib/user' 

class TC_UserTest < Test::Unit::TestCase 
    def setup 
     @user = User.new() 
    end 

    def test_email 
     # using the writer accessor 
     @user.email = '[email protected]' 
     # bypassing the writer accessor. evil. 
     @user.email[4] = '#' 
     assert_equal('[email protected]', @user.email) 
    end 
end 

通過使用由讀者訪問給我參考,我能夠處理電子郵件實例變量,而無需通過作家訪問去。

同樣普林西將適用於任何類型的數據,可以讓操作不直接分配與=

我被過分熱心的新的價值?我只想編寫健壯的代碼。有沒有辦法確保我的電子郵件地址只能使用writer訪問器進行設置?

我是新來的語言,我試圖感受最佳實踐。

回答

1

做你想做什麼,我建議是將正則表達式轉換爲自己的驗證方法。

更好的是,除非你真的想做正確的事,否則不要寫郵件正則表達式。

使用,而不是一個寶石:在您設置電子郵件https://github.com/SixArm/sixarm_ruby_email_address_validation

,與http://ruby-doc.org/core-1.9.3/Object.html#method-i-freeze

獎金答案凍結它:是的,引發ArgumentError是正確的錯誤類型一般。如果您使用的是Rails,請考慮使用Rails驗證方法。

+0

感謝您的詳細解釋!我會忠於你的忠告。 –

1

您可以在作家凍結值,這樣你就可以通過指定新的作家之一,但已經分配將是不變的:

class User 
    attr_reader :email 

    def email=(value) 
    if (value =~ /^[a-z\d\-\_\+\.][email protected]([a-z\d\-]+\.)+[a-z]+$/) 
     # make email immutable: 
     @email = value.freeze 
    else 
     # bonus question: is ArgumentError the right error type to use here? 
     raise ArgumentError, "#{value} is not a valid email address." 
    end 
    end 
end 
+0

謝謝,凍結的概念對我來說是新的。聽起來就像我正在尋找的東西。 –

2

使測試通過(並保護@email變量)的選項是公開重複。

def email 
    @email.dup 
end 
+0

那還沒有發生在我身上。這是解決問題的有趣方式。我想我正在使用凍結選項。試圖改變一個凍結的變量會引發一個很好的錯誤。 –

相關問題