Overriding id on create in ActiveRecord

后端 未结 13 2557
自闭症患者
自闭症患者 2020-11-28 05:07

Is there any way of overriding a model\'s id value on create? Something like:

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

would be ide

相关标签:
13条回答
  • 2020-11-28 06:02

    For Rails 3, the simplest way to do this is to use new with the without_protection refinement, and then save:

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

    For seed data, it may make sense to bypass validation which you can do like this:

    Post.new({:id => 10, :title => 'Test'}, :without_protection => true).save(validate: false)
    

    We've actually added a helper method to ActiveRecord::Base that is declared immediately prior to executing seed files:

    class ActiveRecord::Base
      def self.seed_create(attributes)
        new(attributes, without_protection: true).save(validate: false)
      end
    end
    

    And now:

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

    For Rails 4, you should be using StrongParams instead of protected attributes. If this is the case, you'll simply be able to assign and save without passing any flags to new:

    Post.new(id: 10, title: 'Test').save      # optionally pass `{validate: false}`
    
    0 讨论(0)
  • 2020-11-28 06:04

    id is just attr_protected, which is why you can't use mass-assignment to set it. However, when setting it manually, it just works:

    o = SomeObject.new
    o.id = 8888
    o.save!
    o.reload.id # => 8888
    

    I'm not sure what the original motivation was, but I do this when converting ActiveHash models to ActiveRecord. ActiveHash allows you to use the same belongs_to semantics in ActiveRecord, but instead of having a migration and creating a table, and incurring the overhead of the database on every call, you just store your data in yml files. The foreign keys in the database reference the in-memory ids in the yml.

    ActiveHash is great for picklists and small tables that change infrequently and only change by developers. So when going from ActiveHash to ActiveRecord, it's easiest to just keep all of the foreign key references the same.

    0 讨论(0)
  • 2020-11-28 06:04

    Actually, it turns out that doing the following works:

    p = Post.new(:id => 10, :title => 'Test')
    p.save(false)
    
    0 讨论(0)
  • 2020-11-28 06:04

    you can insert id by sql:

      arr = record_line.strip.split(",")
      sql = "insert into records(id, created_at, updated_at, count, type_id, cycle, date) values(#{arr[0]},#{arr[1]},#{arr[2]},#{arr[3]},#{arr[4]},#{arr[5]},#{arr[6]})"
      ActiveRecord::Base.connection.execute sql
    
    0 讨论(0)
  • 2020-11-28 06:06

    You could also use something like this:

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

    Although as stated in the docs, this will bypass mass-assignment security.

    0 讨论(0)
  • 2020-11-28 06:10

    we can override 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)
    
    0 讨论(0)
提交回复
热议问题