Rails는 마법을 만들거나 업데이트합니까?
CachedObject
키로 인덱싱 된 일반 직렬화 된 객체를 저장 하는 클래스 가 있습니다. 이 클래스가 create_or_update
메서드 를 구현하기를 원합니다 . 개체가 발견되면 업데이트하고, 그렇지 않으면 새 개체를 만듭니다.
Rails에서이 작업을 수행 할 수있는 방법이 있습니까? 아니면 내 자신의 방법을 작성해야합니까?
"upsert"(데이터베이스가 동일한 작업에서 업데이트 또는 삽입 문을 실행하는) 유형의 문을 찾는 경우에는 해당되지 않습니다. 기본적으로 Rails 및 ActiveRecord에는 이러한 기능이 없습니다. 그러나 upsert gem을 사용할 수 있습니다 .
: 그렇지 않으면, 당신은 사용할 수 있습니다 find_or_initialize_by
또는 find_or_create_by
대부분의 경우에, 전혀 거의 문제가 없다, 추가 데이터베이스 히트의 비용이기는하지만, 비슷한 기능을 제공한다. 따라서 심각한 성능 문제가 없으면 gem을 사용하지 않을 것입니다.
예를 들어, "Roger"라는 이름을 가진 사용자가 없으면 새 사용자 인스턴스가 name
"Roger"로 설정된 상태로 인스턴스화됩니다 .
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
또는 find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
Rails 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
블록을 사용할 수 있지만 블록은 레코드가 new 인 경우에만 실행됩니다 .
User.where(name: "Roger").first_or_initialize do |user|
# this won't run if a user with name "Roger" is found
user.save
end
User.find_or_initialize_by(name: "Roger") do |user|
# this also won't run if a user with name "Roger" is found
user.save
end
레코드의 지속성에 관계없이 블록을 사용 tap
하려면 결과에 사용 하십시오.
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end
Rails 4에서는 특정 모델에 추가 할 수 있습니다.
def self.update_or_create(attributes)
assign_or_new(attributes).save
end
def self.assign_or_new(attributes)
obj = first || new
obj.assign_attributes(attributes)
obj
end
다음과 같이 사용하십시오.
User.where(email: "a@b.com").update_or_create(name: "Mr A Bbb")
또는 이니셜 라이저에있는 모든 모델에 이러한 메서드를 추가하려는 경우 :
module ActiveRecordExtras
module Relation
extend ActiveSupport::Concern
module ClassMethods
def update_or_create(attributes)
assign_or_new(attributes).save
end
def update_or_create!(attributes)
assign_or_new(attributes).save!
end
def assign_or_new(attributes)
obj = first || new
obj.assign_attributes(attributes)
obj
end
end
end
end
ActiveRecord::Base.send :include, ActiveRecordExtras::Relation
Add this to your model:
def self.update_or_create_by(args, attributes)
obj = self.find_or_create_by(args)
obj.update(attributes)
return obj
end
With that, you can:
User.update_or_create_by({name: 'Joe'}, attributes)
The magic you have been looking for has been added in Rails 6
Now you can upsert(update or insert).
Model.upsert(column_name: value)
Note: For bulk update or create you can use upsert_all
You can do it in one statement like this:
CachedObject.where(key: "the given key").first_or_create! do |cached|
cached.attribute1 = 'attribute value'
cached.attribute2 = 'attribute value'
end
Old question but throwing my solution into the ring for completeness. I needed this when I needed a specific find but a different create if it doesn't exist.
def self.find_by_or_create_with(args, attributes) # READ CAREFULLY! args for finding, attributes for creating!
obj = self.find_or_initialize_by(args)
return obj if obj.persisted?
return obj if obj.update_attributes(attributes)
end
The sequel gem adds an update_or_create method which seems to do what you're looking for.
참고URL : https://stackoverflow.com/questions/18747062/rails-create-or-update-magic
'developer tip' 카테고리의 다른 글
TFS에서 다른 사용자의 체크 아웃을 실행 취소하는 방법은 무엇입니까? (0) | 2020.09.09 |
---|---|
jQuery UI 자동 완성에서 결과 없음 감지 (0) | 2020.09.09 |
기능적 언어 (특히 Erlang)는 어떻게 / 왜 잘 확장됩니까? (0) | 2020.09.09 |
JavaScript에는 "단락"평가가 있습니까? (0) | 2020.09.08 |
ADO.NET Entity Framework : 업데이트 마법사가 테이블을 추가하지 않습니다. (0) | 2020.09.08 |