Oluşturma sırasında bir modelin kimlik değerini geçersiz kılmanın bir yolu var mı? Gibi bir şey:
Post.create(:id => 10, :title => 'Test')
ideal olurdu, ama belli ki işe yaramayacak.
Oluşturma sırasında bir modelin kimlik değerini geçersiz kılmanın bir yolu var mı? Gibi bir şey:
Post.create(:id => 10, :title => 'Test')
ideal olurdu, ama belli ki işe yaramayacak.
Yanıtlar:
id sadece attr_protected, bu yüzden onu ayarlamak için toplu atamayı kullanamazsınız. Bununla birlikte, manuel olarak ayarlarken, sadece çalışır:
o = SomeObject.new
o.id = 8888
o.save!
o.reload.id # => 8888
Orijinal motivasyonun ne olduğundan emin değilim, ancak bunu ActiveHash modellerini ActiveRecord'a dönüştürürken yapıyorum. ActiveHash, ActiveRecord'da aynı names_to semantiğini kullanmanıza izin verir, ancak bir geçiş yapmak ve bir tablo oluşturmak ve her aramada veritabanının ek yükünü üstlenmek yerine, verilerinizi yml dosyalarında depolamanız yeterlidir. Veritabanındaki yabancı anahtarlar yml'deki bellek içi kimliklere başvurur.
ActiveHash, seyrek olarak değişen ve yalnızca geliştiriciler tarafından değişen seçim listeleri ve küçük tablolar için mükemmeldir. Bu nedenle, ActiveHash'tan ActiveRecord'a geçerken, tüm yabancı anahtar referanslarını aynı tutmak en kolayıdır.
ActiveRecord::VERSION::STRING == "3.2.11"
(sqlite3 adaptörüyle) ve yukarıdakiler benim için çalışıyor.
Deneyin
a_post = Post.new do |p|
p.id = 10
p.title = 'Test'
p.save
end
bu size aradığınız şeyi vermelidir.
Bunun gibi bir şey de kullanabilirsiniz:
Post.create({:id => 10, :title => 'Test'}, :without_protection => true)
Belgelerde belirtildiği gibi , bu toplu atama güvenliğini atlayacaktır.
Raylar 4 için:
Post.create(:title => 'Test').update_column(:id, 10)
Diğer Raylar 4 cevaplar vermedi değil benim için çalış. Birçoğu Rails Konsolunu kontrol ederken değişiyor gibi görünüyordu , ancak MySQL veritabanındaki değerleri kontrol ettiğimde değişmeden kaldılar. Diğer cevaplar sadece bazen işe yaradı.
MySQL için en azından atanırken id
otomatik artış id numarasının altında yok değil kullandığınız sürece işe update_column
. Örneğin,
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
Eğer değiştirirseniz create
kullanmak new
+ save
hala bu sorun olacaktır. El ile değişen id
gibi p.id = 10
de bu sorunu üretir.
Genel olarak, fazladan bir veritabanı sorgusuna mal olsa bile, her zaman çalışacağı update_column
için değiştirmek için kullanırdım id
. Bu, geliştirme ortamınızda görünmeyebilecek bir hatadır, ancak çalıştığını söylerken üretim veritabanınızı sessizce bozabilir.
Post.new.update(id: 10, title: 'Test')
Aslında şu işe yaradığı ortaya çıktı:
p = Post.new(:id => 10, :title => 'Test')
p.save(false)
validate: false
, basitçe yerine geçerseniz yine de çalışır false
. Ancak yine de korumalı öznitelik sorunuyla karşılaşıyorsunuz - cevabımda ana hatlarıyla açıkladığım ayrı bir yol var.
Jeff'in işaret ettiği gibi, id attr_protectedmış gibi davranır. Bunu önlemek için, varsayılan korumalı öznitelikler listesini geçersiz kılmanız gerekir. Öznitelik bilgilerinin dışarıdan gelebileceği her yerde bunu yaparken dikkatli olun. Kimlik alanı bir nedenle varsayılan olarak korunmaktadır.
class Post < ActiveRecord::Base
private
def attributes_protected_by_default
[]
end
end
(ActiveRecord 2.3.5 ile test edilmiştir)
nitelikleri geçersiz kılabiliriz_protected_by_varsayılan
class Example < ActiveRecord::Base
def self.attributes_protected_by_default
# default is ["id", "type"]
["type"]
end
end
e = Example.new(:id => 10000)
Post.create!(:title => "Test") { |t| t.id = 10 }
Bu bana normalde yapmak isteyeceğiniz türden bir şey olarak gelmiyor, ancak bir tabloyu sabit bir kimlikle doldurmanız gerekiyorsa (örneğin, bir rake görevi kullanarak varsayılanlar oluştururken) ve siz otomatik artırmayı geçersiz kılmak istiyorsanız (böylece görevi her çalıştırdığınızda tablo aynı kimliklerle doldurulur):
post_types.each_with_index do |post_type|
PostType.create!(:name => post_type) { |t| t.id = i + 1 }
end
Bu create_with_id işlevini seeds.rb'nizin en üstüne koyun ve sonra bunu, açık kimliklerin istendiği nesne oluşturma işleminizi yapmak için kullanın.
def create_with_id(clazz, params)
obj = clazz.send(:new, params)
obj.id = params[:id]
obj.save!
obj
end
ve böyle kullan
create_with_id( Foo, {id:1,name:"My Foo",prop:"My other property"})
kullanmak yerine
Foo.create({id:1,name:"My Foo",prop:"My other property"})
Bu vaka, bir id
tür özel tarih ile üzerine yazılması gereken benzer bir sorundur :
# in app/models/calendar_block_group.rb
class CalendarBlockGroup < ActiveRecord::Base
...
before_validation :parse_id
def parse_id
self.id = self.date.strftime('%d%m%Y')
end
...
end
Ve sonra :
CalendarBlockGroup.create!(:date => Date.today)
# => #<CalendarBlockGroup id: 27072014, date: "2014-07-27", created_at: "2014-07-27 20:41:49", updated_at: "2014-07-27 20:41:49">
Geri aramalar iyi çalışıyor.
İyi şanslar!.
id
Unix'e dayalı bir zaman damgası oluşturmam gerekiyordu . Bunu içeride yaptım before_create
. İyi çalışıyor.
Rails 3 için bunu yapmanın en basit yolu new
, without_protection
iyileştirme ile kullanmak ve ardından save
:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save
Tohum verileri için, şu şekilde yapabileceğiniz doğrulamayı atlamak mantıklı olabilir:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save(validate: false)
Aslında ActiveRecord :: Base'e çekirdek dosyaları çalıştırmadan hemen önce bildirilen bir yardımcı yöntem ekledik:
class ActiveRecord::Base
def self.seed_create(attributes)
new(attributes, without_protection: true).save(validate: false)
end
end
Ve şimdi:
Post.seed_create(:id => 10, :title => 'Test')
Rails 4 için, korumalı öznitelikler yerine StrongParams kullanmalısınız. Bu durumda, şunlara herhangi bir bayrak iletmeden kolayca atayabilir ve kaydedebilirsiniz new
:
Post.new(id: 10, title: 'Test').save # optionally pass `{validate: false}`
{}
Yukarıdaki Samuel'in cevabı olarak nitelikler koymadan benim için işe yaramıyor (Rails3).
id
hala 10
id
10 olarak geçti - yani tam olarak olması gereken bu. Beklediğiniz bu değilse, bir örnekle açıklayabilir misiniz?