Rails destroy all but newest n records

后端 未结 7 923
眼角桃花
眼角桃花 2021-02-18 17:00

How do I destroy all but the newest n records using Rails\' ActiveRecord?

I can get the newest n records using order and limit but how do I destroy the inverse?

相关标签:
7条回答
  • 2021-02-18 17:35

    Previous answers use find or last require the creation of ActiveModel, which take extra computation time.

    I think using pluck is better, since it only creates an Array of ids.

    ids = Foo.limit(n).order('id DESC').pluck(:id)
    Foo.where('id NOT IN (?)', ids).destroy_all
    
    0 讨论(0)
  • 2021-02-18 17:36

    I have two methods of doing this, assuming n = 5:

    Foo.order('id desc').offset(5).destroy_all
    

    This sorts records with latest first, and destroys everything past the 5th records. Or

    Foo.destroy_all(['id <= ?', Foo.order('id desc').limit(1).offset(5).first.id])
    

    This finds the 6th latest record id and deletes all records with id <= 6th latest record id.

    Also, you might want to look at this SO question.

    0 讨论(0)
  • 2021-02-18 17:39

    None of these work in Rails 6, but delete_by does.

    keep_ids = [2345, 345256, 34]
    Component.delete_by('id NOT IN (?) AND status = "inactive"', keep_ids) }
    
    0 讨论(0)
  • 2021-02-18 17:40

    [Rails 5 / ActiveRecord::Relation]

    destroy_all no longer takes parameters... Actually, the ActiveRecord::Relation never allowed parameters I don't think... Anyway, you should just put the condition before it, but use destroy_all after the query, like this:

    Person.destroy_all("last_login < '2004-04-04'")
    Person.destroy_all(status: "inactive")
    Person.where(age: 0..18).destroy_all
    
    0 讨论(0)
  • 2021-02-18 17:47

    Either of these methods would do it:

    # Fetch your latest N records
    newest_n_records = Foo.find(:all, :order => 'created_at DESC', :limit => n)
    
    # Then do:
    Foo.destroy_all(['id NOT IN (?)', newest_n_records.collect(&:id)])
    
    # Or:
    Foo.destroy_all('created_at < ?', newest_n_records.last.created_at)
    
    0 讨论(0)
  • 2021-02-18 17:50
    Foo.destroy_all(['id NOT IN (?)', Foo.last(1000).collect(&:id)])
    
    0 讨论(0)
提交回复
热议问题