tutorials. WEB DEVELOPMENT

Trashing banner

Creating a trashing concern in rails 5

In some instances, we want to 'softly' destroy records; persisting in the database but making it inaccessible through ActiveRecord queries where defined. Trashing is what many would call and while there is the option of using gems such as acts_as_trashable, it is always a good idea to minimize the number of external dependencies. One approach to this would be to add trashed_at attribute to the ActiveRecord::Base class then querying for records whose column trashed_at value is nil This is what we are going to do only that we are creating a concern with the required functionality to be used across mutilple models Here's the link to code

setup

I will name my app trashing so let's go ahead and create a new app. I'm using the lastest stable version of rails 5 i.e version 5.0.0.1. We'll take advantage of the rails-api gem, which, starting with Rails 5, now comes built in since we only need as JSON response as an output for our ActiveRecord queries.

$ rails _5.0.0.1_ new trashing --api

$ cd trashing

make sure you've got all the dependencies installed by running

$ bundle install

Let's go ahead a scaffold two new models. In this case I will name mine Post and Comment with each having two new columns body and trashed_at.

$ rails g scaffold post body:text trashed_at:datetime

$ rails g scaffold comment body:text trashed_at:datetime

migrate the db changes

$ rails db:migrate

firing the localhost and accessing /comments and /posts pages should return nil arrays posts gem push
comments gem push
gem push
Note the query in logs

Concern

We are going to create our trashable concern. A concern is basically a way of organizing code in this case by having a common functionality across multiple models in one file. A DRY of sorts. Inside model/concerns create a file named trashable.rb with the following contents:
We're extending ActiveSupport::Concern to get hold of included function which typically includes the two scopes in the models where the trashable module will be included The default scope is set to only returns record that have trashed_at column as nil meaning trashed items won't be included. On the other hand, trashed scope does the opposite e.g Comment.trashed. trashed? method returns Boolean checking whether a record has trashed_at as not nil.

Testing

Let's include the trashable concern in our two models
Using Faker gem I created 10 records for each ActiveRecord::Base class. Firing the localhost posts gem push
comments gem push
logs gem push
Let's go ahead trash the first 5 records of each model i.e:
The resultant response should only return untrashed items: posts gem push
comments gem push
That's it! You can go ahead and add other functionalities to the concern e.g unmuting trashed items.
Create Ruby Gem by Example

By Victor Areba

Blog pic
I am a passionate Rubyist. This is a platform where I share what I have learned over the years in matters Ruby, Rails, JavaScript and other related technologies. I also write non technical stuff particulary creative writing here Inkulumo. I enjoy swimming and watching movies.

1 comments

Joseph Ndungu
15 August 2016
Very nice and well written article. One concern though, i'd advice not using a default scope. For example if I had other scopes in my model, calling Unscoped removes ALL scopes that might normally apply to your select, including (but not limited to) associations. So for example I wanted to get trashed comments for a user, I'd do something like User.first.comments.trashed, the generated query would look like "SELECT "comments".* FROM "comments". This is not what we want. There are many ways to override this but it gets very complicated quickly. I'd suggest using a named scope to replace the default scope..

Login to post your comment