has_secure_password와 presence와 allow_nil과 나.

Rails 튜토리얼 (제 6 판)의 10.1.4 -TDD로 편집을 성공시킨다.
오전중 가득 걸려 해소시킨 의문의 비망록입니다.
나 이외의 사람은 이런 곳에서 지루하지 않을지도 모르지만 ··

막힌 곳과 의문점



걸린 곳: 비밀번호가 비어 있는 상태에서도 업데이트할 수 있도록 합니다.



"사용자 정보를 편집 할 때 하나의 암호를 입력하는 것은 불편하기 때문에
비밀번호를 변경하지 않으면 입력하지 않고 사용자 정보를 업데이트 할 수 있습니다. "
라는 내용.

구체적으로 현재 상황

user.rb
class User < ApplicationRecord
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

그리고 nil, 빈 문자, 6자 미만의 암호는 허용되지 않습니다.

user.rb
class User < ApplicationRecord
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

그리고, allow_nil 라고 하는 옵션으로, 패스워드가 비었을 때의 예외 처리를 준다 (밸리데이션을 스킵 한다) 요.

라는 것이었습니다.

무엇이 의문인가? 분명히이 기사를 부드럽게 따뜻하게 건너 뛰십시오

질문 : 원래, presence : true 쓸 필요가 있었습니까? ?



왜 그런 의문이 생겨 버렸는가 하면, 튜토리얼중의,
「allow_nil에 의해 신규 등록시에 패스워드가 없어도 등록할 수 버린다!?」라고 걱정이 되지만,has_secure_password가 객체 생성시 존재 여부를 확인하기 때문에,
그 걱정도 필요 없어! "
라는 문장.
(간략화하고 있습니다. 어폐가 있으면 죄송합니다..)

이하, 내 의문과 의문이 생기는 원인이 된 착각입니다.
  • 신규 등록시는 패스워드 필수로 하고 싶다 → has_secure_password 로 검증할 수 있다
  • 편집시에는 패스워드 넣지 않아도 갱신할 수 있도록 하고 싶다 → has_secure_password 는 오브젝트 생성시에만 존재성을 검증하기 때문에, 편집시에는 패스워드 넣지 않아도 OK!
    ⇒ 어라, has_secure_password 그냥 완결? presence: true 필요없다··?

  • 중요한 것을 간과하고 있었던 것이군요.

    결론:편집시, 하늘의 경우는 스킵 하고 싶지만, 공문자의 경우는 밸리데이션 걸면.



    다시 한번, 아래의 3점을 명확히 해 두고 싶습니다.
  • has_secure_password : DB에 레코드가 생성되었을 때만 존재성의 validation을 행한다
  • presence: true : 값이 nil 또는 空文字가 아닌지 확인
  • allow_nil : 대상 값이 nil이면 유효성 검사 건너 뛰기 = 값이 空文字이면 유효성 검사에 걸립니다

  • 즉, presence: true를 작성하지 않으면,
    「편집시, 패스워드란에 스페이스를 박아 버렸을 경우에도 갱신이 생겨 버린다」
    그렇게했다 · ·

    어떻게 의문을 해소했는가



    presence: true 필요없다··?」라고 생각했기 때문에presence: true를 지우고 다음 상태에서 테스트를 돌려 보았습니다.

    user.rb
    class User < ApplicationRecord
      has_secure_password
      validates :password, length: { minimum: 6 }, allow_nil:true
    

    그러면 아래 통합 테스트는 GREEN에.

    test/integration/users_edit_test.rb
      test "successful edit" do
        get edit_user_path(@user)
        assert_template 'users/edit'
        name = "Foo Bar"
        email = "[email protected]"
        patch user_path(@user), params: { user: {name: name,
                                                email: email,
                                                password: "",
                                                password_confirmation: "" }}
        assert_not flash.empty?
        assert_redirected_to @user
        @user.reload
        assert_equal name, @user.name
        assert_equal email, @user.email
      end
    

    역시 presence: true 필요 없어?··? 그렇게 생각했을 때,
    또 다른 테스트가 나를 상기시켜주었습니다.

    user_test.rb
      test "password should be present (nonblank)" do
        @user.password = @user.password_confirmation = " " * 6
        assert_not @user.valid?
      end
    

    이쪽이 제대로 RED가 되어 있었다!

    우선 이 테스트는 사용자를 신규 등록하지 않고 패스워드의 값을 공문자로 설정하고 있기 때문에has_secure_password 유효성 검사에는 걸리지 않습니다.

    그리고 presence: true를 지워 버렸기 때문에, 공문자 입력이 OK가 되어,
    유저가 유효하게 되어 버렸기 때문에 테스트가 RED가 되어 있었던 것이었습니다.

    여기서 확실히 " " * 6와 빈 문자가 테스트 되었기 때문에
    자신의 착각을 알 수있었습니다. .

    똑같이 꼭 여기에서 막혀 버린 분의 참고가 되면 다행입니다.

    참고


  • Rails 튜토리얼
  • Rails 가이드 /Active Record 유효성 검사
  • 좋은 웹페이지 즐겨찾기