Overriding id on create in ActiveRecord

后端 未结 13 2555
自闭症患者
自闭症患者 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 05:46

    Try

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

    that should give you what you're looking for.

    0 讨论(0)
  • 2020-11-28 05:46

    As Jeff points out, id behaves as if is attr_protected. To prevent that, you need to override the list of default protected attributes. Be careful doing this anywhere that attribute information can come from the outside. The id field is default protected for a reason.

    class Post < ActiveRecord::Base
    
      private
    
      def attributes_protected_by_default
        []
      end
    end
    

    (Tested with ActiveRecord 2.3.5)

    0 讨论(0)
  • 2020-11-28 05:59

    For Rails 4:

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

    Other Rails 4 answers did not work for me. Many of them appeared to change when checking using the Rails Console, but when I checked the values in MySQL database, they remained unchanged. Other answers only worked sometimes.

    For MySQL at least, assigning an id below the auto increment id number does not work unless you use update_column. For example,

    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
    

    If you change create to use new + save you will still have this problem. Manually changing the id like p.id = 10 also produces this problem.

    In general, I would use update_column to change the id even though it costs an extra database query because it will work all the time. This is an error that might not show up in your development environment, but can quietly corrupt your production database all the while saying it is working.

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

    This case is a similar issue that was necessary overwrite the id with a kind of custom date :

    # 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
    

    And then :

    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">
    

    Callbacks works fine.

    Good Luck!.

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

    In Rails 4.2.1 with Postgresql 9.5.3, Post.create(:id => 10, :title => 'Test') works as long as there isn't a row with id = 10 already.

    0 讨论(0)
  • 2020-11-28 06:02
    Post.create!(:title => "Test") { |t| t.id = 10 }
    

    This doesn't strike me as the sort of thing that you would normally want to do, but it works quite well if you need to populate a table with a fixed set of ids (for example when creating defaults using a rake task) and you want to override auto-incrementing (so that each time you run the task the table is populate with the same ids):

    post_types.each_with_index do |post_type|
      PostType.create!(:name => post_type) { |t| t.id = i + 1 }
    end
    
    0 讨论(0)
提交回复
热议问题