생성시 모델의 ID 값을 재정의하는 방법이 있습니까? 다음과 같은 것 :
Post.create(:id => 10, :title => 'Test')
이상적이지만 분명히 작동하지 않습니다.
답변
id는 attr_protected 뿐이므로 대량 할당을 사용하여 설정할 수 없습니다. 그러나 수동으로 설정하면 다음과 같이 작동합니다.
o = SomeObject.new
o.id = 8888
o.save!
o.reload.id # => 8888
원래 동기가 뭔지는 모르겠지만 ActiveHash 모델을 ActiveRecord로 변환 할 때 이렇게합니다. ActiveHash를 사용하면 ActiveRecord에서 동일한 belongs_to 시맨틱을 사용할 수 있지만 마이그레이션하고 테이블을 생성하고 모든 호출에서 데이터베이스 오버 헤드를 발생시키는 대신 yml 파일에 데이터를 저장하기 만하면됩니다. 데이터베이스의 외래 키는 yml의 메모리 내 ID를 참조합니다.
ActiveHash는 자주 변경되지 않고 개발자 만 변경하는 선택 목록 및 작은 테이블에 적합합니다. 따라서 ActiveHash에서 ActiveRecord로 이동할 때 모든 외래 키 참조를 동일하게 유지하는 것이 가장 쉽습니다.
답변
시험
a_post = Post.new do |p|
p.id = 10
p.title = 'Test'
p.save
end
그것은 당신이 찾고있는 것을 당신에게 줄 것입니다.
답변
다음과 같이 사용할 수도 있습니다.
Post.create({:id => 10, :title => 'Test'}, :without_protection => true)
문서에 명시되어 있지만 이는 대량 할당 보안을 우회합니다.
답변
Rails 4 :
Post.create(:title => 'Test').update_column(:id, 10)
다른 Rails 4 답변은 저에게 효과적 이지 않았습니다 . Rails Console을 사용하여 확인할 때 대부분 변경된 것처럼 보였지만 MySQL 데이터베이스에서 값을 확인했을 때 변경되지 않았습니다. 다른 답변은 때때로 효과가있었습니다.
최소한 MySQL의 경우를 사용하지 않는 한 id
자동 증가 ID 번호 아래에 할당하면 작동 하지 않습니다update_column
. 예를 들면
p = Post.create(:title => 'Test')
p.id
=> 20 # 20 was the id the auto increment gave it
p2 = Post.create(:id => 40, :title => 'Test')
p2.id
=> 40 # 40 > the next auto increment id (21) so allow it
p3 = Post.create(:id => 10, :title => 'Test')
p3.id
=> 10 # Go check your database, it may say 41.
# Assigning an id to a number below the next auto generated id will not update the db
+ create
를 사용하도록 변경 하면 여전히이 문제가 발생합니다. 유사 항목을 수동으로 변경해도이 문제가 발생합니다.new
save
id
p.id = 10
일반적으로 항상 작동하므로 추가 데이터베이스 쿼리가 필요하더라도 update_column
변경하는 데 사용 합니다 id
. 이것은 개발 환경에 표시되지 않을 수있는 오류이지만 작동 중이라고 말하면서 프로덕션 데이터베이스를 조용히 손상시킬 수 있습니다.
답변
실제로 다음 작업을 수행하는 것으로 나타났습니다.
p = Post.new(:id => 10, :title => 'Test')
p.save(false)
답변
Jeff가 지적했듯이 id는 attr_protected 인 것처럼 동작합니다. 이를 방지하려면 기본 보호 속성 목록을 재정의해야합니다. 속성 정보가 외부에서 올 수있는 모든 곳에서이 작업을 수행하도록주의하십시오. id 필드는 기본적으로 보호됩니다.
class Post < ActiveRecord::Base
private
def attributes_protected_by_default
[]
end
end
(ActiveRecord 2.3.5로 테스트)
답변
attributes_protected_by_default를 재정의 할 수 있습니다.
class Example < ActiveRecord::Base
def self.attributes_protected_by_default
# default is ["id", "type"]
["type"]
end
end
e = Example.new(:id => 10000)