How to Rail Rails Before Rails Rails You.

Aymes S.
8 min readSep 17, 2020

--

D I S C L A I M E R :
I am not an expert in Rails. I can only provide information that I believe I understand so far. This was created mainly to test my own understanding of the material. If you find anything in this article that contains false information or seems misleading, please correct me! Thank you.

FIRST. Create a FRESH Rails application by running:

rails new [NameOfYourApplication]rails new Doggorails new AdoptDoggo

Note: the first letter should be capitalized or title-cased(the first letter of each word is capitalized).

You will now see all of the folders needed to create your application! Just double-check that schema.rb looks good or else seeding in your data will be a nightmare.

SECOND. The most efficient way to create your MVC(models, views, and controllers) and migration:

rails g resource [NameOfTable] [columnname]:[datatype] [columnname]:[datatype]rails g resource Dog name:string breed:string age:integer

Note: the name of your table should be plural and the first letter should be title-cased. Also, notice how there aren’t commas being used but only spaces.

Here’s also a list of the most common data types.

integer      (whole numbers)
primary_key (id number)
float (0.0)
boolean (true || false)
string ("text")
text ("a long description")
date (YYYY-MM-DD)
time (HH:MM:SS[.NNNNN])
datetime (YYYY-MM-DD HH:MM:SS)
timestamp (YYYY-MM-DD HH:MM:SS UTC)

SEED YOUR DATA:

This might be the worst thing in the world.
MAKE SURE YOUR SCHEMA.RB AND MIGRATIONS PAGE LOOKS GOOD AND IS GOING TO MATCH WITH WHATEVER DATA YOU CREATE IN YOUR SEEDS.RB!!! The last thing you want is running your application and seeing a bunch of errors.

Dog.destroy_all
Dog.create(name: "Nugget", breed: "Siberian Husky", age: 1)

Note: The ‘.destroy_all’ function will replace all pre-existing data in your database system with the fresh new data you are reseeding it with.

Oops! But I forgot that I wanted to add a photo of Nugget! I’m going to need to add a URL somewhere. Instead of restarting our migration all over, we can create a new migration.

rails g migration add_[ColumnName]_to_[TableName] [columnname]:[datatype]ORrails g migration AddColumnNameToTableName columnname:datatype
rails g migration add_url_to_dogs url:stringrails g migration AddUrlToDogs url:string

Easy fix! Remember to migrate the migrations you just created.
Check out your ‘schema.rb’ to make sure your updated table is correct. Now we just have to remember to add a photo to each instance we are creating.

Dog.create(name: "Nugget", breed: "Siberian Husky", age: 1, 
url: "https://www.flickr.com/photos/142916389@N03/50352181986/")

SEED YOUR DATA!

Now we are going to go back and forth with our controller, views, and routes files. It’s super helpful to test your application as you go.

METHODS FOR YOUR CONTROLLER:

Here, we are getting a list of ALL of the dogs through the Index:

def index
@dogs = Dog.all
end

Now we are finding each dog by its ID number through Show:

def show
id = params[:id]
@dog = Dog.find(id)
end

If we want the user to create a new instance of a dog, they would first have to be able to create a form:

def new
@dog = Dog.new
end

After the user submits their form request, we can then create a new instance of a dog:

def create
name = params["dog"]["name"]
breed = params["dog"]["breed"]
age = params["dog"]["age"]
url = params["dog"]["url"]
dog = Dog.create(name: name, breed: breed, age: age, url: url)
redirect_to dog_path(dog)
end

Edit/Update:

def edit
@dog = Dog.find(params[:id])
render :edit
end
def update
@dog = Dog.update(params[:id])
redirect_to dog_path(@dog)
end

Delete:
Redirects to the index page. Remember that once an instance is deleted, there will be no show page for that instance. We must get redirected back to the index page or to another available page.

def destroy
@dog = Dog.destroy(params[:id])
redirect_to dogs_path
end

WHAT’S IN YOUR HTML:

Here’s an example of your index page could look like to display all of the dogs. Remember that we want the user to see a list of all of the dogs.

Your index.html.erb page:

<h1>List of Dogs</h1>
<%@dogs.each do |dog| %>
<%=link_to dog.name, dog_path(dog)%>
<%end%>

Note: <% is a snowcone and <%= is a squid. They both allow Ruby code inside of them but the squid will display what’s presented in the code. In this case, we will be showing the user all of the links of a dog’s name and

Your show.html.erb page:

<li>Name: <%= @dogs.name %></li>
<li>Breed: <%= @dogs.breed %></li>
<li>Age: <%= @dogs.age %></li>
%= image_tag("#{@dogs.url}", height: "30%", width: "30%")%>
<%= link_to("Back To Index", dogs_path)%><%= link_to "Delete Dog", dog_path(@dog.id), method: "delete",
data: {:confirm => "Are you sure?"}%>
<%= link_to "Edit Dog", edit_dog_path %>

Your new.html.erb page:

Shown below is an HTML form action tag. The difference between the HTML’s action tag and the Rails form tag is that HTML requires the user to have an authenticity token.

<form action="/dogs" method="POST"><label for="name">Doggos Name:</label>
<input type="text" id="name" name="name">
<label for="breed">Breed:</label>
<input type="text" id="breed" name="breed">
<label for="age">Age:</label>
<input type="text" id="age" name="age">
<label for="url">URL:</label>
<input type="text" id="url" name="url">
<%= hidden_field_tag :authenticity_token, form_authenticity_token %><input type="submit" value="DOGGO!"></form>

Now let’s check out Rail’s form_for tag:

<h1>Add a new Dog!</h1>
<%= form_for(@dogs) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :breed %>
<%= f.text_field :breed %>
<%= f.label :age %>
<%= f.number_field :age %>
<%= f.label :url %>
<%= f.text_field :url %>
<%= f.submit 'DOGGO!' %>
<% end %>

Rail’s form_for tag doesn’t require the authenticity token because it automatically does it for us! Neat!

Notice that the ‘age’ has a ‘number_field.’ Pretty much what number_field does, it allows the age to toggle up and down.

What if you want the user to only choose the breeds that are in your database already? We can use collection_select to use a drop-down box.

<%= f.collection_select(:breed_id, Breed.all, :id, :name) %>

If we want to get checkboxes we do:

<%= f.collection_check_boxes(:breed_id, Breed.all, :id, :name) %> 

Your edit.html.erb page:

Would be the same thing as your NEW page except for your routes.

<h1>Edit Doggo!</h1>
<%= form_for(@dogs) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :breed %>
<%= f.text_field :breed %>
<%= f.label :age %>
<%= f.number_field :age %>
<%= f.label :url %>
<%= f.text_field :url %>
<%= f.submit 'DOGGO!' %>
<% end %>

UNDERSTANDING THE ROUTES:

How it feels when your routes stop you from moving forward.

This starts off confusing, but hopefully, I can give you some clarity.

When a user goes to our website (localhost:3000/dogs), they expect a list of all of the dogs. We are going to contact our controller(dogs) and use the method(index) to pull all of the dogs from our database.

get '/dogs', to: 'dogs#index'

What if a user just wants to see one specific dog? We are going to contact our controller(dogs) again and use the method(show) to pull a single instance of a dog.

get 'dogs/:id', to: 'dogs#show', as: 'dog'

Now, what if a user wants to add their own dog? We are going to have the user request a form to do so. We then contact our controller(dogs) and use the method(new) to process the request. The URL (localhost:3000/dogs/new) will pop up for the user and give them a form to fill out.

get '/dogs/new', to: 'dogs#new', as: 'new_dog'

Before the user can complete their request, it needs to get accepted by our database. The reason why we use the verb ‘POST’ is because the user is creating a new instance of a dog from the form we provided for them.

post '/dogs/', to: 'dogs#create'

Below is a little cheat sheet that I created to help you understand what’s going on in the routes.

RESOURCES:

What if I told you you didn’t have to write out all of your routes? Yep. There’s a thing called ‘resources.’

get '/dogs', to: 'dogs#index'
get 'dogs/:id', to: 'dogs#show', as: 'dog'
get '/dogs/new', to: 'dogs#new', as: 'new_dog'
post '/dogs/', to: 'dogs#create'
resources: :dogs, only: [:index, :show, :new, :create]
resources: :dogs, except: [:edit, :update, :destroy]

Both resources are calling the same thing. “Only” will ONLY call the routes for the index, show, new, and create. “Except” will call on everything EXCEPT for edit, update, and destroy.

BEFORE ACTION:

If you noticed, we repeated ‘(params[:id])’ quite a few times. ‘before_action’ is a method that is used in your controllers. It’s saying, “Hey, call this before anything else!”

class DogsController < ApplicationController
before_action :find_dog, only: [:show, :edit, :update, :destroy]
def index
@dogs = Dog.all
end

def edit
end
.....end

Let’s check out the ‘find_dog’ method.

 privatedef find_dog
@dog = Dog.find(params[:id])
end

STRONG PARAMS:

Think of strong params as a liquor store clerk. The clerk is checking everyone’s IDs to make sure they’re over 21. If the clerk was not checking IDs, then that means anyone could purchase alcohol. Strong params act as a security blanket and decide what gets accepted into our database system. Remember what our controller page looked like? You might have noticed we repeated (params[:id]) quite a bit. There’s a way to fix that!

 privatedef dog_params
params.require(:dog).permit(:name, :breed, :age, :url)
end

What methods would change:

def create
@dog = Dog.new(dog_params)
if @dog.save
redirect_to dog_path(@dog.id)
else
render :new
end
end
def update
@dog = Dog.update(dog_params)
if @dog.save
redirect_to dog_path(@dog)
else
render :new
end
end

VALIDATIONS:

Validations happen in your models. They make sure that the user is including a certain element when creating a new form. For example, a dog can’t be created if they don’t have a breed.

validates :name, presence: true, uniqueness: {case_sensitive: false}validates :breed, presence: truevalidates :bio, length: {minimum: 30}validates :age, numericality: {less_than: 25, message: "%{age} is way too high for a doggo"}validates :good_with_kids, presence: true, inclusion: {in: [true, false], message: "%{value} is not true or false"}

We also have to raise the error in the HTML file for the form page.

<% if @dog.errors %>
<% @dog.errors.full_messages.each do |error|%>
<%= error %>
<% end %>
<% end %>
There’s more…?!

Custom Validators:

validate :dogs_dont_start_with_qdef dogs_dont_start_with_q
if name.downcase.starts_with?('q')
errors.add(:name, "can't start with q")
end
end

Note: When you are validating custom methods, the word ‘validate’ must be SINGULAR.

RENDER PARTIALS:

Partials create a shortcut for us when it comes to creating or editing a form page. We would create a new HTML in our views file and label it a form. In this case, I created a file and labeled it, ‘_dog_form.html.erb’. Inside of the dog_form, we will put exactly what was in our new and edit HTML files. By doing this, this will help us from repeating code.

<%= form_for(@dogs) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :breed %>
<%= f.text_field :breed %>
<%= f.label :age %>
<%= f.number_field :age %>
<%= f.label :url %>
<%= f.text_field :url %>
<%= f.submit 'DOGGO!' %>
<% end %>

Remember that “dog_form” is the name of your HTML that has your form page. Once you have your form page set up, you can stick this bad boy in your new.html.erb and edit.html.erb!

<%= render partial: "dog_form", locals: {button_text: "Edit this dog!"} %>

CREATING AN ABOUT PAGE:

Create a new controller for your about page.

rails g controller [NameOfController]rails g controller Application

Inside your ApplicationController:

def about
@num_dogs = Dog.count
render :about
end

Inside your views/application/about.html.erb :

<h1>About my Dogs</h1>
<div>Total number of dogs: <%= @num_dogs %></div>
You got this!

--

--

Aymes S.
Aymes S.

Written by Aymes S.

Software Engineer in the making.

No responses yet