当前位置:  开发笔记 > 编程语言 > 正文

在ActiveRecord中覆盖create上的id

如何解决《在ActiveRecord中覆盖create上的id》经验,为你挑选了8个好方法。

是否有任何方法可以在创建时覆盖模型的id值?就像是:

Post.create(:id => 10, :title => 'Test')

会是理想的,但显然不会奏效.



1> 小智..:

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 3.2.11

2> 小智..:

尝试

a_post = Post.new do |p| 
  p.id = 10
  p.title = 'Test'
  p.save
end

应该给你你想要的东西.


不确定为什么你会被投票,这对我很有用

3> Samuel Heane..:

你也可以使用这样的东西:

Post.create({:id => 10, :title => 'Test'}, :without_protection => true)

虽然如文档中所述,但这将绕过质量分配安全性.


唉,这不再适用于Rails 4,他们删除了选项哈希

4> Rick Smith..:

对于Rails 4:

Post.create(:title => 'Test').update_column(:id, 10)

其他轨道4个回答并没有为我工作.在使用Rails控制台检查时,其中许多似乎发生了变化,但当我检查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您仍会遇到此问题.手动更改之idp.id = 10也会产生此问题.

一般来说,我会使用update_column更改,id即使它需要额外的数据库查询,因为它将一直工作.这是一个错误,可能不会出现在您的开发环境中,但可以悄悄地破坏您的生产数据库,同时说它正在运行.


这也是我在控制台的rails 3.2.22情况下工作的唯一方法.使用'save'变体的答案没有效果.

5> Codebeef..:

实际上,事实证明,做以下工作:

p = Post.new(:id => 10, :title => 'Test')
p.save(false)



6> Nic Benders..:

正如杰夫指出的那样,id表现得好像是attr_protected.为防止这种情况,您需要覆盖默认受保护属性的列表.在属性信息可以来自外部的任何地方都要小心.出于某种原因,id字段是默认保护的.

class Post < ActiveRecord::Base

  private

  def attributes_protected_by_default
    []
  end
end

(使用ActiveRecord 2.3.5测试)



7> 小智..:

我们可以覆盖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)



8> Sean Cameron..:
Post.create!(:title => "Test") { |t| t.id = 10 }

这并不会让我觉得你通常会想做的事情,但如果你需要使用一组固定的id填充一个表(例如使用rake任务创建默认值)并且你想要覆盖自动递增(这样每次运行任务时,表都会填充相同的ID):

post_types.each_with_index do |post_type|
  PostType.create!(:name => post_type) { |t| t.id = i + 1 }
end

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有