Answers:
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时,最简单的方法就是将所有外键引用保持相同。
ActiveRecord::VERSION::STRING == "3.2.11"
这里(使用sqlite3适配器),上面的代码对我有用。
您还可以使用如下所示的内容:
Post.create({:id => 10, :title => 'Test'}, :without_protection => true)
尽管如文档所述,这将绕过批量分配安全性。
对于Rails 4:
Post.create(:title => 'Test').update_column(:id, 10)
其他轨道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
因为它将一直有效。此错误可能不会出现在您的开发环境中,但会在说它正在运行的同时悄悄地破坏您的生产数据库。
Post.new.update(id: 10, title: 'Test')
实际上,事实证明,执行以下操作:
p = Post.new(:id => 10, :title => 'Test')
p.save(false)
validate: false
,这仍然有效,而不是简单地false
。但是,您仍然遇到保护属性的问题-我在回答中概述了一种单独的方法。
将此create_with_id函数放在您seed.rb的顶部,然后用它在需要显式ID的地方创建对象。
def create_with_id(clazz, params)
obj = clazz.send(:new, params)
obj.id = params[:id]
obj.save!
obj
end
像这样使用
create_with_id( Foo, {id:1,name:"My Foo",prop:"My other property"})
而不是使用
Foo.create({id:1,name:"My Foo",prop:"My other property"})
这种情况是类似的问题,有必要id
使用一种自定义日期覆盖:
# 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
然后 :
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">
回调工作正常。
祝好运!。
id
基于Unix的时间戳。我已经在里面做了before_create
。工作良好。
对于Rails 3中,要做到这一点最简单的方法是使用new
与without_protection
细化,然后save
:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save
对于种子数据,可以绕开验证,如下所示:
Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save(validate: false)
实际上,我们已经在ActiveRecord :: Base中添加了一个辅助方法,该方法在执行种子文件之前立即声明:
class ActiveRecord::Base
def self.seed_create(attributes)
new(attributes, without_protection: true).save(validate: false)
end
end
现在:
Post.seed_create(:id => 10, :title => 'Test')
对于Rails 4,您应该使用StrongParams而不是受保护的属性。在这种情况下,您无需分配任何标志即可简单地进行分配和保存new
:
Post.new(id: 10, title: 'Test').save # optionally pass `{validate: false}`
{}
上面塞缪尔(Samuel)的答案中,这对我不起作用(Rails3)。
id
仍然是10
id
被传递为10-因此,它应该是正确的。如果那不是您所期望的,可以举个例子澄清一下吗?