【问题标题】:Delete old records on Heroku (Rails 3.1) via rake task通过 rake 任务删除 Heroku (Rails 3.1) 上的旧记录
【发布时间】:2012-02-19 00:33:28
【问题描述】:

我似乎无法从 heroku 上的应用中删除旧记录。

当前 heroku 调度器运行:

class Post < ActiveRecord::Base

def self.get_data
  # this populates my app but the database is starting to get large and I don't need the old records
  scr = Scrape.new
  data_array = scr.scrape
  store_data(data_array)
  # destroy_old_data
end

但我想取消注释“destory_old_data”调用。

def destroy_old_data
  # oldest = Post.where("updated_at > ?", 30.days.ago)
  # Post.delete_all("updated_at > ?", 30.days.ago)
  # Post.destroy_all("updated_at > ?", 30.days.ago)
  oldest = Post.find(:all, "updated_at > ?", 30.days.ago)
  oldest.destroy
end

如您所见,我尝试了一些似乎可以在控制台本地运行的东西,但我无法让它们在 heroku 上运行。

我得到的错误是这样的:

ArgumentError: wrong number of arguments (2 for 1)

or

when using Post.find
NoMethodError: undefined method `destroy' for #<Array:0x00000004579898>

要成功找到并删除所有这些旧记录,我能做的最简单的调用是什么?

任何帮助将不胜感激。

【问题讨论】:

  • 您是否在oldest = Post.find(:all, "updated_at"...) 上收到该错误?
  • 不,我得到:NoMethodError: undefined method `destroy' for #<0x00000004579898>

标签: ruby-on-rails database activerecord heroku


【解决方案1】:

您正在尝试“删除”数组,即帖子列表。您应该改为对该列表中的每个项目调用删除。

Post.where(["updated_at > ?", 30.days.ago]).each do |post|
  post.delete
end

哪里,接受一个论点。并返回符合其条件的帖子列表。然后,您可以遍历这些帖子并对每个帖子执行操作 (delete)。

【讨论】:

  • 这返回了一个空数组(意思是:=> [])。我有超过 30 天的帖子。做一个 Post.first 会返回一条记录,updated_at: "2011-12-23 19:01:53"
  • 如果我错了,请纠正我,但这只会返回 30 天前创建的帖子,而不是所有超过 30 天的帖子。
  • 你是对的,我从问题中复制粘贴了错误的代码。更新为使查询返回 greater then 30 days ago
【解决方案2】:

要解决 NoMethodError,您需要遍历记录数组并在每个记录上调用 destroy

oldest.each { |r| r.destroy }

或者您可以使用destroy_all 之类的方法,您甚至不需要额外的findhttp://apidock.com/rails/ActiveRecord/Base/destroy_all/class

Post.destroy_all(['updated_at < ?', 30.days.ago])

将条件放入数组中应该可以解决@luke-chadwick 在他的回答中提到的ArgumentError

要考虑的一个问题是您要删除多少条记录(这是来自文档的注释):

注意:当您一次删除多条记录时,每条记录的实例化、回调执行和删除可能会很耗时。它为每条记录生成至少一个 SQL DELETE 查询(或者可能更多,以强制执行您的回调)。如果您想快速删除许多行,而不用担心它们的关联或回调,请改用 delete_all。

delete_all 可能是您更快的选择,除非您还需要清理其他相关记录,例如评论。

【讨论】:

  • 只是指出一个错误:不应使用 &gt; 运算符,因为它会使 ActiveRecord 销毁 30 天旧的数据。请改用&lt;
【解决方案3】:

Post.destroy_all 方法接受可以传递给 find(:all) 的条件参数的任何内容。这包括字符串、散列或数组。

如果您在 documentation 中显示源代码来销毁所有内容,您应该会看到:

# File activerecord/lib/active_record/base.rb, line 879
def destroy_all(conditions = nil)
  find(:all, :conditions => conditions).each { |object| object.destroy }
end

如您所见,它需要一个参数。所以条件需要用数组大括号包裹起来(如图):

Post.destroy_all(['updated_at > ?', 30.days.ago])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-03
    • 2012-09-26
    • 2011-08-30
    • 2013-09-14
    • 2011-01-15
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多