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
- The browser issues a request for the /users URI.
- Rails routes /users to the index action in the Users controller.
- The index action asks the User model to retrieve all users (User.all).
- The User model pulls all the users from the database.
- The User model returns the list of users to the controller.
- The controller captures the users in the @users variable, which is passed to the index view.
- The view uses embedded Ruby to render the page as HTML.
- 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:
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