찾기 대 find_by 대 어디


127

나는 레일을 처음 사용합니다. 레코드를 찾는 방법이 많이 있다는 것을 알았습니다.

  1. find_by_<columnname>(<columnvalue>)
  2. find(:first, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>).first

그리고 모두 정확히 동일한 SQL을 생성하는 것처럼 보입니다. 또한 여러 레코드를 찾는 경우에도 마찬가지입니다.

  1. find_all_by_<columnname>(<columnvalue>)
  2. find(:all, :conditions => { <columnname> => <columnvalue> }
  3. where(<columnname> => <columnvalue>)

어떤 규칙을 사용할 것인지에 대한 경험 규칙이나 추천 규칙이 있습니까?

답변:


103

자신의 요구에 가장 잘 맞는 것을 사용하십시오.

find방법은 일반적으로 ID별로 행을 검색하는 데 사용됩니다.

Model.find(1)

제공 find한 속성으로 항목을 찾을 수없는 경우 예외가 발생합니다. where예외가 발생하지 않도록 하려면 (아래 설명에 따라 속성을 찾을 수없는 경우 빈 배열을 반환 함)을 사용하십시오.

다른 용도 find는 일반적으로 다음과 같은 것으로 대체됩니다.

Model.all
Model.first

find_by열 내에서 정보를 검색 할 때 도우미로 사용되며 명명 규칙을 사용하여 이러한 정보에 매핑됩니다. 예를 들어, name데이터베이스에 이름이 지정된 열이있는 경우 다음 구문을 사용합니다.

Model.find_by(name: "Bob")

.where 는 일반적인 도우미가하지 않을 때 좀 더 복잡한 논리를 사용할 수있게 해주는 조건입니다. 조건에 맞는 항목의 배열 (또는 빈 배열)을 반환합니다.


62
find_by더 이상 사용되지 않지만 구문이 약간 변경됩니다. 에서 find_by_name("Bob")find_by(:name, "Bob").
Brian Morearty 2016 년

61
@BrianMorearty 나는 당신이 의미한다고 생각합니다find_by(name: "Bob")
MCB

1
@BrianMorearty find_by_...더 이상 사용되지 않는 증거를 찾을 수 없습니다 . 소스가 있습니까? 보인다 find_byfind_by_...모두 여전히 레일에 4 지원
데니스

4
@Dennis, 당신은 그것이 더 이상 사용되지 않는 것이 맞으며, 그것이 내가 말한 것입니다. 그러나 나는 "하지만 구문이 조금 바뀌고있다"고 말했을 때 더 명확 해졌다. 내가 의미하는 바는 "하지만 지금도 새로운 구문을 사용할 수 있습니다." 새로운 구문에 대한 MCB의 수정을 참조하십시오.
Brian Morearty

3
edgeguides.rubyonrails.org/…에 대한 자세한 내용은 rails 4.0 릴리스 "find_by _... 및 find_by _...!를 제외한 모든 동적 방법"에서 언급 된 내용입니다 .
Mukesh Singh Rathaur

131

여기서 ActiveRecord :: Relation을 반환합니다.

이제 find_by 구현을 살펴보십시오.

def find_by
  where(*args).take
end

보시다시피 find_bywhere 와 동일 하지만 하나의 레코드 만 반환합니다. 이 방법은 (1 개) 기록을 받고 사용해야합니다 경우 일부 조건과 모든 레코드를 얻기 위해 사용되어야한다.


1
find_by는 객체를 반환하지만 여기서는 컬렉션을 반환합니다.
Kick Buttowski

때 범위를 벗어 쿼리 값이 find_by구출 ::RangeError에서 where(*args) 와 반환 전무합니다.
fangxing

34

Model.find

1- 매개 변수 : 찾을 개체의 ID입니다.

2- 발견 된 경우 : 오브젝트를 리턴합니다 (한 오브젝트 만).

3- 찾을 수없는 경우 : ActiveRecord::RecordNotFound예외 가 발생합니다.

Model.find_by

1-매개 변수 : 키 / 값

예:

User.find_by name: 'John', email: 'john@doe.com'

2- 발견 된 경우 : 오브젝트를 리턴합니다.

3- 찾을 수없는 경우 :을 반환합니다 nil.

참고 :ActiveRecord::RecordNotFound 사용을 늘리려면find_by!

Model.where

1- 매개 변수 : find_by

2- 발견 된 경우 : ActiveRecord::Relation매개 변수와 일치하는 하나 이상의 레코드를 포함하여 리턴합니다 .

3- 찾을 수없는 경우 : Empty를 반환합니다 ActiveRecord::Relation.


31

사이에 차이가 find하고 find_by있다는 점에서 find찾을 수없는 경우, 반면에 오류가 반환됩니다 find_by널 (null)을 반환합니다은.

find_by email: "haha"반대로 와 같은 방법이 있다면 읽기가 더 쉽습니다 .where(email: some_params).first.


17

Rails 4부터 다음을 수행 할 수 있습니다.

User.find_by(name: 'Bob')

이는 find_by_nameRails 3 과 동일 합니다.

사용 #where하는 경우 #find#find_by충분하지 않습니다.


2
AGIS, 나는 당신과 동의하지만 인터넷을 우리가 사용해야하는 이유 그 이상 검색했습니다 find_by하지를 find_by_<column_name>. 누군가에게 대답하기 위해 필요합니다.
KULKING

Agis, 더 이상 find_by_nameRails 4에서 사용하지 말아야 할 주장을 뒷받침 할만한 자료가 있습니까? 내가 아는 한, 더 이상 사용되지 않습니다 .
Dennis

그렇게하는 간단한 방법이 있지만 이름에 와일드 카드가 있다고 말하면find_by(name: "Rob*")
Batman

1
@Dennis 둘 다 사용할 수 있으며 유효합니다. API가 더 직관적 인 IMHO이므로 새로운 구문을 선호합니다. 그것은 내가 직접 디자인하는 방법입니다 :)
Agis

8

허용 대답은 일반적으로 모든 것을 커버,하지만 난 당신이 업데이트와 같은 방법으로 모델 일을 계획하고, 당신은 (그 하나의 레코드 검색하는 넣다 뭔가를 추가하고 싶습니다 id, 그리고 당신이 모르는를) find_by입니다 레코드를 검색하고 배열에 넣지 않기 때문에 갈 길

irb(main):037:0> @kit = Kit.find_by(number: "3456")
  Kit Load (0.9ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" = 
 '3456' LIMIT 1
=> #<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56",   
updated_at: "2015-05-12 06:10:56", job_id: nil>

irb(main):038:0> @kit.update(job_id: 2)
(0.2ms)  BEGIN Kit Exists (0.4ms)  SELECT 1 AS one FROM "kits" WHERE  
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.5ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE  "kits"."id" = 
1  [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]] 
(0.6ms)  COMMIT => true

그러나 사용 where하면 직접 업데이트 할 수 없습니다

irb(main):039:0> @kit = Kit.where(number: "3456")
Kit Load (1.2ms)  SELECT "kits".* FROM "kits" WHERE "kits"."number" =  
'3456' => #<ActiveRecord::Relation [#<Kit id: 1, number: "3456", 
created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 07:16:58", 
job_id: 2>]>

irb(main):040:0> @kit.update(job_id: 3)
ArgumentError: wrong number of arguments (1 for 2)

이러한 경우 다음과 같이 지정해야합니다

irb(main):043:0> @kit[0].update(job_id: 3)
(0.2ms)  BEGIN Kit Exists (0.6ms)  SELECT 1 AS one FROM "kits" WHERE 
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.6ms)   
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1  
[["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]]
(0.5ms)  COMMIT => true

내가 찾던 정확히
Paul Brunache

2
@kit = Kit.where (number : "3456"). first-직접 업데이트 할 수 있으며 지원 중단
에도 불구

6

허용 된 답변 외에 다음도 유효합니다.

Model.find()ID 배열을 허용하고 일치하는 모든 레코드를 반환합니다. Model.find_by_id(123)또한 배열을 수락하지만 배열에있는 첫 번째 id 값만 처리합니다.

Model.find([1,2,3])
Model.find_by_id([1,2,3])


3

지금까지 주어진 대답은 모두 괜찮습니다.

그러나 흥미로운 차이점은 Model.findID로 검색 한다는 점입니다 . 발견되면 Model객체 (단일 레코드 만)를 반환 하지만 ActiveRecord::RecordNotFound그렇지 않으면 throw합니다 .

Model.find_byModel.find데이터베이스의 열 또는 열 그룹과 매우 유사하고 검색 할 수 있지만 nil검색과 일치하는 레코드가 없으면 반환 합니다.

Model.where반면 에 검색과 일치Model::ActiveRecord_Relation 하는 모든 레코드를 포함하는 배열과 같은 객체를 반환합니다 . 레코드가 없으면 빈 Model::ActiveRecord_Relation개체를 반환 합니다.

나는 이것이 어느 시점에서 어느 것을 사용할지를 결정하는 데 도움이되기를 바랍니다.


3

모델이 있다고 가정 User

  1. User.find(id)

기본 키 = id 인 행을 반환합니다. 반환 유형은 User객체입니다.

  1. User.find_by(email:"abc@xyz.com")

이 경우 속성 또는 이메일이 일치하는 첫 번째 행을 반환합니다. 반환 유형은 User다시 객체입니다.

참고 :- User.find_by(email: "abc@xyz.com")User.find_by_email("abc@xyz.com")

  1. User.where(project_id:1)

속성이 일치하는 users 테이블의 모든 사용자를 반환합니다.

여기서 반환 유형은 ActiveRecord::Relation객체입니다. ActiveRecord::Relation클래스에는 Ruby의 Enumerable모듈이 포함되어 있으므로 배열과 같은 객체를 사용하고 트래버스 할 수 있습니다.


0

모든 오픈 소스 기술을 사용하는 데있어 가장 중요한 부분은 길이와 폭을 검사 할 수 있다는 것입니다. 이 링크 확인

find_by ~> 지정된 조건과 일치하는 첫 번째 레코드를 찾습니다. 묵시적 순서는 없으므로 순서가 중요하면 직접 지정해야합니다. 레코드가 없으면 nil을 리턴합니다.

find ~> 지정된 조건과 일치하는 첫 번째 레코드를 찾습니다. 레코드가 없으면 예외가 발생하지만 의도적으로 수행됩니다.

위의 링크를 확인하십시오. 다음 두 가지 기능에 대한 모든 설명과 사용 사례가 있습니다.


-5

개인적으로 사용하는 것이 좋습니다

where(< columnname> => < columnvalue>)

1
이것은 질문에 대답 할 수 있습니다. 그러나 허용되는 대답 대신 접근 방식 사용의 장단점을 설명하십시오.
Vivek Kumar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.