aint no party like an mvc party


Ashley Williams, NYCDA

Thursday, 28 March 2013

WHat is an mvc?

models


USER
id: integer
name: string
email: string

MICROPOSTS
id: integer
content: string
user_id: integer

Creating a resource


rails generate scaffold User name:string email:string

rails generate = a command to rails to make a resource

scaffold = make the model, view, and controller

User = name of the resource

name:string = data attribute of the resource

email: string = data attribute of the resource

czech it out!


bundle exec rake db:migrate
rails s



1.  update the database to include our new Users resource

2.  run a local server so that we can see the site

ROSES, Smell em


/ users                    index       page to list all the users
/users/1                show        page to show user with id 1
/users/new          new          page to make a new user
/users/1/edit      edit           page to edit user with id 1


explore your new resource by entering these URLs manually into your browser 


does this remind you of anything from the beginning of the class?

MVC IN ACTION


MVC IN ACTION

  1. The browser issues a request for the /users URI.
  2. Rails routes /users to the index action in the Users controller.
  3. The index action asks the User model to retrieve all users (User.all).
  4. The User model pulls all the users from the database.
  5. The User model returns the list of users to the controller.
  6. The controller captures the users in the @users variable, which is passed to the index view.
  7. The view uses embedded Ruby to render the page as HTML.
  8. The controller passes the HTML back to the browser.

MVC IN ACTION

  • pages correspond to actions in the controller
  • a controller is just a collection of actions
  • actions: index, show, new, create, edit, update, destroy

Actions either RENDER PAGES or MODIFY DATA


OK, SO LET'S REVIEW


  • rails generate scaffold <RESOURCE> <ATTRIBUTES>
  • bundle exec db:migrate :This adds the resource to the schema for a database
  • the controller for that resource is created; the controller hold actions
  • routes.db matches actions with URLs
  • These actions perform HTTP requests at these URLs
  • They either render pages or modify data (or both!)

Microposts time


  • What is our first step?

microposts


rails generate scaffold Micropost content:string user_id:integer
 
  • What do we need to do now? 

microposts

rails generate scaffold Micropost content:string user_id:integer
bundle exec rake db:migrate


Let's see what we did. How?

Microposts


rails generate scaffold Micropost content:string user_id:integer
bundle exec rake db:migrate
rails s

open your browser to localhost:3000


What do you expect to see in your routes.rb file?

What does that mean for your controller and views?

Microposts

What is the action and purpose of each of these?
Where could you go to look?


WHAT ARE WE MISSING


Take a second and play around with your new webapp. There are a lot of things you *can* do. Are there things that aren't quite right? 


Try to come up with at least 3.

Think about...
How do microposts relate to users? What kind of info can you enter for user attributes? Micropost attributes?

MODEL WEAKNESSes

  • No validations! We can use whatever data we want in any attribute field. Blank names, invalid email addresses...
  • No authentication/authorization! Users can't sign in/out and any user can do anything!
  • No layout! This thing looks uggggggly.
  • No real understanding!

Get validated

VALIDATIONS are added to MODELS
validates <attribute_name>, <validation_type>: <value>


e.g.

validates :content, :length=> { :maximum => 140 }
validates :user_id, :presence=> true

RAILS validation HELPERS

  • presence: is this attribute required to have a value?
  • length: how many chars or numbers?
  • format: what should the value of this attribute look like?
  • uniqueness: can other objects of this model have the same value for this attribute?


All of them are listed here:

validating an email address


  • the :format helper requires us to use REGULAR EXPRESSIONS (regexp, pronounced "reg-eps")
  • we will use a pre-written one, but there are many
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }

  • If you want to learn about regexps, check out this online ruby regexp generator/editor:

http://www.rubular.com


REG EXPS: VALIDATING EMAIL


TRY IT OUT


  • Add a uniqueness validation to the user's email address
  • Add a length validation to the user's name (<=50chars)
  • Add a length validation to the micropost content (<=140chars)
  • Add a presence validation to the user's email address
  • Add a presence validation to the user's name address
  • Add a presence validation to the microposts' user_id

A CAVEAT ABOUT UNIQUENESS

What can go wrong? Here’s what:

  • Luke signs up for the sample app, with address luke@skywalker.com.
  • Luke accidentally clicks on “Submit” twice, sending two requests in quick succession.
  • The following sequence occurs: request 1 creates a user in memory that passes validation, request 2 does the same, request 1’s user gets saved, request 2’s user gets saved.
  • Result: two user records with the exact same email address, despite the uniqueness validation.

what? how? really?


Really.

In order to fix this we need to enforce uniqueness on the database level.

To do this we need to change our model.

A BRIEF INTRO TO DATABASES


Databases are sets of 'tables' that relate to each other in certain ways.

The tables represent our models.

These tables have columns that represent our attributes

Every database has a file that holds the names of these tables and their associated columns. It is called the schema.

A BRIEF INTRO TO DATABASES


For most databases, you have to write the schema yourself.

In Rails, you don't have to. Instead, the schema is dynamically generated.

We saw this when we generated the User and Microposts models.

We can add to these models by creating migrations.

Migrations


We can created a migration in terminal by typing:
rails generate migration <name_of_migration>

This will create a file in the db>migrations folder that looks like this

class <name_of_migration> < Activerecord::Migration
   def change
   end
end

Migrations

We can tell Rails to add a column to a model by typing this
add_column <model>, <attribute>, <type>

all of the values above should be typed as symbols, meaning put a colon in front of the name, e.g. :symbol

We can tell Rails to add an index to an attribute by typing this
add_index <model>, <attribute>, unique: true

Migrations

Everytime we write a migration, we need to tell Rails to run it.
We can do that by typing this in Terminal:
bundle exec rake db:migrate

Try it out

  • Add a website field to our User model

CASE SENSITIVE

By default, Rails is case-sensitive. This means that 

LUKE@SKYWALKER.COM

is different from

luke@skywalker.com

To fix, we need to update our model:
before_save { |user| user.email = email.downcase }

aint no party like an mvc party

By ag_dubs

aint no party like an mvc party

  • 671