2011-03-02 4 views
15

내 모델의 필드가 부울인지 확인하려고하지만 테스트가 계속 실패합니다.레일 : 부울 값의 포함 여부 확인 테스트 실패

이 읽은 후 : Validating boolean value in Rspec and Rails 나는과 같이 그 일을 결국이 Rails: how do I validate that something is a boolean? :

class Model < ActiveRecord::Base 

    validates :my_field, :inclusion => { :in => [true, false] } 

end 

내가이에게 (RSpec에와 했어야 매처 (matcher)를 사용하여) 몇 가지 방법을 테스트 해봤를하고 있기 때문에 내 테스트에 계속 실패, 나는 지금 당장 멍청한 (?) 길을 걷고있다. 그래도 테스트는 통과되지 않고 어딘가에서 값을 변환하는 메커니즘이 있다고 추측합니다. 여기

내가 무슨 일이 일어나고 있는지 알아 내기 위하여 사용하고 무엇을 : 나는 무엇을 놓치고

# create instance without setting value ... 

# these work as expected 
model_instance.valid?.should be_false  # passes 
model_instance.my_field = true 
model_instance.valid?.should be_true  # passes 
model_instance.my_field = false  
model_instance.valid?.should be_true  # passes 

# works as expected 
model_instance.my_field = "" 
model_instance.valid?.should be_false  # passes 

# these should pass but fail 
model_instance.my_field = "foo" 
model_instance.my_field.should == "foo" # fails as well, my_field == false 
model_instance.valid?.should be_false  # fails 

model_instance.my_field = "false" 
model_instance.my_field.should == "false" # fails as well, my_field == false 
model_instance.valid?.should be_false  # fails 

model_instance.my_field = "123" 
model_instance.valid?.should be_false  # fails 

model_instance.my_field = "true" 
model_instance.my_field.should == "true" # fails as well, my_field == true 
model_instance.valid?.should be_false  # fails 

? 다소 논리적 인 방식으로 값이 변환 된 것으로 보입니다. 그러나이를 방지하려면 어디에서 어떻게해야합니까? 이러한 종류의 유효성 검사를 올바르게 수행하는 방법은 무엇입니까?

답변

34

부울 필드를 true/false로 검증해야하는이 아이디어가 어디에서 왔는지 모르겠지만 최근에는 관련이없는 몇 가지 프로젝트에서 보았습니다. 어딘가에서 시작된 밈.

부울 필드로, 참 또는 거짓이어야합니다. AR은 부울 값의 구현 세부 사항을 처리합니다. 부울 필드가 필요하면 데이터베이스에 부울 필드를 만듭니다. 이야기의 끝. 소스를 보면

, 여기 부울에 값을 변환하는 코드입니다 :

TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set 
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set 

그래서 다른 살펴 본다 : 여기

# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 147 
147:   def value_to_boolean(value) 
148:   if value.is_a?(String) && value.blank? 
149:    nil 
150:   else 
151:    TRUE_VALUES.include?(value) 
152:   end 
153:   end 

가 그리고는 부울 대응 동일시하는 값입니다 위의 코드에서 기대하는 바가 틀린 것을 제외하고는 모든 것이 그대로 있어야합니다. "foo"를 부울 값에 할당하면 "foo"는 허용되는 true 값 목록에 없으므로 부울 필드의 기본값은 false가되며, 이는 나중에 접근 자에서 반환됩니다. 필드의 부울 값은 여전히 ​​:in => [true, false]이므로 모델이 유효합니다. "false"와 "123"은 같은 이유로 실패합니다. "true"는 부울 true의 허용되는 값이므로 필드가 true로 설정되고 위에서 설명한 이유로 유효합니다.

+1

감사합니다. 'FALSE_VALUES' /'TRUE_VALUES' 상수에 대해 알지 못했습니다. 그리고 당신의 포괄적 인 대답은 그것을 멋지게 설명합니다! 오늘 뭔가 배웠습니다. – polarblau

+8

나는 부울 필드가 validates_presence_of 일 때, 그것이 틀릴 때마다 검증을 실패한다는 것을 생각한다. 해결 방법은 validates_inclusion_in을 사용하는 것입니다. Rails 3.0.9에서이 동작을 직접 볼 수 있습니다. 여기를 참고하십시오 : http://www.ruby-forum.com/topic/99285 –

+0

레일즈 가이드를 다시 읽고 Validation에 대해 다시 읽었으며, 부울 필드의 유효성을 검사하는 방법을 설명했습니다. 내 첫 번째 본능은 "항상 true 또는 false가 될 것이고 결코 없기 때문에 부울을 검증해야하는 이유는 무엇입니까?"라고했습니다. 나는이지면에 부딪쳤다. 나는 그 밈이 새 이주자들과 함께 시작했다고 생각하며, 좀 갇혀있다. "그들이 어떻게 설명하는지, 그것은 완료되어야한다". 나는 그것이 완전성을 위해 설명되었다고 생각합니다. 단지 2 센트 가치입니다 ... –

26

저는 Rails 전문가는 아니지만 여기에 목을 걸고 절대 값 ()에 대한 부울 값의 유효성을 검사하고 싶다고 말합니다. 즉, 널 (NULL) 값을 허용하지 않으려는 경우를 가정 해 보겠습니다.

데이터베이스 프로그래밍 배경에서 볼 수 있듯이 부울 필드에는 true, false 및 NULL의 세 가지 값이있을 수 있습니다. 원시 SQL에서 프로그래밍 할 때 NULL은 많은 추가 작업을 유발하는 특수 처리 (= null 대신 is null 대신)가 필요합니다.

오늘 Rails 3.2를 테스트 할 때 nil 값이있는 유효성이 검사되지 않은 부울 필드를 만들고이를 PostgreSQL 데이터베이스에 저장하는 것으로 문제없이 NULL로 저장되었습니다.

  • 는 마이그레이션에 :null => false와 부울 필드를 정의 레일에 논리 값에 대한이 방법을 사용하여, 내가 계획입니다이 발생할 수있는 모든 문제를 방지합니다.
  • :inclusion => { :in => [true, false] }을 사용하여 모델 필드의 유효성을 검사하십시오. 필드가 초기화되지 않은 경우 (nil) 좋은 메시지를 제공합니다.

그것은 내가 :presence 검증을 사용할 수 없습니다 처음에 직관적 아니지만, 그것은 :presence는 값이 비어 있지 않은 것을 확인합니다 밝혀, 값 false이 비어입니다. 즉, :presence => true의 유효성을 검사하고 값을 false으로 설정하면 유효성 검사가 실패합니다. API에서는 validates_presence_of을, @ Kumajunkie의 답변에 대해서는 정원의 코멘트를 참조하십시오.

+1

나는 완전히 동의한다. INSERT가 데이터베이스에 의해 거부되는 것을 결코 원하지 않습니다 (아주 못생긴 메시지, 대개 500 오류). 대신 Rails 유효성 검사에서 사용자 친화적 인 유용한 오류 메시지로 완료 될 수 있습니다. – sockmonk

+0

죄송합니다,하지만 내 model.rb 파일을 해결할 구문을 가져올 수 없습니다. 나는 유효성 검사의 변형을 시도했다 : property_name, inclusion (true, false)뿐만 아니라 : inclusion => {in => [true, false]}. model.rb 파일에 대한 대답은 무엇입니까? – flobacca

+1

@flobacca, 예. 원래 질문의 맨 위에있는 예와 같이 모델로 이동합니다. 작동하지 않는 경우 특정 코드 예제를 표시 할 수 있도록 자신 만의 질문을 만들어야 할 수 있습니다. –