레코드가 없을 때 nil과 함께 find ()


96

내 현재 레일 프로그램에서 다음과 같은 것을 사용할 때

 user = User.find(10)

ID = 10 인 사용자가 없으면 다음과 같은 예외가 발생합니다.

ActiveRecord::RecordNotFound: Couldn't find User with ID=10

예외를 발생시키는 대신 nil을 얻을 수 있으므로 다음과 같이 할 때 :

unless user = Challenge.find(10)
  puts "some error msg"         
end

레코드가 없을 때 nil을 얻고 싶고 begin / rescue를 사용하고 싶지 않습니다.

감사


답변:


172

네, 그냥하세요 :

Challenge.find_by_id(10)

Rails 4 및 5의 경우 :

Challenge.find_by(id: 10)

11
이상한! 나는 그것이 .find_by_*nil을 반환하고 .find그렇지 않을 것이라고 결코 짐작하지 못했을 것입니다.
ddavison 2014-08-07

이것은 rails 4에서 변경되었습니다 . 특정 속성으로 항목을 찾는 새로운 방법 은이 답변 stackoverflow.com/a/26885027/1438478 을 참조하십시오 .
Fralcon 2015 년

Rails 4.2에서 해시를 'x'로 전달 Something.find_by(id: x)하면 WHERE 절의 일부로 해시의 모든 속성 / 값 쌍이 포함 된 SQL 문이 생성 되는 이상한 문제를 발견 했습니다. 나에게 Rails 버그처럼 보입니다.
Tilo

Rails (3, 4 또는 5) find_by_...는 모델에 포함 된 모든 속성에 대해 동적 파인더를 생성 :id합니다. 따라서 Challenge.find_by_id(10)Rails 버전에 관계없이 작동해야합니다.
Arta

아래 @MohamedIbrahim로 지정, 당신은 할 수 있습니다 :Challenge.find(10) rescue nil
Hallgeir Wilhelmsen은

31

Rails 4에서는 find_by_id수락 된 답변에 사용 된 것과 같은 동적 파인더 가 더 이상 사용되지 않습니다.

앞으로는 새 구문을 사용해야합니다.

Challenge.find_by id: 10

4
다른 나처럼이 혼동되는 경우 누군가에 : Challenge.find_by(id: 10)이 글을 쓰는 다른 방법입니다
데빈 하워드

14

ActiveRecord 쿼리 인터페이스를 사용하면됩니다.

이것은 Exception을 발생시키는 대신 nil을 반환합니다.

  User.where(:id => 10).first

대신 이것을 사용하는 이유 find_by_id는 Rails 3에서 4로 이동할 수 있기 때문입니다. Rails 4에서는 find_by(:id => 10).
Gene

5

단순히 예외를 포착하지 않는 이유는 무엇입니까? 귀하의 사례는 다음과 같은 예외 사항과 정확히 일치합니다.

begin
  user = User.find(10)
rescue ActiveRecord::RecordNotFound
  puts "some error msg"
end

복구 블록의 오류에서 복구하려면 (예 : 자리 표시 자 사용자 (null 패턴) 설정)이 블록 아래에서 코드를 계속 사용할 수 있습니다. 그렇지 않으면 "begin"과 "rescue"사이의 블록에 "happy case"에 대한 모든 코드를 넣을 수 있습니다.


Btw : begin…end컨트롤러 메서드와 같은 블록이 이미 있으면 블록이 필요하지 않습니다 . 이 경우 필요한 유일한 추가 라인은 rescue라인입니다. 훨씬 더 우아하고 쉽게이 검사보다 처리하는 nilif문.
morgler

4

당신은 이것을 시도 할 수 있습니다 Challenge.exists?(10)


7
추가 SQL 요청이됩니다
fl00r

나는이 생각 심지어 더 나은 테스트를 찾고
SomeSchmo

당신이 반환 된 값에 대해하지만 DB의 레코드의 존재에 대해 걱정하지 않는 경우에 사용
필립 Bartuzi

4

mongoid로 어려움을 겪는 사람들을 위해 레일 버전에 관계없이 findfind_by메소드 모두 예외가 발생 한다는 것이 밝혀졌습니다 !

false로 설정할 수 있는 옵션 (즉 raise_not_found_error )이 있지만 falsey로 인해 find메서드가 예외를 발생시키지 않습니다.

따라서 몽고 이드 사용자를위한 해결책은 역겨운 코드입니다.

User.where(id: 'your_id').first # argghhh

모하메드-이브라힘의 구조없는 해결책에 대해 어떻게 생각하십니까? .where(email: params[:email]).first나 보다 더 우아해 보인다 .
Wylliam Judd

1
차라리 그 사용하지 rescue이 같은 오타 등의 문제를 숨길 수 있기 때문에 구문
크리스티아누 멘돈카

@morgler의 솔루션을 사용하여 마무리했습니다.
Wylliam Judd

2

다음과 같이 간단합니다.

user = User.find(10) rescue nil

1
이 경우 구조 될 것으로 예상되는 오류 인 ActiveRecord :: RecordNotFound에 대해 더 구체적으로 설명하겠습니다. @morgler
luizrogeriocn

2
개인적으로 이것이 최선의 답변이라고 생각합니다. 사용자가 발견되지 않는 경우 이미 무엇을 내 코드를 말하는거야if user...else
Wylliam 주드

0

필요한 속성 (귀하의 경우 id)과 함께 find_by를 사용할 수 있습니다. 주어진 ID를 찾을 수없는 경우 오류를 제공하는 대신 nil을 반환합니다.

user = Challenge.find_by_id(id_value)

또는 새로운 형식을 사용할 수 있습니다.

user = Challenge.find_by id: id_value

where를 사용할 수도 있지만 0 개 이상의 레코드가있는 활성 레코드 관계를 반환하는 위치를 알아야합니다. 먼저 하나의 레코드 만 반환하거나 0 개 레코드가 반환되는 경우 nil을 사용해야합니다.

user = Challenge.where(id: id_value).first
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.