3

非常に単純な User クラスを作成しました。インスタンス変数 email には、リーダー アクセサーと、メール アドレスを正規表現で検証する独自のライター アクセサーがあります。

class User
    attr_reader :email

    def email=(value)
        if (value =~ /^[a-z\d\-\_\+\.]+@([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 = 'user@example.com'
        # bypassing the writer accessor. evil.
        @user.email[4] = '#'
        assert_equal('user@example.com', @user.email)
    end
end

リーダー アクセサーによって提供された参照を使用することで、ライター アクセサーを介さずに email インスタンス変数を操作できます。

同じ原則が、= で新しい値を完全に代入することなく操作できるすべてのデータ型に適用されます。

私は熱心すぎますか?堅牢なコードを書きたいだけです。メールアドレスがライターアクセサーを使用してのみ設定できるようにする方法はありますか?

私はこの言語に不慣れで、ベストプラクティスの感触を掴もうとしています。

4

3 に答える 3

2

@emailテストに合格する (そして変数を保護する) ためのオプションは、重複を公開することです。

def email
  @email.dup
end
于 2012-11-25T13:46:03.493 に答える
1

ライターで値をフリーズできます。これにより、ライターを介して新しい値を割り当てることができますが、既に割り当てられている値は不変になります。

class User
  attr_reader :email

  def email=(value)
    if (value =~ /^[a-z\d\-\_\+\.]+@([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
于 2012-11-25T11:54:06.007 に答える
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 検証メソッドの使用を検討してください。

于 2012-11-25T11:54:24.403 に答える