Rails - 使用 rake 任务更新属性.需要帮助疑难解答模型方法代码 [英] Rails - Update attributes using rake task. Need help troubleshooting model method code

查看:55
本文介绍了Rails - 使用 rake 任务更新属性.需要帮助疑难解答模型方法代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用每晚运行的 rake 任务(使用 Heroku 调度程序)并在满足某些特定条件时更新一些属性.

I am trying to use a rake task that will run every night (using Heroku Scheduler) and update some attributes if some certain criteria is met.

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

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

The application allows users to "take the challenge" and read a book a week over the course of a year. It's pretty simple: users sign up, create the first book that they will read for their first week, then can enter what they're going to read next week. After they've "queued" up next week's book, that form is then hidden until it's been 7 days since their first book was created. At that point, the book that was queued up gets moved to the top of the list and marked as 'currently reading', while the previous 'currently reading' book moves down to the second position in the list.

如果用户没有排队"一本书,如果距离最新的当前正在阅读"的书已经过去 7 天,系统会自动创建一本书.

And IF a user doesn't 'queue' a book, the system will automatically create one if it's been 7 days since the latest 'currently reading' book was created.

我需要什么建议

如果距离上一本当前正在阅读"的图书创建已经过去 7 天,我目前遇到的问题是让图书更新属性.下面是我的书籍模型,方法 update_queue 是在 rake 任务期间调用的.运行 rake 任务当前不会出现错误并正确循环代码,但它只是不会更改任何属性值.因此,我确定 update_queue 方法中的代码在某些地方不正确,我希望您能帮助解决原因.我测试的方法是添加一本书,然后手动将系统日期更改为提前 8 天.相当野蛮,但我没有为此应用程序编写的测试套件&这是对我来说最简单的方法:)

The place I'm currently stuck is getting the books to update attributes if it's been 7 days since the last 'currently reading' book was created. Below is my book model and the method update_queue is what gets called during the rake task. Running the rake task currently gives no errors and properly loops through the code, but it just doesn't change any attribute values. So I'm sure the code in the update_queue method is not correct somewhere along the lines and I would love your help troubleshooting the reason why. And how I'm testing this is by adding a book then manually changing my system's date to 8 days ahead. Pretty barbaric, but I don't have a test suite written for this application & it's the easiest way to do it for me :)

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 任务看起来像这样(scheduler.rake 放在 lib/tasks 中):

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 模型,然后执行以下操作:

I would move the update_queue logic to the User model and modify the Book model somewhat, and do something like this:

# 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 调度程序每天运行一次:

Now you can have the Heroku scheduler run something like this once a day:

User.all.each(&:update_queue)

修改 User.all 以仅在需要时返回活动用户.

Modify User.all to only return active users if you need to.

哦,您可以在测试时使用 timecop gem 来操作时间和日期.

Oh, and you can use the timecop gem to manipulate times and dates when testing.

这篇关于Rails - 使用 rake 任务更新属性.需要帮助疑难解答模型方法代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆