This is how you CRUD

Jadam
gSchool Stories
Published in
7 min readNov 6, 2014

--

This run through is structured in a way that wont stop to explain all the small things about syntax or purpose or files and methods. Rather we will be going through a process of error driven development to guide us along our crudding journey. CRUD, or Create Read Update Destroy, is a core element of building in Ruby on Rails and many other languages. There are plenty of resources out there that provide a much more in depth explanation of what CRUD is, but we’re going to jump right into knocking out some CRUD here.

Open up your terminal to start out, and punch the following lines of code in, one row at a time.

$ rails new widgets -—database=postgresql
$ cd widgets
$ bundle
$ rake db:create

In a second terminal tab run your rails server

$ rails s

Now head over to your browser and enter localhost:3000 into your address bar. You should see the Rails Welcome Page.

Back in terminal we’ll generate a database table for some widgets to CRUD and then open up our Atom editor to check out the file.

$ rails g migration MyWidgetsAndThings
invoke active_record
create db/migrate/20141106150725_my_widgets_and_things.rb
$ atom .

Now in the text editor we’ll create a new database table by putting in the following code within the existing def change and end block.
db/migrate/20141106150725_my_widgets_and_things.rb

create_table :widgets do |t|
t.string :name
t.string :description
t.integer :age
end

Additional datatypes to choose from: http://stackoverflow.com/questions/17918117/rails-4-datatypes

Once our widgets database table is created we’ll head back over to the terminal and migrate those changes.

$ rake db:migrate== 20141106025705 MyWidgetsAndThings: migrating ==================
 —  create_table(:widgets)
-> 0.0052s
== 20141106025705 MyWidgetsAndThings: migrated (0.0053s) =========

Your terminal output should look something like the one above

That should be the last time we’ll need the terminal for a while. Back over in Atom, open up your routes.rb file. We will be adding in two lines here: resources :widgets and root ‘widgets#index’
config/routes.rb

Rails.application.routes.draw do
resources :widgets
root ‘widgets#index’
end

You can delete all the commented out text (the light grey text with hashtags in front of it) If you choose to do that your file should have 4 lines like the code above.

Next create a file inside of your apps/controllers directory, name it
widgets_controller.rb and drop in the following code to set your index action.
app/controllers/widgets_controller.rb

class WidgetsController < ApplicationController
def index
end
end

Check localhost:3000 ~> We have our first desired error: ‘The action ‘index’ could not be found for PlantsController’

So lets add an index action. Create a folder named widgets within the app/views directory. Then create a file named index.html.erb and add in the following code:
app/views

<h1>Widgets</h1>
<%= link_to ‘New Widget’, new_widget_path %>

Check localhost:3000 ~> Click on the ‘New Widget’ link. You should be rewarded with a fail message stating: ‘action new could not be found’

To resolve that disconnect provide your controller with that new action:
app/controllers/widgets_controller.rb

def new
end

Check localhost:3000/widgets/new ~> Our first ‘Missing template’ error.

Create a view file named new.html.erb inside of your app/views/widgets directory and enter in the following code:
app/views/widgets

<h1>Widget Factory</h1>
<%= form_for @widget do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :age %>
<%= f.text_field :age %>
<%= f.submit %>
<% end %>

Check localhost:3000/widgets/new ~> Here we get a ‘First argument in form cannot contain nil or be empty’ error as expected.

Backover in our new action within the controller we’ll add the following line of code: @widget = Widget.new

app/controllers/widgets_controller.rb

def new
@widget = Widget.new
end

Check localhost:3000/widgets/new ~> You should get ‘uninitialized constant PlantsController::Plant’ If you happen to get the following error undefined method `new’ for Widget:Module’ tweet at me to resolve it.

This means we need a Model. To create one well need to add a file named widget.rb (singular widget) inside the app/models directory with the code:
app/models

class Widget < ActiveRecord::Baseend

Check localhost:3000/widgets/new ~> We should now have our new page with fields and a button. Click that button and you should get ‘The action ‘create’ could not be found for WidgetsController

We need a create action. Drop the following code into your controller under you new action:
app/controllers/widgets_controller.rb

def create
end

Check localhost:3000/widgets/new ~> Click that button again and you will see a ‘missing template’ error.

Unlike new, create does not need a view. Instead we will just redirect users back to the index page after they create a new widget with redirect_to root_path in our create action.
app/controllers/widgets_controller.r

def create
redirect_to root_path
end

Create a widget
Check localhost:3000/widgets/new ~> Clicking the button again you will be sent to your index page.

That’s great, but it doesn’t actually save the data you filled in the fields. To accomplish that drop the following code inside your create action, above the redirect you just added.
/controllers/widgets_controller.rb

def create
@widget = Widget.new(params.require(:widget)
.permit(:name, :destroy, :age))
@widget.save
redirect_to root_path
end

Check localhost:3000/widgets/new ~> Fill in the fields and click the button. Nothing will show, but it is saving now.

The first step in getting it to show we will be to add a table into our index.html.erb file.
views/widgets/index.html.erb

<% @widgets.each do |widget| %>
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Age</th>
</tr>
<tr>
<td><%= widget.name %></td>
<td><%= widget.description %></td>
<td><%= widget.age %></td>
<td><%= link_to ‘Edit’, ‘#’ %></td>
<td><%= link_to ‘Show’, ‘#’ %></td>
<td><%= link_to ‘Delete’, ‘#’ %></td>
</tr>
</table>
<% end %>

Check localhost:3000 ~> There’s a place for it to show now but we’re getting a ‘undefined method `each’ for nil:NilClass’ error.

/controllers/widgets_controller.rb
Drop the following code inside your new action:
`@widgets = Widget.all`

Check localhost:3000 ~> Widgets appear!

/views/widgets/index.html.erb
Next we’ll replace the hashtag and quotes for the ‘Edit’ `link_to`line of code with `edit_widget_path(widget)` so that it looks like the following:


<td><%= plant.age %></td>
<td><%= link_to ‘Edit’, edit_widget_path(widget) %></td>
<td><%= link_to ‘Show’, ‘#’ %></td>

Check localhost:3000 ~> If you click our updated “edit” link you will get: “The action ‘edit’ could not be found for WidgetsController”

Under your create action add an edit action the same way you did for index, new, and create.
/controllers/widgets_controller.rb

def edit
end

Check localhost again ~> Do a hard refresh on the page and get: ‘Missing template widgets/edit’

Create a new view called edit.html.erb inside your /views/widgets directory and add the following code:
/views/widgets

<h1>Edit Widget</h1>
<%= form_for @widget do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :age %>
<%= f.text_field :age %>
<%= f.submit %>
<% end %>

Check localhost:3000/widgets/1/edit ~> And get this message: ‘First argument in form cannot contain nil or be empty’

Back in your controller add @widget = Widget.find(params[:id]) inside your new edit action, so that it looks like this:
/controllers/widgets_controller.rb

def edit
@widget = Widget.find(params[:id])
end

Check localhost:3000/widgets/1/edit ~> Click ‘Update Widget’ button and get this error: ‘The action ‘update’ could not be found for WidgetsController’

Under your edit action add an update action.
/controllers/widgets_controller.rb

def update
end

Check localhost:3000/widgets/1/edit ~> ‘Missing template widgets/update’

Update doesn’t get a view. We just want to make sure all the data is updated for our widget. `if` that happens we will just redirect the user to the index. `Else` should that not happen we’ll render the edit page again:
/controllers/widgets_controller.rb

def edit
@widget = Widget.find(params[:id])
if
@widget.update(params.require(:widget)
.permit(:name, :description, :age)
redirect_to root_path
else
render :edit
end

end

Check localhost:3000/widgets/1/edit ~> We should see that the changes we made work when you click the update button.

Next up the show link. Let’s fix that it currently doesn’t go anywhere by replacing the `’#’` with the path `widget_path(widget)`
/views/widgets/index.html.erb


<td><%= link_to ‘Edit’, edit_widget_path(widget) %></td>
<td><%= link_to ‘Show’, widget_path(widget) %></td>
<td><%= link_to ‘Delete’, ‘#’ %></td>

Check localhost:3000 ~> The action ‘show’ could not be found for WidgetsController is what we’ll get when we click the show link.

Under your update action add a show action.
/controllers/widgets_controller.rb

def show
end

Check localhost:3000/widgets/1 ~> ‘Missing template widgets/show’

Create a new view called show.html.erb and insert the following code:
/views/widgets

<h1><%= @widget.name %></h1>
<%= @widget.description %></br>
<%= @widget.age %></br>
<%= link_to ‘All Widgets’, widgets_path %> |
<%= link_to ‘Edit’, edit_widget_path(@widget) %>

Check 3000/widgets/1 ~> We get a ‘NoMethodError’: ‘undefined method `name’ for nil:NilClass’ because we haven’t set our widgets instance variable in the show action yet.

Add: @widget = Widget.find(params[:id]) Inside your show action.
/controllers/widgets_controller.rb

def show
@widget = Widget.find(params[:id])
end

Check localhost:3000/widgets/1 ~> You’ll see your widget’s name in bold and its description and age. Click the ‘All Widgets’ link to get back to the index page.

/views/widgets/index.html.erb
Swap project_path(project) for the final ’#’ in the delete link. We’ll also add in a comma and additional functionality that the destroy action requires in the form of: , method: :delete

The full line should now look something like this:


<td><%= link_to ‘Show’, plant_path(plant) %></td>
<td><%= link_to ‘Delete’, project_path(project), method: :delete %></td>
</tr>

Check localhost:3000 ~> Click on your ‘Delete’ link and you should get a familiar ‘Unknown action’ fail screen.

To remedy that we will add a destroy action.
/controllers/widgets_controller.rb

def destroy
end

Check localhost:3000 ~> Now the expected ‘Template is missing’ fail screen.

Just like our create and update actions, the destroy action will not require a
view. Instead we will verify the widget, destroy the widget, and then redirect the user to the index page within the action with the following code:
/controllers/widgets_controller.rb

def destroy
@widget = Widget.find(params[:id])
@widget.destroy
redirect_to widgets_path
end

Check localhost:3000 ~> Click the ‘Delete’ link and it should disappear.

Congratulations! You’re the proud owner of a very ugly and useless web app. Feel free to mess around with the code, break it, add some bootstrap, add another round of crud, whatever you want.

I hope this was a helpful tutorial for CRUD. Consider going back though and googling any terms, concepts, or syntax you want to have a deeper understanding of. Once you can get through this process with minimal referencing you will be on your way to develpoing Ruby on Rails apps.

A markdown version of this CRUD run-through is available on my github: https://github.com/MrJadaml/widgets .

If you have any question feel free to comment in the side bar or tweet at me: @Mrjadaml

--

--

Jadam
gSchool Stories

A chronic creative in Denver currently exploring street art in society though the @DenverStreetart project. All while trying to live a sustainable lifestyle.