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.