[ruby-on-rails] 둘 이상의 속성으로 find_or_create_를 가로막습니까?

find_or_create_by라는 활성 레코드에 편리한 동적 속성이 있습니다.

Model.find_or_create_by_<attribute>(:<attribute> => "")

그러나 둘 이상의 속성으로 find_or_create를해야하는 경우 어떻게해야합니까?

GroupMember라는 Group과 Member 간의 M : M 관계를 처리하는 모델이 있다고 가정 해 보겠습니다. member_id = 4 인 인스턴스는 여러 개있을 수 있지만 member_id = 4 및 group_id = 7 인 인스턴스는 두 번 이상 필요하지 않습니다.

GroupMember.find_or_create(:member_id => 4, :group_id => 7)

나는 이것을 처리하는 더 좋은 방법이있을 수 있다는 것을 알고 있지만 find_or_create 아이디어의 편의를 좋아합니다.



답변

여러 속성을 다음과 연결할 수 있습니다 and.

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

( find_or_initialize_by기록을 즉시 저장하지 않으려는 경우 사용 )

편집 : 위의 방법은 Rails 4에서 더 이상 사용되지 않습니다. 새로운 방법은 다음과 같습니다.

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create

GroupMember.where(:member_id => 4, :group_id => 7).first_or_initialize

편집 2 : 이 모든 것이 속성에 한정되는 것은 아닙니다.

https://github.com/rails/rails/blob/4-2-stable/guides/source/active_record_querying.md

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

되었다

GroupMember.find_or_create_by(member_id: 4, group_id: 7)


답변

이 스레드를 우연히 발견하지만 상황에 따라 변경 될 수있는 속성을 가진 오브젝트를 찾거나 작성해야하는 다른 사용자는 모델에 다음 방법을 추가하십시오.

# Return the first object which matches the attributes hash
# - or -
# Create new object with the given attributes
#
def self.find_or_create(attributes)
  Model.where(attributes).first || Model.create(attributes)
end

최적화 팁 : 어떤 솔루션을 선택하든 가장 자주 쿼리하는 속성에 대한 인덱스 추가를 고려하십시오.


답변

Rails 4에서는 다음을 수행 할 수 있습니다.

GroupMember.find_or_create_by(member_id: 4, group_id: 7)

그리고 사용법 where이 다릅니다 :

GroupMember.where(member_id: 4, group_id: 7).first_or_create

이것은 다음을 호출 create합니다 GroupMember.where(member_id: 4, group_id: 7):

GroupMember.where(member_id: 4, group_id: 7).create

반대로, find_or_create_by(member_id: 4, group_id: 7)의지는 다음을 요구 create합니다 GroupMember.

GroupMember.create(member_id: 4, group_id: 7)

레일 / 레일 관련 커밋 을 참조하십시오 .


답변

블록을 전달하여 find_or_create 전달하면 객체가 새로 생성 된 경우 추가 될 추가 매개 변수를 전달할 수 있습니다. 검색하지 않는 필드가 있는지 확인하는 경우에 유용합니다.

가정 :

class GroupMember < ActiveRecord::Base
    validates_presence_of :name
end

그때

GroupMember.where(:member_id => 4, :group_id => 7).first_or_create { |gm| gm.name = "John Doe" }

이름이 “John Doe”인 새 GroupMember를 찾지 못하면 member_id 4 and group_id 7


답변

넌 할 수있어:

User.find_or_create_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_create

또는 그냥 초기화하려면 :

User.find_or_initialize_by(first_name: 'Penélope', last_name: 'Lopez')
User.where(first_name: 'Penélope', last_name: 'Lopez').first_or_initialize


답변