Search code examples
ruby-on-railsrubydestroyself-destruction

Self deleting checklist not deleting items


I'm building a self-deleting checklist with Ruby on Rails that is supposed to automatically delete an item once it's expired after 7 days. But the item just remains and goes into the negative ( -1, -2, -3, etc.) I'm not sure where the problem is exactly.

My destroy action is working for everything else.

I've researched all over Stack and Google but I'm not finding anything helpful.

Here is my itemscontroller:

class ItemsController < ApplicationController
  before_action :find_item, only: [:show, :edit, :update, :destroy]

  def index
    @items = Item.all
    @items = Item.where(user: current_user)
  end

  def new
    @item = Item.new
    # authorize @item
  end

  def create
    @item = current_user.items.build(item_params)
    @item.expires_at = Time.now + 7.days
    # authorize @item
     if @item.save
      redirect_to @item, notice: "Item was added!"
     else
       flash[:error] = "Error adding item. Please try again! Your organization depends on it!"
       render :new
     end
  end

  def show
    @item = Item.find(params[:id])
    @item.days_left 
  end


  def edit
    @item = Item.find(params[:id])
  end

  def update
    @item = Item.find(params[:id])
    if @item.update_attributes(item_params)
      flash[:notice] = "Item was updated."
       redirect_to item_path
    else
       flash[:error] = "There was an error saving the item. Please try again."
       render 'edit'
    end
  end

  def destroy
    if @item.days_left == 0
      @item.destroy
    end

    @item.destroy
    redirect_to items_path
  end



  def completed
    @item = Item.find(params[:id])
    @item.update_attribute(:completed, true)
    redirect_to items_path
  end

  private


  def item_params
    params.require(:item).permit(:name, :user, :description)
  end

  def find_item
    @item = Item.find(params[:id])
  end
end

And the Item model:

    class Item < ActiveRecord::Base
  belongs_to :user

  def completed
     completed == true
  end

   default_scope { order('expires_at ASC') }

   def days_left
      7 - (DateTime.now.to_date - created_at.to_date).to_i
   end

end

Routes.rb

Rails.application.routes.draw do


  get 'about' => 'welcome#about'

  get "users/dashboard" => "items#index"

  root to: 'welcome#index'



  devise_for :users
  resources :users, only: [:update, :show, :index]
  resources :items do
    member do
      patch :completed
    end
  end
end

Schema.rb

ActiveRecord::Schema.define(version: 20150823054939) do

  create_table "items", force: :cascade do |t|
    t.string   "name"
    t.integer  "user_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.boolean  "completed"
    t.datetime "expires_at"
    t.text     "description"
  end

  add_index "items", ["user_id"], name: "index_items_on_user_id"

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.string   "name"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "unconfirmed_email"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "role"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

Solution

  • If I understood correctly, the problem lies in the destroy method. It should be

    def destroy
      if @item.days_left == 0
      @item.destroy
      end
      redirect_to items_path
    end
    

    Update:

    If you want the items to be self-deleted, you can use whenever gem to a task which does that like below

    # lib/tasks/delete_expired_items.rake
    every :hour do 
      runner "Item.delete_expired_items"
    end
    
    #item.rb
    def delete_expired_items
      #this will delete the items that are created 7 days ago from today.
      self.where('created_at =?', 7.days.ago).destroy_all
    end