Loenvpy
Loenvpy

Reputation: 919

Destroy a post after 30 days from its creation

For learning purposes I created a blog, now I want to destroy a post automatically after 30 days from its creation. how can I do it?

This is my Posts controller

  def index
    @posts = Post.all
  end
  def create
    @post = current_user.posts.new(post_params)
    @post.save
    redirect_to posts_path
  end
  def destroy
    @post.destroy
     redirect_to posts_path
  end

Upvotes: 1

Views: 1871

Answers (5)

craig.kaminsky
craig.kaminsky

Reputation: 5598

Along with the aforementioned whenever gem, you can also use two gems called Sidekiq and Sidetiq for scheduling tasks/workers.

I've been using these on a large app at work and am very pleased with it. It's fast (uses Redis, added with a simple gem, reliable, and easy to use).

# in app/workers/clean_posts.rb
class CleanPosts
  include Sidekiq::Worker
  include Sidetiq::Schedulable

  recurrence { monthly }

  def perform
    # stealing from toolz
    Post.where('created_at >= :thirty_days_ago', thiryty_days_ago: Time.now - 30.days).destroy_all
  end
end

This will, however, remove the posts from your DB and they will no longer be accessible by your application.

Upvotes: 3

Maksim Gladkov
Maksim Gladkov

Reputation: 3079

To achieve desired result, you need to change your index action like this:

def index
    @posts = Post.where(created_at: 30.days.ago..Time.now)
end

In such way, you won't need to destroy posts and you will get the desired result.

If you need to limit access to the older posts, then you can use:

def show
    @post = Post.where(created_at: 30.days.ago..Time.now).find(params[:id])
end

And, if we are speaking about code beauty, then you should move where(created_at: 30.days.ago..Time.now) part to a scope in your model, like this:

class Post
   ...

   scope :recent, -> { where(created_at: 30.days.ago..Time.now) }
end

And use it like this:

Post.recent #=> to get list of recent posts
Post.recent.find(params[:id]) #=> to get recent post with specified id

Upvotes: 1

Matias
Matias

Reputation: 641

I would set up a task with whenever that runs every 1 day.

To generate a task:

rails g task posts delete_30_days_old

Then on the created file (lib/tasks/posts.rb), add the following code:

namespace :posts do
  desc "TODO"
  task delete_30_days_old: :environment do
    Post.where(['created_at < ?', 30.days.ago]).destroy_all
  end
end

This is of course if you want to delete the posts that have more than 30 days, other answers might as well work but I would rather have my database with clean data that I'll use on my application.

Upvotes: 6

xlembouras
xlembouras

Reputation: 8295

You can not do that from your controller, you need to add some functionality to your application.

You will need a cron job running everyday that will look for posts that are more than 30 days old and destroy them.

eg Post.where('created_at < ?', 30.days.ago)

For handling the cron jobs better you might consider using the whenever gem that helps a lot and keeps the cron setup in your app.

Upvotes: 0

toolz
toolz

Reputation: 891

Posts will be stored in your database. The model is what interacts with your database. Your controller never sees the database, it only sees what the model shows it. If you wanted to pull from the database using your model inside the controller you could do it with this code.

@posts = Post.where('created_at >= :thirty_days_ago', thiryty_days_ago: Time.now - 30.days)

Post in this code calls you app/model/Post.rb which inherited active record. .where is the active record method that looks at your database based on the stuff you define. Here we have defined to pull only rows where the created_at column has a time in it that is 30 days ago.

If you look inside your database you'll notice the created_at column was automagically put in there for you.

Upvotes: 3

Related Questions