Ruby on Rails Tutorial Modify a Craigslist Clone

What to expect in this guide People start learning Rails for all sorts of reasons. Whether you have been programming for years and want to give web development in Ruby a try, or you are a complete coding newbie wanting to see if programming is for you, Rails is a great tool to learn. Most of the resources in this guide assume no programming knowledge — more advanced readers may choose to skim the introductory sections of each to learn the particulars of Ruby and Rails. In this guide, we are going to cover: The Rails landscape Installation of the necessary tools What is Ruby What is Rails Changing the structure of your database Models Interacting with your application from the command line Making souped-up HTML Adding URLs Handling requests Making reusable chunks of display code Building forms Where to go next Before getting started, you should pick a goal. This tutorial will walk you though modifying a sample application, but the real test is when you apply these concepts to something unique. This could be a personal blog, or a site for your dog walking business... whatever! "Building a better Facebook" is probably a bit ambitious for a first project – keep it simple. Having a real problem to solve in the back of your mind will help keep you motivated, and allow you to ask yourself "how would this apply to my project?" as you cover each concept. For beginners It's been said that it takes 10,000 hours of practice to master a skill, and programming is a particularly difficult one – if it were easy, there would be a lot more programmers in the world. There's a quote: Give someone a program, you frustrate them for a day; teach them how to program, you frustrate them for a lifetime. Don't be discouraged if it isn't making sense. There are tons of resources, online and in-person, that can help you get unstuck. Welcome to Thinkful's Ruby on Rails Tutorial! Click here to share what you'd like to learn about next :) Get notified when new guides are released

What is Ruby on Rails? Rails is a framework written in Ruby that helps you build web applications. There are a lot of concepts packed into that one sentence that may be new to you, but don't worry, we'll get you feeling cozy. Ruby is a programming language. While there are many others (e.g. Python and Java) and they can mostly accomplish the same tasks, Ruby is a particularly readable and fun one, so you've made a good choice. If we were building a house, Ruby would be the raw materials: plywood, nails, etc. Rails is a framework written in (and for) Ruby – think of this as the frame for the house. It gives you certain parameters to work within, but you have a lot of flexibility about how the final product turns out. Just like the frame is built from the same raw materials that will be used to fill in the details of the house, Rails is written in Ruby, and you will add all of your application-specific features using Ruby (and HTML, and CSS, etc.). Through your instructions in Ruby, Rails will take information stored in a database and send HTML to be displayed to the user in a browser. Let's get going!

The first rite of passage of programming is getting the necessary tools installed. Thankfully, there is a handy guide that describes how to do just that. Install Rails

IRB, Scripts, and the Ruby Language It's really tough to have a conversation if you don't speak the language, so Ruby is the next step on the way to building your first app. Like most programming languages, Ruby is written in source code files as text, which is then run one of two ways: Interactively through the REPL (Read-Evaluate-Print Loop), which in Ruby is called IRB, i.e.

$ irb > Ruby.goes.here Run as scripts, i.e. $ ruby file.rb One convention to note: lines that start with a $ (like above) means they are commands, intended to be run at the command line. Lines that start with # or are surrounded by <!-- ... --> are comments, just there as helpful info. Give these resources a try to learn the basics of programming in Ruby: Try Ruby Ruby Bits If you run into problems where you're not sure the state that your program is in, just remember: puts is your friend. If you aren't sure what the value of a variable is at a certain line, just print it out to your console. Additional resources Codecademy

Programming Ruby (the "Pickaxe" book)

A Framework for Ruby Now that you have the basics down, you are ready for the main course: Rails! Gems are reusable plugins that are published by the community, the most popular of which is Rails. Rails itself is made up of many smaller gems. Sample Application Let's start with a super simple classifieds site called Thinklist (a Craigslist clone), where we can create and view individual listings. To get it set up, do the following: Download and unzip the starter application code Open up your terminal Navigate to the Thinklist directory (a.k.a folder) using the cd command (a.k.a. "change directory"), followed by the path (actual location may vary): $ cd ~/Downloads/thinklist-start Install the app's gem dependencies – which are listed in the Gemfile – using Bundler: $ bundle Set up the database: $ rake db:setup Start the server: $ bin/rails server Open the application in your browser: http://localhost:3000 You should now see something that looks like this: Adding On The application is fairly simple, but play around with it a bit to get a feel for it. We are going to use this application as a starting place, and learn some Rails by adding support for categories. Don't worry if you get lost – after each step, we will include: A link to the code as it should appear

A link to the "diff" showing what changed Open up the folder in your Sublime Text (or other code editor of choice) by dragging the folder onto the editor application icon. You will now see a bunch of folders and files – these are the guts of your Rails app. Let's get started!

Changing the structure of your database In web applications, information is stored in a database. Think of a database as a bunch of interconnected spreadsheets, called tables. Take a look at the existing structure in db/schema.rb. In an application using a SQL database (like Thinklist), each type of thing (users, products, etc.) will generally have it's own table. Let's get the category structure in place. Generate Use the Rails generate command to set up the migration, which contains instructions for changes to the structure of the database. This could include modifying an existing table (e.g. adding a column), or in this case, creating a new one. Run: $ bin/rails generate migration CreateCategories Code

Diff Change Open the newly created migration file, db/migrate/XXXXX_create_categories.rb. Here, we will need to specify exactly what we want changed, which in this case will be adding a categories table, as well as a reference (a.k.a. foreign key) from the listings so they can each be assigned a category. Add this to the file: # modify db/migrate/XXXXX_create_categories.rb class CreateCategories < ActiveRecord::Migration def change create_table :categories do |t| t.string :name t.timestamps end add_reference :listings, :category end end Code

Diff Confused about where to add your code? The first commented line in each code block indicates which file you should be working in, which might not exist yet. If you're still confused about where you should be adding code within the file, check out the "diff" link included below each block. Remember - the "code" link will show you the code as it should appear at that point, and the "diff" shows what was changed from the previous step. Run Though the migration file has been generated, we now need to apply the change. Rake is another gem that lots of Rails-related commands are run through. $ bin/rake db:migrate Assuming the migration was successful, you will see the changes reflected in db/schema.rb. Code

Diff

Models are what deal with data in your application – they handle passing information to and from the database. You can see our (currently very simple) model definition for Listings in app/models/listing.rb. Now that we have the database structure in place for categories, we need to create a corresponding model. The file and class name are the singular form of the table name (categories), and are case-sensitive. # create app/models/category.rb class Category < ActiveRecord::Base has_many :listings, dependent: :nullify end Code

Diff Models in Rails are built on top of a gem called ActiveRecord, so you will notice that your Category model inherits (the < part) from ActiveRecord::Base. The has_many line tells Rails that there is a relationship (a.k.a. association) between the listings and the categories. Don't worry about dependent: :nullify for now; it just tells your app how to deal with a record when its owner is deleted (in this case, the Category). Now let's set up the other half of the relation: # modify app/models/listing.rb class Listing < ActiveRecord::Base belongs_to :category # ... end Code

Diff This tells Rails that Listing's can be assigned a category. has_many with a belongs_to is called a one-to-many relationship, because one Category can have many Listings, but a Listing can have at most one Category.

Interacting with your application from the command line The easiest way to understand how models work are to interact with them in the Rails console. The console is IRB (which we've already seen), but you are able to make calls to your Rails application code. To open it, run: $ bin/rails console >> At this new prompt, type the following, then press ENTER to execute the line: Category.count As expected, none exist yet. Let's create one: Category.create(name: "Antiques") Both #count and #create are class methods provided by ActiveRecord, but we can interact with individual instances/categories as well: Category.count category = Category.last category.name category.created_at Go ahead and create a few more categories. When done, type exit and press ENTER to quit the Rails console.

Making souped-up HTML Views are the part of Rails that generate HTML to be sent back to the browser... in other words, what the user will actually see. In Rails, ERB templates are used to insert Ruby code into HTML files, so that you can generate pages depending on what record the user is viewing, whether they're logged in or not, etc. Helpers are methods that can be used within your views, whether provided by Rails or written by you. We will want a way to see all of the categories, so let's add a dropdown to the navigation bar: Replace the existing "Listings" link with: <!-- modify app/views/layouts/application.html.erb --> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Categories <span class="caret"></span></a> <ul class="dropdown-menu" role="menu"> <li> <%= link_to 'All', root_path %> </li> <% Category.order('name ASC').each do |category| %> <li> <%= link_to category.name, '#' %> </li> <% end %> </ul> </li> Code

Diff There are a bunch of things to point out here. Besides the normal HTML, <% ... %> tags execute Ruby, and <%= ... %> tags output the result of the expression. link_to is a built-in helper that takes the text to display and the model to create an anchor tag to. The various attributes (class, role, etc.) on the HTML tags are there to apply styling from Bootstrap. Bootstrap is a framework that can be used with any site to make styling pages easier – basically to give minimal, good-looking defaults for buttons, navigation, that work well on a range of browsers and screen sizes. For new projects, you can learn how to set it up here. You'll notice, however, after refreshing the page, all of the category links go to #... a.k.a. nowhere. Modify them to link to the category page: <!-- modify app/views/layouts/application.html.erb --> <!-- before --> <%= link_to category.name, '#' %> <!-- after --> <%= link_to category.name, category %> Code

Diff We now get an error, "undefined method category_path". That page doesn't exist yet!

Adding URLs When you visit a Rails website, the request comes in through the router, which determines the URL structure of your application. Let's add a URL to view all listings in a particular category. # add to middle of config/routes.rb resources :categories, only: [:show] Code

Diff When the page is refreshed, you will no longer get an error, because we've now told Rails the URL structure for viewing a particular category. To see all URLs that your application supports, use this command: $ bin/rake routes Prefix Verb URI Pattern Controller#Action ... category GET /categories/:id(.:format) categories#show When you click on an individual category, however, you will get an "uninitialized constant CategoriesController" error, because we haven't set up a controller to handle the request yet.

Handling requests The router determines which controller action to send the requests to. After the controller receives the request, it then gathers up the models it needs, and renders the appropriate view. Create a controller for categories: # create app/controllers/categories_controller.rb class CategoriesController < ApplicationController def show @category = Category.find(params[:id]) end end Code

Diff Similar to the Category model with ActiveRecord::Base, controllers in our app inherit from our ApplicationController, which in turn inherits from ActionController::Base. Instance variables (the ones that start with @) are used to pass data from the controller to the view. Refresh the category page, and you should see a new error: "Missing template categories/show". /categories/ID is hitting the show action/method, which implicitly tries to render the corresponding view (notice that when we ran bin/rake routes previously, /categories/:id(.:format) corresponded to categories#show - that's the template it's looking for!). That doesn't exist yet, so let's put in that last piece.

Making reusable chunks of display code Rails templates are organized by folders corresponding to the controller, and the filename corresponding to the action. The view for categories#show, for example, will live in app/views/categories/show.html.erb. Let's say we want to make our list of listings display the same on the homepage, as well as on the individual category pages. We could copy-and-paste the code from the listings index page, but within an application, copy_and_paste == 'baaaaddd'. Instead, let's extract the code that handles rendering that part of the page, so it can be used in both places. Take everything from app/views/listings/index.html.erb except the &lr;h1>...&lr;/h1> and move it into a new file called app/views/listings/_list.html.erb. Template filenames that start with an underscore are known as partials, which are intended to be used from within other views. Once the code is in there, change all of the occurrences of @listings to use a local variable (listings) instead (i.e. remove the @s). This will allow that code to be more portable. Where the list code was within our existing template, have it render the new partial instead: <!-- modify app/views/listings/index.html.erb --> <h1>Listings</h1> <%= render partial: 'list', locals: { listings: @listings } %> Code

Diff After verifying that the homepage still renders correctly, go ahead and add the page to view a category, which will look a lot like the listings/index.html.erb template above, but using the category name as the heading instead. <!-- create app/views/categories/show.html.erb --> <h1><%= @category.name %></h1> <%= render partial: 'listings/list', locals: { listings: @category.listings } %> Code

Diff