class: middle, center # Rails ![Rails](img/rails.png) [http://pjb3.me/bewd-rails](http://pjb3.me/bewd-rails) .footnote[ created with [remark](http://github.com/gnab/remark) ] --- # Create A New Project Create a new Rails app using the Postgresql database .terminal $ rails new betastore -d postgresql create create README.rdoc create Rakefile create config.ru create .gitignore create Gemfile create app create app/assets/javascripts/application.js create app/assets/stylesheets/application.css create app/controllers/application_controller.rb create app/helpers/application_helper.rb create app/views/layouts/application.html.erb create app/assets/images/.keep create app/mailers/.keep create app/models/.keep create app/controllers/concerns/.keep create app/models/concerns/.keep ... --- # Project Structure .terminal betastore ├── app - Application code ├── config - Configuration code ├── db - Database modifications ├── lib - Generic code ├── log - Log files ├── public - HTML/CSS/JavaScript/Images ├── test - Test code └── vendor - 3rd party code --- # Model-View-Controller (MVC) The MVC pattern keeps persistence and presentation code separate .terminal ├── app │ ├── controllers │ ├── models │ └── views └── config └── routes.rb ## Router Controls which controller action handles the request ## Controller Coordinates between models and views ## Model (persistence) Used by the controller to store/retrieve data from the database ## View (presentation) Templates used to generate HTML --- # How Requests Are Handled in Rails Apps ![MVC](img/request_diagram.png) 1. Browser makes an HTTP request 2. Router determines which controller action should handle the request 3. Controller action uses models to store/retrieve data 4. Models make SQL queries to store/retrieve data from the database 5. Controller passes data to the view templates to generate an HTML page 6. Controller returns the HTML page to the browser to be rendered --- # Rails Generators The scaffold generators will generate code for you For our application, let's generate a "coming soon" page where we collect email addresses .terminal $ rails generate scaffold subscription email invoke active_record create db/migrate/20130923234940_create_subscriptions.rb create app/models/subscription.rb invoke test_unit create test/models/subscription_test.rb create test/fixtures/subscriptions.yml invoke resource_route route resources :subscriptions invoke scaffold_controller create app/controllers/subscriptions_controller.rb invoke erb create app/views/subscriptions create app/views/subscriptions/index.html.erb create app/views/subscriptions/edit.html.erb create app/views/subscriptions/show.html.erb create app/views/subscriptions/new.html.erb create app/views/subscriptions/_form.html.erb ... --- # Database Setup ## Config database Replace the contents of `config/database.yml` with this: ```yml development: adapter: postgresql database: betastore_development test: adapter: postgresql database: betastore_test ``` Because you are using Postgres.app, you can connect without a username or password ## Run migrations .terminal $ rake db:create $ rake db:migrate == CreateSubscriptions: migrating ============================================ -- create_table(:subscriptions) -> 0.0044s == CreateSubscriptions: migrated (0.0045s) =================================== `rake` is command for running tasks, run `rake -T` to see the list You can create your own, we will cover that later --- # Running the server .terminal $ rails server => Booting WEBrick => Rails 4.0.0 application starting in development on http://0.0.0.0:3000 => Run `rails server -h` for more startup options => Ctrl-C to shutdown server [2013-09-23 19:56:40] INFO WEBrick 1.3.1 [2013-09-23 19:56:40] INFO ruby 2.0.0 (2013-06-27) [x86_64-darwin12.4.0] [2013-09-23 19:56:40] INFO WEBrick::HTTPServer#start: pid=387 port=3000 Your server will continue running in this bash shell. You can press ctrl+c to stop it, but leave it running. Go to http://localhost:3000 to see the app --- .center[![Welcome](img/welcome.png)] --- # Our App We are just getting started with our Betastore app, so for now we want to show a form on the home page that will allow future customers to give us their email address so we can send them an email when our store goes live. We will store the email addresses we collect in our database. --- # Root Route `config/routes.rb` ```ruby Betastore::Application.routes.draw do resources :subscriptions root :to => 'subscriptions#new' end ``` Remove comments and add root route to our sign up page --- # View The Routes .terminal $ rake routes Prefix Verb URI Pattern Controller#Action subscriptions GET /subscriptions(.:format) subscriptions#index POST /subscriptions(.:format) subscriptions#create new_subscription GET /subscriptions/new(.:format) subscriptions#new edit_subscription GET /subscriptions/:id/edit(.:format) subscriptions#edit subscription GET /subscriptions/:id(.:format) subscriptions#show PATCH /subscriptions/:id(.:format) subscriptions#update PUT /subscriptions/:id(.:format) subscriptions#update DELETE /subscriptions/:id(.:format) subscriptions#destroy root GET / subscriptions#new Routes are executed in order until a match is found `:` in a URI pattern represents a variable, so `/subscriptions/:id` matches `/subscriptions/1` The format of `subscriptions#index` means the `index` method of the `SubscriptionsController` --- # Subscriptions New The subscription sign up form that was generated for us looks like this: .center[![Scaffold New](img/scaffold_new.png)] --- # What We Want Lets change it to look like this: .center[![Betamore Sign Up](img/betamore_sign_up.png)] --- # Subscriptions Controller Here is a simplified version of what you see in `app/controllers/subscriptions_controller.rb`: ```ruby class SubscriptionsController < ApplicationController def new @subscription = Subscription.new end def create @subscription = Subscription.new(subscription_params) if @subscription.save redirect_to new_subscription_path, notice: 'Subscription was successfully created.' else render action: 'new' end end private def subscription_params params.require(:subscription).permit! end end ``` The new action sets up a variable for the form. The create action handles actually creating a record in the database based on the form data passed in. We will cover how this works in more detail in future lessons. --- # Redirects A redirect is an HTTP response with no body abut a `Location` header that instructs the browser to load a different URL .terminal $ curl -I http://google.com HTTP/1.1 301 Moved Permanently Location: http://www.google.com/ Content-Type: text/html; charset=UTF-8 Date: Thu, 26 Sep 2013 20:59:44 GMT Expires: Sat, 26 Oct 2013 20:59:44 GMT Cache-Control: public, max-age=2592000 Server: gws Content-Length: 219 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Alternate-Protocol: 80:quic --- # Views Views in Rails are templates written in Embedded Ruby (ERB), which is similar to PHP .terminal Hello, <%= @name %> if name is set to `"Paul"`, that becomes .terminal Hello, Paul `<% %>` are used for expressions that don't return a value .terminal <% if @name %> Hello, <%= @name %> <% else %> Welcome, Guest <% end %> The code between the `<% %>` and `<%= %>` is Ruby --- # New view Replace the contents of this file `app/views/subscriptions/new.html.erb` .terminal <%= render 'form' %> --- # Form Partial Replace the contents of this file `app/views/subscriptions/_form.html.erb` .terminal <%= form_for(@subscription) do |f| %>
<%= f.label :email, "Find out when we go live:" %> <%= f.text_field :email %> <%= f.submit "Sign Up" %>
<% end %> <% if flash.present? %> <% flash.each do |k,v| %>
<%= v %>
<% end %> <% end %> --- # Layout Replace the contents of this file `app/views/layouts/application.html.erb` .terminal
Betastore
<%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %>
<%= image_tag "logo.jpg", width: 600 %> <%= yield %>
--- # Get the logo .terminal $ mkdir public/images $ cd public/images $ curl -o logo.jpg http://whatweekly.com/wp-content/uploads/2012/08/betamorelogo.jpg --- # Sign Up Form Go to http://localhost:3000 to see the sign up page .center[![Betamore Sign Up](img/betamore_sign_up.png)] --- # Success Go ahead and submit an email address and you should see the success page: .center[![Betamore Sign Up Success](img/betamore_sign_up_success.png)] --- # Rails Console Wouldn't it be nice if we could look into our database to see what records we have? You can boot up an IRB session with the Rails environment loaded up using the command `rails console`: .terminal $ rails console Loading development environment (Rails 4.0.2) You can then get the last subscription created like this: .terminal >> Subscription.last => #
--- # psql We can also use Postgres' command line tool to query our database: .terminal $ psql -d betastore_development psql (9.3.1) Type "help" for help. betastore_development=# select email from subscriptions; email -------------------- mail@paulbarry.com (1 row) `psql` is like IRB for your database. The prompt ends in a `#` character. You type in a SQL query and press enter and it shows you the result. You can press `ctrl+d` to exit. This is just a simple query to get all the email addresses in the database. We will learn SQL in-depth in a future class. --- # Navicat There is an app called **Navicat Essentials for PostgreSQL** available in the Mac App Store for $6.99, I recommend purchasing that. It is a graphical tool for working with your database. Once you have it installed and running, click on connection and you will see something like this: .center[![Navicat Connection](img/navicat_connection.png)] Enter `localhost` for **Connection Name**, `betastore_development` for **Default Database**, your Mac username for **User Name**, leave the **Password:** field blank and then check the box **Save password**. Press the button "Test Connection" and you should see something similar to the following slide. --- # Navicat Connection .center[![Navicat Test Connection](img/navicat_test_connection.png)] --- # Navicat Once connected, you navigate to your database in the left-side menu: ![Navicat Database](img/navicat_database.png) Then you can double-click on the subscriptions table and see the rows that are in the table: ![Navicat Table](img/navicat_table.png) --- # Review We're just getting started with our Rails app. At this point we want to make sure we understand the high-level components of a Rails app and how they relate to one another: ![MVC](img/request_diagram.png) 1. Browser makes an HTTP request 2. Router determines which controller action should handle the request 3. Controller action uses models to store/retrieve data 4. Models make SQL queries to store/retrieve data from the database 5. Controller passes data to the view ERB templates to generate an HTML page 6. Controller returns the HTML page to the browser to be rendered We will be exploring each of these components in-depth in our upcoming classes.