【问题标题】:Rails creating records with timestamps set to nil, 'heroku restart' solves itRails 创建时间戳设置为零的记录,'heroku restart' 解决了它
【发布时间】:2015-07-16 19:51:16
【问题描述】:

我有一个 Rails 4 应用程序在实时生产站点上显示出一些奇怪的行为。通常在创建 Post 时,默认的 Rails 时间戳(created_at 和 updated_at)被设置为 nil,解决它的唯一方法是重新启动 Heroku dynos。

重启 Heroku 后,我可以再次创建 PostsPost 正在创建中,但它的时间戳被简单地设置为 nil。因此,当我单击“创建帖子”时,服务器会抛出 500 错误,因为我的帖子视图中有一些代码比较时间戳。

这不会发生在我的本地开发环境中,只会发生在实时 Heroku 服务器上。

有人经历过吗?如果它在本地工作正常并且“heroku重启”修复它(暂时),它真的是代码中的错误吗?我的应用程序已危险地接近内存耗尽,这可能与此有关吗?

这是我的帖子create 定义:

def create
    @post = Post.new(post_params)
    @post.user_id = current_user.id

    @post.user.increment!(:level, 20)

    if @post.save

        Subscription.create(:user_id => current_user.id, :post_id => @post.id, :comments_count => 0, :updated_at => (Time.now - 1.minute))

        User.where(:auto_sub => true).each do |user|
            unless user.id == current_user.id
                Subscription.create(:post_id => @post.id, :user_id => user.id, :comments_count => 0, :updated_at => (Time.now - 1.minute))
            end
        end

        redirect_to @post, notice: "Look at you, you're so good at this internet thing"

    else
        render 'new'
    end
end

这是我的show 定义:

def show
    @post = Post.friendly.find(params[:id])
    @user = @post.user
    @other_posts = Post.where(:blog => true).sample(4)

    if user_signed_in?

        @subscription = @post.subscriptions.where(:user_id => current_user.id)

        if @subscription.count > 0
            if @post.comments_count > 0
                @subscription.last.update_attributes(:updated_at => Time.now, :comments_count => @post.comments_count, :last_comment_id => @post.comments.last.id)
            else
                @subscription.last.update_attributes(:updated_at => Time.now, :comments_count => @post.comments_count)
            end
        end

    end

    @comments = @post.comments.paginate(:page => params[:page], :per_page => 20)

    redirect_to live_path if Post.friendly.find(params[:id]).live == true
end

有什么想法吗?

【问题讨论】:

  • 您是否在代码库中的某处将ActiveRecord::Base.record_timestamps 设置为false
  • 在您的 create 方法中,您正在传递 updated_at。那是自动保存的,所以至少你不需要它。在最坏的情况下,它可能会搞砸方法。
  • 我在更新和投票中都有Post.record_timestamps = false,这可能是问题吗?如果是这样,为什么heroku restart 会解决它,它不会总是抛出错误吗?
  • Ryan:我的create方法中的updated_at是创建一个相关的Subscription模型,我没有接触Post.updated_at。

标签: ruby-on-rails ruby ruby-on-rails-4 heroku


【解决方案1】:

设置 Post.record_timestamps = false 将停止对该 dyno 的所有后续请求设置 updated_at 和 created_at (如果您有多个 dyno,那么在其他 dyno 也更改该设置之前,对其他 dyno 的请求不会受到影响)。

heroku 重新启动可以解决问题,因为在新启动的应用程序中,该设置尚未更改 - 您说您只是通过投票和更新操作来执行此操作。在开发中,这些操作很少运行,另外您的开发环境会自动重新加载以响应代码更改。

您没有说明为什么将 record_timestamps 设置为 false,但是一旦您完成了需要该设置的任何操作,就应该将其设置回 true。我个人会写一个这样的方法:

class Post < ActiveRecord::Base
  def self.without_timestamps
    begin
      old_value = record_timestamps
      self.record_timestamps = false
      yield
    ensure
      self.record_timestamps = old_value
    end
  end
end

并使用它来包装应该在没有时间戳的情况下运行的块。

【讨论】:

  • 完全合理,感谢您的回答。我会重新思考我如何以及为什么使用record_timestamps
猜你喜欢
  • 1970-01-01
  • 2015-08-01
  • 2019-03-26
  • 2018-07-06
  • 1970-01-01
  • 2011-05-31
  • 2022-01-14
  • 2012-07-21
  • 2019-11-11
相关资源
最近更新 更多