예외없이 Array Rails ActiveRecord에서 ID를 선택하는 방법


134

ID 배열이 있으면

ids = [2,3,5]

그리고 나는 수행

Comment.find(ids)

모든 것이 잘 작동합니다. 그러나 존재하지 않는 ID가 있으면 예외가 발생합니다. 이것은 일부 필터와 일치하는 ID 목록을 얻을 때 일반적으로 발생합니다.

current_user.comments.find(ids)

이번에는 유효한 댓글 ID가있을 수 있지만 주어진 사용자에게 속하지 않으므로 찾을 수 없으며 예외가 발생합니다.

시도 find(:all, ids)했지만 모든 레코드를 반환합니다.

내가 지금 할 수있는 유일한 방법은

current_user.comments.select { |c| ids.include?(c.id) }

그러나 그것은 매우 비효율적 인 솔루션처럼 보입니다.

존재 하지 않는 레코드에 대한 예외를 얻지 않고 배열 에서 ID 를 선택하는 더 좋은 방법이 있습니까?

답변:


215

걱정되는 예외를 피하고 있다면 "find_all_by .."함수 군은 예외를 발생시키지 않고 작동합니다.

Comment.find_all_by_id([2, 3, 5])

일부 ID가 존재하지 않아도 작동합니다. 이것은에서 작동

user.comments.find_all_by_id(potentially_nonexistent_ids)

사례도 마찬가지입니다.

업데이트 : Rails 4

Comment.where(id: [2, 3, 5])

이것은 내가 선호하는 솔루션입니다. 예외 처리 경로보다 깨끗해 보입니다
Sam Saffron

5
이에 대한 또 다른 확장으로 복잡한 조건을 연결해야하는 경우 Comment.all (: conditions => [ "(?)에서 승인 및 id", [1,2,3]])
Omar Qureshi

14
이것은 Rails 4에서 더 이상 사용되지 않습니다 : edgeguides.rubyonrails.org/…
Jonathan Lin

3
@JonathanLin은 정확합니다. mjnissim의 대답이 선호되어야합니다 : stackoverflow.com/a/11457025/33226
Gavin Miller

6
그러면 Array대신을 반환하여 ActiveRecord::Relation나중에 할 수있는 작업을 제한합니다. Comment.where(id: [2, 3, 5])을 반환합니다 ActiveRecord::Relation.
Joshua Pinter

147

업데이트 :이 답변은 Rails 4.x와 관련이 있습니다.

이 작업을 수행:

current_user.comments.where(:id=>[123,"456","Michael Jackson"])

이 방법의 장점은 Relation더 많은 .where절, .limit절 등을 조인 할 수 있는 객체를 반환한다는 점 입니다. 또한 예외를 발생시키지 않고 존재하지 않는 ID를 허용합니다.

최신 Ruby 구문은 다음과 같습니다.

current_user.comments.where(id: [123, "456", "Michael Jackson"])

where배열과 비교할 때 구문 을 확인해 주셔서 감사합니다 . IN문으로 SQL을 코딩해야한다고 생각 했지만 더 깔끔해 보이고 더 이상 사용되지 않습니다 scoped_by_id.
Mark Berry

1
이것이 무엇이며 어떻게 작동합니까? 레일스 매직인가요?! 동료가 언급 한 것처럼 '객체 목록과 정수 비교하기'
atw

22

더 많은 제어가 필요한 경우 (아마도 테이블 이름을 지정해야 함) 다음을 수행 할 수도 있습니다.

Model.joins(:another_model_table_name)
  .where('another_model_table_name.id IN (?)', your_id_array)

정확히 내가 찾던 것. 감사!
Myxtic

your_id_array물건을 되 찾을 때 순서를 유지할 방법이 있습니까?
Joshua Pinter

@ JoshPinter 나는 이것이 데이터베이스가 같은 순서로 물건을 반환 할 것으로 예상되는 신뢰할 수있는 방법이라고 생각하지 않습니다. 아마도 올바른 순서를 보장하기 위해 끝에 ORDER BY 쿼리를 추가하십시오.
Jonathan Lin

@JonathanLin 응답 Jonathan 감사합니다. 당신 말이 맞아요 는 사용 ORDER BY순서가 특성을 기반으로하지 않기 때문에 내 상황에서 작동하지 않습니다. 그러나 SQL을 통해 그렇게 할 수있는 방법이 있으므로 (빠른) 누군가가 그것을 위해 보석을 만들었습니다. 이 Q & A를 확인하십시오 : stackoverflow.com/questions/801824/…
Joshua Pinter

10

이제 .find 및 .find_by_id 메소드는 레일 4에서 더 이상 사용되지 않습니다. 대신 아래에서 사용할 수 있습니다.

Comment.where(id: [2, 3, 5])

일부 ID가 존재하지 않아도 작동합니다. 이것은에서 작동

user.comments.where(id: avoided_ids_array)

ID 제외 용

Comment.where.not(id: [2, 3, 5])

3
github.com/rails/activerecord-deprecated_finders .find 및 .find_by_id 메소드는 레일 4에서 더 이상 사용되지 않습니다.
Canna

0

앱을 종료하는 예외를 피하려면 해당 예외를 포착하고 원하는 방식으로 처리하여 ID를 찾을 수없는 상황에서 앱의 동작을 정의해야합니다.

begin
  current_user.comments.find(ids)
rescue
  #do something in case of exception found
end

루비의 예외에 대한 자세한 정보 는 다음과 같습니다 .


1
네이 문제를 해결하지만, 정말 깨끗한 해결책이 아니다
야쿱 아놀드

3
예외를 잡으려면 예상 한 예외를 선언해야합니다. 그렇지 않으면 예상하지 못한 것을 포착하여 실제 문제를 숨길 위험이 있습니다.
Haegin

0

다른 조건을 넣고 싶다면 named_scope에서도 사용할 수 있습니다

예를 들어 다른 모델을 포함하십시오.

named_scope 'get_by_ids', 람다 {| ids | {: include => [: comments], : conditions => [ "comments.id IN (?)", ids]}}

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