The value of DRY code.
By: Jas Spencer
Tags: Programming, Ruby, Coding, Rails

Here is an example from a simple Rails blogging application, here is what the Articles Controller initially looked like:

class ArticlesController < ApplicationController

def index

@articles = Article.all

end



def show

@article = Article.find(params[:id])

end



def new

@article = Article.new

end def edit

@article = Article.find(params[:id])

end



def create

@article = Article.new(params.require(:article).permit(:title, :description))

if @article.save

flash[:notice] = "Article was created successfully!" redirect_to @article

else

render 'new'

end

end def update

@article = Article.find(params[:id])

if @article.update(params.require(:article).permit(:title, :description))

flash[:notice] = "Article was updated successfully!" redirect_to @article

else

render 'edit'

end

end def destroy

@article = Article.find(params[:id])

@article.destroy

redirect_to articles_path

end

end

There is a lot to unpack here, but this code is pretty clunky. With all the repetition, it increases the chance of an error. Notice how the line

@article = Article.find(params[:id]) occurs 4 times throughout the controller and yes I actually coded this 4 times over just to prove this point.

Notice that also in the create and update methods we have the line

(params.require(:article).permit(:title, :description))

we can fix this as well by introducing two methods to clean up this code.

Let’s take of the first problem, we’ll create some private methods for this controller, the first one will be called ‘set_article’.

def set_article

@article = Article.find(params[:id])

end

Now we need to make sure that ‘set_article’ gets used for those 4 methods.

At the top of the controller we add:

class ArticlesController < ApplicationController

before_action :set_article, only: [:show, :edit, :update, :destroy]

This means that before anything happens, those methods will implement the ‘set_article’ method, no longer having to code it over and over again!

Now for the ‘params.require …’ line that’s just ensuring that the articles have all the require attributes when they are being created, they must have a title and description. It can be cleaned up using another private method. This one will be called ‘article_params’

def article_params

params.require(:article).permit(:title, :description)

end

Now in the create and update methods, simply just pass in ‘article_params’ as the argument.

The shiny, new, DRY Articles Controller looks like this:

class ArticlesController < ApplicationController

before_action :set_article, only: [:show, :edit, :update, :destroy]



end def index @articles = Article.allend def show

end



end def new @article = Article.newend def edit

end



if

flash[:notice] = "Article was created successfully!"

redirect_to

else

render 'new'

end

end def create @article = Article.new(article_params)if @article .saveflash[:notice] = "Article was created successfully!"redirect_to @article elserender 'new'endend

if

flash[:notice] = "Article was updated successfully!"

redirect_to

else

render 'edit'

end

end def updateif @article .update(article_params)flash[:notice] = "Article was updated successfully!"redirect_to @article elserender 'edit'endend



redirect_to articles_path

end def destroy @article .destroyredirect_to articles_pathend private



end def set_article @article = Article.find(params[:id])end def article_params

params.require(:article).permit(:title, :description)

end

end

Much better!