0

(Herokuスケジューラを使用して)毎晩実行されるrakeタスクを使用し、特定の基準が満たされた場合にいくつかの属性を更新しようとしています。

アプリケーションに関する小さなロジック:

このアプリケーションを使用すると、ユーザーは「チャレンジ」して、1年間で1週間にわたって本を読むことができます。非常に簡単です。ユーザーはサインアップして、最初の週に読む最初の本を作成し、次の週に読む予定の本を入力できます。彼らが来週の本を「キューに入れ」た後、最初の本が作成されてから7日が経過するまで、そのフォームは非表示になります。その時点で、キューに入れられた本はリストの一番上に移動し、「現在読んでいる」とマークされ、前の「現在読んでいる」本はリストの2番目の位置に移動します。

また、ユーザーが本を「キューに入れる」ことがない場合、最新の「現在読んでいる」本が作成されてから7日が経過すると、システムは自動的に本を作成します。

アドバイスが必要なところ

私が現在立ち往生している場所は、最後の「現在読んでいる」本が作成されてから7日が経過している場合に、本に属性を更新させることです。以下は私の本のモデルであり、メソッドupdate_queueはレーキタスク中に呼び出されるものです。現在、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タスクは次のようになります(lib /tasksに配置されたscheduler.rake):

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

2 に答える 2

0

おそらくその理由は、プログラムフローがif days_gone>=7条件の内部に入っていないためです。

これは2つの方法で確認できます

1-シンプルで簡単な方法(ただし、あまり良い方法ではありません)

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

于 2013-01-02T04:51:24.590 に答える
0

ロジックをUserモデルに移動しupdate_queue、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スケジューラーに次のようなものを1日1回実行させることができます。

User.all.each(&:update_queue)

User.all必要な場合にのみアクティブユーザーを返すように変更します。

ああ、そしてあなたはテストするときに時間と日付を操作するためにtimecopgemを使うことができます。

于 2013-01-03T03:37:18.330 に答える