Git Product home page Git Product logo

Comments (10)

DevanB avatar DevanB commented on June 2, 2024

Using Whenever gem, automate the to-do item deletion.

task delete_items: :environment do
  Item.where("created_at <= ?", Time.now - 7.days).destroy_all
end

from blocitoff.

mkwiatkowski avatar mkwiatkowski commented on June 2, 2024

Time.now - 7.days can also be written as 7.days.ago

from blocitoff.

DevanB avatar DevanB commented on June 2, 2024

So how do I TDD this? I could write the test in the model specs, but is that where it belongs? Do I create a new file to test the whenever gem? Is there a way to test against the whenever gem? I'm not finding anything easily.

from blocitoff.

mkwiatkowski avatar mkwiatkowski commented on June 2, 2024

Testing rake tasks is tricky. Testing passage of time is also tricky. And it seems you have both problems combined. :)

To test a rake task the best approach is to start with extracing the code into a module. You can put it in app/models and name it like a command (e.g. DeleteItems or DeleteItemsTask). Then the rake code would look like something this:

task delete_items: :environment do
  DeleteItems.run # or "call", or "execute"
end

Testing a module is trivial, you basically test it like any other model.

The second problem: testing passage of time was usually solved using the Timecop gem. But since Rails 4.1 there is now a travel_to testing helper. Use any of those to simulate passage of time in your test.

In the end, a basic test will have the following structure:

  1. Make some new todos.
  2. Travel in time 7 days into the future.
  3. Call the delete-items module.
  4. Assert that all todos were removed.

from blocitoff.

DevanB avatar DevanB commented on June 2, 2024

So let me make sure I'm understanding this correctly. I can leave my rake task in the lib folder, but also create a app/models/DeleteTodos.rb file, but somehow make this a module? So maybe:

module DeleteTodos
  task delete_todos: :environment do
    Todo.where("created_at <= 7 ?", 1.week.ago).destroy_all
  end
end

Then just write a test in the todo model spec against running this module?

from blocitoff.

DevanB avatar DevanB commented on June 2, 2024

I found a few examples online, and thought about trying them. My tests are passing now, but you are my mentor so you can tell me if this is bad practice or something:

require 'rails_helper'
require 'rake'

describe Todo do
  before do
    @user = create(:user)
    @todo = create(:todo, created_at: Time.new(2014, 7, 31, 9, 5, 0))
    load "tasks/delete_todos.rake"
    Rake::Task.define_task(:environment)
  end

  describe "#expiration_date" do
    it "returns the number of days remaining before todo is deleted" do
      expect(@todo.expiration_date).to eq(Time.new(2014, 8, 7, 9, 5, 0))
    end
  end

  describe "#delete_completed_todo" do
    it "deletes the todo after the todo is marked as complete" do
      @todo.update_attribute("completed", true)
      expect(Todo.count).to eq(0)
    end
  end

  describe "#delele_todos" do
    include ActiveSupport::Testing::TimeHelpers
    it "deletes the todo after 7 days" do
      travel_to Time.new(2014, 8, 7, 9, 5, 0) do
        Rake::Task["delete_todos"].invoke
        expect(Todo.count).to eq(0)
      end
    end
  end
end

from blocitoff.

mkwiatkowski avatar mkwiatkowski commented on June 2, 2024

The model file should be named app/models/delete_todos.rb. The convention is to use a camel case for the class names, but snake case for the file names.

Since the rake file is to look like this:

task delete_items: :environment do
  DeleteTodos.run
end

the module file has to look like this:

module DeleteTodos
  def self.run
    Todo.where("created_at <= 7 ?", 1.week.ago).destroy_all
  end
end

from blocitoff.

mkwiatkowski avatar mkwiatkowski commented on June 2, 2024

Loading rake tasks is possible, although I don't like it. I prefer making rake tasks so simple they can't be wrong and then testing the separate modules.

from blocitoff.

DevanB avatar DevanB commented on June 2, 2024

Cool:)

Now I understand! I read about it and hear about it, but it's still a foreign idea that people write their own classes and modules in Rails. Seems like Rails just has it all kinda built in for you, so you do not have to write extra things. I guess you have to write a lot of custom stuff in Sinatra!

from blocitoff.

mkwiatkowski avatar mkwiatkowski commented on June 2, 2024

Rails is just a framework, a scaffolding for your code. It does not release you from using good programming practices (like separating business logic into classes and modules in this case).

from blocitoff.

Related Issues (8)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.