选择!总是在heroku上返回nil

时间:2014-12-20 16:40:29

标签: ruby-on-rails select heroku

当地的一切都很好。 这对Heroku不起作用:

class Ticket
  def self.how_many_today
    todays_tickets = Ticket.all.to_a.select!{ |t| t.created_at.to_date == Date.today }
    todays_tickets == nil ? 0 : todays_tickets.count
  end

  # This method is scheduled with cron
  def self.reset_todays_nr
    @todays_nr = nil
  end

  def self.set_todays_nr
    if @todays_nr.nil?
      @todays_nr = how_many_today + 1
    else
      @todays_nr += 1
    end
  end
end

即,在heroku run console上播放会发现这种不一致:

irb(main):023:0* set_todays_nr
=> 1
irb(main):024:0> set_todays_nr
=> 2
irb(main):025:0> set_todays_nr
=> 3
irb(main):026:0> Ticket.all.to_a.select!{ |t| t.created_at.to_date == Date.today }
=> nil
irb(main):028:0> Ticket.first.created_at
=> Sat, 20 Dec 2014 16:19:31 UTC +00:00
irb(main):029:0> Ticket.first.created_at.to_date
=> Sat, 20 Dec 2014
irb(main):030:0> Date.today
=> Sat, 20 Dec 2014
irb(main):031:0> Date.today.to_date
=> Sat, 20 Dec 2014
irb(main):032:0> Date.today == Ticket.first.created_at.to_date
=> true
irb(main):033:0> Date.today.to_date == Ticket.first.created_at.to_date
=> true
irb(main):034:0> 
irb(main):035:0* Ticket.all.to_a.select!{ |t| t.created_at.to_date == Date.today }
=> nil
irb(main):036:0> Ticket.all.map(&:created_at)
=> [Sat, 20 Dec 2014 16:19:31 UTC +00:00, Sat, 20 Dec 2014 16:21:12 UTC +00:00]
irb(main):037:0> _[0].to_date == Date.today
=> true

看起来select!的条件已正确解析,手动检查显示该条件有一些元素,但select!不返回任何数组。再次,这在本地工作。

数据库已经迁移,夹具加载就像在本地一样。 尽管使用cron调度self.reset_todays_nr可能会导致问题,但在这种情况下不会触发此方法,因此它与问题无关,但我在此处发布它以防万一此问题比我想。 有人可以帮帮我吗?

2 个答案:

答案 0 :(得分:1)

确实很奇怪。特别是因为我刚才在Rails控制台中运行了一些命令而且array.select!{}不应该返回nil,除非数组开头是空的。

[1].select!{ |t| false } #=> []
[].select!{ |t| false } #=> nil

重新检查Ticket.all.to_a的输出是什么。

此外,您的选择条件可以简单地设置为:

var = Ticket.select{ |t| t.created_at.to_date == Date.today }

这将自行选择所有票据然后过滤。

但最好是在查询中进行过滤和计数,而不是加载内存中的所有内容,然后进行进一步的比较操作。看看这个:

Ticket.where("DATE(created_at) = DATE(?)", Date.today).count

或者使用您的SQL更改DATE(?)部分"获取今天的日期"功能

或者,您可以:

now = DateTime.now
range = (today.beginning_of_day)..(today.end_of_day)
Ticket.where(created_at: range).count

请记住时区可能存在的差异,即created_at列可能的时区与DateTime.now生成的时区不同。你必须检查。

答案 1 :(得分:0)

@Humza,非常感谢!这不是精确的解决方案,但帮助我解决了这个问题。非常感谢Ticket.where("DATE(created_at) = DATE(?)", Date.today).count - 我的想法完全相同,即不加载整个数组,然后才对其进行评估,所以感谢一种方法。如果您查看我的代码,您会在set_todays_nr中看到我有意将how_many_today置于条件中,以便在cron计划重置@todays_nr时最多运行搜索。更改后,bug变得更加明显:由于应用程序的流程,新的how_many_today返回1 - 在调用此方法之前创建了故障单。虽然奇怪的heroku行为的神秘性仍然未解决,但我没有进一步探讨,因为将方法改为下面的形式解决了这个问题。现在它看起来像这样:

  def self.how_many_today
    Ticket.where("DATE(created_at) = DATE(?)", Date.today).count
  end

  # This method is scheduled with cron; check config/schedule.rb
  def self.reset_todays_nr
    @todays_nr = nil
  end

  def self.set_todays_nr
    if @todays_nr.nil?
      @todays_nr = how_many_today
    else
      @todays_nr += 1
    end
  end