Raillery: Making Routing Even Easier

Jack Overby
3 min readMar 17, 2020

Programmers, just like all subcultures, have characteristics, some of which have been distilled via witticisms and aphorisms:

“A programmer is an organism that converts caffeine into code”

“There are no good programmers- only experienced ones”

“The best programmers are lazy and act dumb”

This last one really hits home. Why do in five lines what can be done in two? Or in one long line that can be done in one slightly shorter line? The world is full of problems that need to be solved, and in a world where the only abundant resource is scarcity, time is the most precious of all, and we’d rather not waste it. As the ubiquitous meme goes:

As a new recruit into the Ruby on Rails Army, I have experienced (undergone? endured?) the joys et al. of routing. While Rails is more concise and readable than Sinatra, which we Flatiron Mod 2 mods have flown to the moon (*groan*), there is still a lot of copy-and-paste. If programmers had a God, and said God had a stone tablet of Commandments, DRY (Don’t Repeat Yourselves) would be one of them. So, as DRY as Rails is, I think we can let it bake under the sun even more- at least for the basic tasks we’re doing so far.

I’m going to show you a few code snippets. See if you can find any patterns:

Index Pages

recipes/index.html.erb<% @recipes.each do |rec| %>
<div><%= link_to recipe.name, student_path(recipe) %></div>
<div><%= link_to recipe.ingredients, student_path(recipe) %></div>
<div><%= link_to recipe.cook_time, student_path(recipe) %></div>
<% end %>
# students/index.html.rb<% @students.each do |student| %>
<div><%=link_to student.first_name, student_path(student)%></div>
<div><%=link_to student.last_name, student_path(student)%></div>
<% end %>

Controller Files

# seas_controller.rbclass SeasController < ApplicationController  def index
@seas = Sea.all
end

def show
@sea = Sea.find(params[:id])
end
def new
@sea = Sea.new
end
def edit
@sea = Sea.find(params[:id])
end
def create
@sea = Sea.new(sea_params)
if @sea.save
redirect_to @sea
else
render 'new'
end
end
def update
@sea = Sea.find(params[:id])
if @sea.update(sea_params)
redirect_to @sea
else
render 'edit'
end
end
def destroy
Sea.destroy(params[:id])
redirect_to '/seas'
end
private def sea_params
params.require(:sea).permit(:name, :temperature, :bio, :mood, :image_url, :favorite_color, :scariest_creature, :has_mermaids)
end
end# student_class_controller.rbclass StudentsController < ApplicationControllerdef index
@students = Student.all
end

def show
@student = Student.find(params[:id])
end
def new
@student = Student.new
end
def edit
@student = Student.find(params[:id])
end
def create
@student = Student.new(student_params)
if @student.save
redirect_to @student
else
render 'new'
end
end
def update
@student = Student.find(params[:id])
if @student.update(student_params)
redirect_to @student
else
render 'edit'
end
end
def destroy
Student.destroy(params[:id])
redirect_to '/students'
end
privatedef student_params
params.require(:student).permit(:first_name, :last_name)
end
end

That’s a lot of repetitive code! Even copying and pasting all into this article was a pain! Basically, only the class names (Student, Sea, Recipe) and the “columns” (member variables) of said classes are changing. The basic structure is darn near identical. So what can we do about it, besides hellishly moan, wail and grind our teeth?

As with everything else that we do more than once… we can automate it!

Here’s pseudo-code of some scripts that could take care of all this:

Controller Generator

def auto_controller(class_name, class_vars)  def index
@class_name.lower = class_name.all
end
def show
@class_name.lower = class_name.new
end
def new
@class_name.lower = class_name.new
end
def edit
@class_name.lower = class_name.find(params[:id])
end
def create
@class_name.lower = class_name.new(class_name_params)
if @class_name.lower.save
redirect_to @class_name.lower
else
render 'new'
end
end
def update
@class_name.lower = class_name.find(params[:id])
if @class_name.lower.update(class_name.lower.params)
redirect_to @class_name.lower
else
render 'edit'
end
end
def destroy
@class_name.destroy(params[:id])
redirect_to '/class_name'
end
private def class_name_params
params.require(:class_name).permit(class_vars)
end
end

Index Generator

def auto_index(class_name, class_vars)
<% @class_name.each do |member| %>
for class_vars.each do |var|
<div><%=link_to member.first_name, student_path(member)%></div>
end
<% end %>
end

So rather than having to type the same either methods over and over, we could simply call the auto_controller method, and said scripts would be generated! After all, as the proverb goes, one line is better than 50.

Going through the process of manually entering these methods and scripts is a great way to ingrain the concepts in our malleable young (in dev years) brains… but Good Lawdy Lawd, I get it by now!! A script like mine could save all of us… dozens and dozens of minutes over the next few weeks! i.e. it could a life changer!

Or it could be a silly, overblown little made-up nothing… just like COVID!

--

--