Find_or_create_by adlı kişiyi birden fazla özelliğe bağlar mı?


203

Aktif kayıtta find_or_create_by adlı kullanışlı bir dinamik özellik var:

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

Ama birden fazla özniteliğe göre find_veya_oluşturmam gerekirse ne olur?

Diyelim ki Grup ile Üye arasında GroupMember adlı bir M: M ilişkisini ele alacak bir modelim var. Üye_id = 4 nerede birçok örnekleri olabilir, ama ben asla birden fazla kez burada member_id = 4 ve group_id = 7 istemiyorum. Böyle bir şey yapmak mümkün olup olmadığını anlamaya çalışıyorum:

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

Bunun üstesinden gelmenin daha iyi yolları olabileceğinin farkındayım, ama find_or_create fikrinin kolaylığını seviyorum.

Yanıtlar:


465

Birden çok özellik aşağıdakilerle bağlanabilir and:

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

( find_or_initialize_bykaydı hemen kaydetmek istemiyorsanız kullanın)

Düzenleme: Yukarıdaki yöntem Rails 4'te kullanımdan kaldırılmıştır. Bunu yapmanın yeni yolu:

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

ve

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

Edit 2: Bunların hepsi raylar dışında sadece belirli olanları hesaba katmadı.

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

Misal

GroupMember.find_or_create_by_member_id_and_group_id(4, 7)

oldu

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

Ayrıca github.com/seamusabshere/upsert'i de beğenebilirsiniz - ilk argüman, bir kaydı bulmak veya oluşturmak için kullanılan bir özellik
— karmasıdır

1
İlklendirmenin, first_or_create durumunda çağrılabilecek new () yerine create () işlevini çağırdığını unutmayın.
— Sumit

Bazıları bu kullanımın özlü bir örneğini paylaşabilir mi? Yerleşimine ve çağrısına aşina değilim.
— 6ft Dan

Birçok kişi henüz Rails 4'ü kullanmadığı için Rails 3 kodunun kaldırılmasını geri aldım.
— Kyle Heironimus

Sadece eklemek için: find_or_create_by _ * () işlevleri Rails 4'te kullanımdan kaldırılmıştır, ancak find_or_create_by () DEĞİLDİR. Find_or_create_by () yöntemini kullanmakta bir sakınca yoktur. Bunun eklendiği taahhüdü kontrol edin github.com/rails/rails/commit/… ve kullanım için resmi Rails 4.2 belgelerine bakın: guides.rubyonrails.org/v4.2.0/…
— CodeExpress

33

Bu iş parçacığında tökezleyen ancak koşullara bağlı olarak değişebilecek niteliklere sahip bir nesne bulması veya oluşturması gereken herkes için, modelinize aşağıdaki yöntemi ekleyin:

# 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

Optimizasyon ipucu: Hangi çözümü seçerseniz seçin, en sık sorguladığınız özellikler için dizinler eklemeyi düşünün.


8
Unutulmaması gereken bir nokta, bunun toplu olarak atanamayan nitelikleri işlemeyecek olmasıdır find_or_create_by.
— x1a4

1
Marco, dene Model.where(attributes).instance_eval{|q| q.first || q.create}.
— hiroshi

3
find_or_createayrıca where….first || createbir yarış koşulu tanıtan bir işlem kullanma yararına sahiptir
— mrm

Ben def self.find_or_create(attributes) self.where(attributes).first || self.create(attributes) endtekrarlamak gerekmez ki söyleyebilirim Model
— Augustin Riedinger

@AugustinRiedinger selfYöntem gövdesi içinde de ihtiyacınız yoktur (kelimeleri kaldırmak istediğiniz için!).
— David Tuite

31

Rails 4'te şunları yapabilirsiniz:

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

Ve kullanımı wherefarklı:

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

Bu arayacak createüzerinde GroupMember.where(member_id: 4, group_id: 7):

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

Aksine, find_or_create_by(member_id: 4, group_id: 7)arayacak createüzerinde GroupMember:

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

Lütfen raylar / raylar hakkındaki ilgili taahhüdüne bakın .


16

Bir bloğu geçirerek find_or_createnesneye yeni oluşturulursa eklenecek ek parametreler iletebilirsiniz. Bu, aramadığınız bir alanın varlığını doğrularsanız kullanışlıdır.

varsayarsak:

class GroupMember < ActiveRecord::Base
    validates_presence_of :name
end

sonra

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

"John Doe" adında yeni bir GroupMember oluşturacak. member_id 4 and group_id 7


4

Yapabilirsin:

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

Veya sadece başlatmak için:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.