Ruby on Rails – create new from web

When you create an @variable as opposed to a variable, the @ tells that it is an instance variable.

By opening config > routes.rb, we can use the code resources :articles to give a lot of different paths to articles (index, create, new, edit, show, update, and destroy).

A nice thing about Ruby on Rails is the program kind of tells you what to work on next.  We want to do a new article, so if I type in my browser: 0.0.0.0:3000/articles/new, it will tell me why it can’t do that (no route).  So go to route.rb and give it the resources to do it.  Reload the page and see that it says uninitialized ArticleController.  Guess where we go next?  Yup.  App > Controllers > new file > “articles_controller.rb”.  The code is as follows:
class ArticlesController < ApplicationController
  def new
  end
end
Save it and reload 0.0.0.0:3000/articles/new.  Now it is missing the template (view).  Go to views and create a new folder called articles.  Inside that folder create a file called new.html.erb.  Put a <h1> at the top telling what the page will do: “Create a new article”.  Reload the site and see if you can see the <h1>.  And we can!  Perfect.  Now we need to create a form to put on that page so the user can create a new article.  RailsGuides has a great site talking about all the parts of forms that rails provides but for now we’re just going to do some basic things.

So on the new.html.erb file, type:
<h1>Create a new article</h1>
<%= form_for @article do |f| %>
<% end %>
When you save and run this, you’ll see an error.  It says the first argument can’t be empty (because we haven’t made @article yet).  So we need to go to articles_controller.rb and create it.  So now it should have:
class ArticlesController < ApplicationController
  def new
    @article = Article.new
  end
end
Since we got all of that working, we can now build the form on new.html.erb.
<h1>Create a new article</h1>
<%= form_for @article do |f| %>
  <p>
    <%= f.label :title %><br/>
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :description %>
    <%= f.text_area :description %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
Everything works, but when you try to click “Create Article” it won’t work.  The error says “action create couldn’t be found in ArticlesController”.  So we need to define create in ArticlesController.  That is done by typing:
class ArticlesController < ApplicationController
  def new
  end
  def create
    #this will show you what is happening, but just comment it out
    #render plain: params[:article].inspect
    @article = Article.new(article_params)
    if @article.save
      flash[:notice] = "Article successfully created
      redirect_to articles_path(@article)
    else
      render 'new'
    end
  end
     
  private
    def article_params
      params:require(:article).permit(:title, :description)
    end
end

The next thing we need to do is figure out how to deal with flash[:notice].  Views > layouts > application.html.erb is a wrapper for all the pages, so we’ll see this html code on all pages.  This would be a good place to put our notice messages.  So in the body of that page (right above <%= yield %>, put:
<% flash.each do |name, msg| %>
  <ul>
    <li><%= msg %></li>
  </ul>
<% end %>

This all looks good but we don’t have a way of displaying the errors or the validations that occur when you click “Create Article”.  We can fix that by entering some code on the new.html.erb page.  Right below h1, put:
<% if @article.errors.any? %>
<h2>The following errors prevented the article from getting created:</h2>
  <ul>
    <% @article.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
    <% end %>
  </ul>
<% end %>

Now when I try to create an article with no title, I do get which errors are occurring so that I know why I can’t make an article.  But when I put in a correct title and description, I get a message “The action ‘show’ could not be found in ArticlesController.”  So I need to define show in ArticlesController found in app > controllers > articles_controller.rb.  It doesn’t seem to matter where I place the define, but I’m going to put it right below create.
def show
  @article = Article.find(params[:id])
end
You now have the action, but are still missing the template.  So go create that under app > view > articles > create a new file called show.html.erb.  On that file, we need to type the code to place the info on that page:
<h1>Showing selected articles</h1>
<p>
  Title: <%= @article.title %>
</p>
<p>
  Description: <%= @article.description %>
</p>

That should be it!  We can now create articles by going to 0.0.0.0:3000/articles/new.  Make sure to commit and push to git and we are done for now.  Next entry will be about editing entries.