Rails -使用rake任务更新属性.需要帮助排除模型方法代码



我正在尝试使用一个rake任务,该任务将每天晚上运行(使用Heroku Scheduler)并更新一些属性,如果满足某些特定条件。

关于应用程序的一点逻辑:

该应用程序允许用户"接受挑战",在一年的时间里每周读一本书。这很简单:用户注册,创建他们第一周要读的第一本书,然后输入他们下周要读的书。在他们"排队"了下周的书之后,该表单将被隐藏,直到他们的第一本书创建后7天。此时,排队的书被移到列表的顶部,并标记为"当前正在阅读",而前一本"当前正在阅读"的书则移到列表的第二个位置。

如果用户没有"排队"一本书,系统将自动创建一个7天,如果最近的"当前阅读"的书被创建。

Where I need some advice

我目前卡住的地方是让书更新属性,如果它已经7天,因为最后一个"当前阅读"的书被创建。下面是我的图书模型,方法update_queue是在rake任务期间被调用的。当前运行rake任务不会产生错误,并正确地循环代码,但它只是不改变任何属性值。所以我确信update_queue方法中的代码在某些地方是不正确的,我希望你能帮助排除原因。我的测试方法是添加一本书,然后手动将系统日期更改为提前8天。相当野蛮,但我没有为这个应用程序编写测试套件&这对我来说是最简单的方法了:)

class Book < ActiveRecord::Base
  attr_accessible :author, :date, :order, :title, :user_id, :status, :queued, :reading
  belongs_to :user
 scope :reading_books, lambda {
    {:conditions => {:reading => 1}}
  }
  scope :latest_first, lambda {
    {:order => "created_at DESC"}
  }

  def move_from_queue_to_reading
    self.update_attributes(:queued => false, :reading => 1);
  end
  def move_from_reading_to_list
    self.update_attributes(:reading => 0);
  end
  def update_queue
    days_gone = (Date.today - Date.parse(Book.where(:reading => 1).last.created_at.to_s)).to_i
    # If been 7 days since last 'currently reading' book created
    if days_gone >= 7
        # If there's a queued book, move it to 'currently reading'
        if Book.my_books(user_id).where(:queued => true)
            new_book = Book.my_books(user_id).latest_first.where(:queued => true).last
            new_book.move_from_queue_to_reading
            Book.my_books(user_id).reading_books.move_from_reading_to_list
        # Otherwise, create a new one
        else
            Book.my_books(user_id).create(:title => "Sample book", :reading => 1)
        end
    end
  end

我的rake任务看起来像这样(调度程序。

task :queue => :environment do
  puts "Updating feed..."
  @books = Book.all
  @books.each do |book|
    book.update_queue
  end
  puts "done."
end

我会将update_queue逻辑移动到User模型并稍微修改Book模型,并做如下操作:

# in book.rb
# change :reading Boolean field to :reading_at Timestamp
scope :queued, where(:queued => true)
scope :earliest_first, order("books.created_at")
scope :reading_books, where("books.reading_at IS NOT NULL")
def move_from_queue_to_reading
  self.update_attributes(:queued => false, :reading_at => Time.current);
end
def move_from_reading_to_list
  self.update_attributes(:reading_at => nil);
end

# in user.rb
def update_queue
  reading_book = books.reading_books.first
  # there is an edge-case where reading_book can't be found
  # for the moment we will simply exit and not address it
  return unless reading_book 
  days_gone = Date.today - reading_book.reading_at.to_date
  # If less than 7 days since last 'currently reading' book created then exit
  return if days_gone < 7
  # wrap modifications in a transaction so they can be rolled back together
  # if an error occurs
  transaction do
    # First deal with the 'currently reading' book if there is one
    reading_book.move_from_reading_to_list
    # If there's a queued book, move it to 'currently reading'
    if books.queued.exists?
      books.queued.earliest_first.first.move_from_queue_to_reading
    # Otherwise, create a new one
    else
      books.create(:title => "Sample book", :reading_at => Time.current)
    end
  end
end

现在可以让Heroku调度器每天运行一次:

User.all.each(&:update_queue)

修改User.all,如果需要,只返回活动用户。

哦,您还可以在测试时使用timeop gem来操作时间和日期。

原因可能是程序流没有进入if days_gone>= 7条件。

你可以用两种方式检查

1 -简单和容易的方法(但不是一个很好的方法)

use p语句每句都有意义全文

,

def update_queue
    days_gone = (Date.today - Date.parse(Book.where(:reading => 1).last.created_at.to_s)).to_i
    p "days gone : #{days_gone}"   
    # If been 7 days since last 'currently reading' book created
    if days_gone >= 7
        p "inside days_gone >= 7"
    etc... 

2 -使用ruby调试器和调试点

在Gem文件中添加
gem 'debugger'

并在需要的地方插入断点

def update_queue
        days_gone = (Date.today - Date.parse(Book.where(:reading => 1).last.created_at.to_s)).to_i
       debugger

的更多帮助

HTH

相关内容

  • 没有找到相关文章

最新更新