Code for Startup MVP (Ruby on Rails) Session 2

59
Learning to Code for Startup MVP Presented by Henry Shi

description

Second Session on Learning to Code for Startup MVP's using Ruby on Rails.

Transcript of Code for Startup MVP (Ruby on Rails) Session 2

Page 1: Code for Startup MVP (Ruby on Rails) Session 2

Learning to Code for Startup MVP

Presented by Henry Shi

Page 2: Code for Startup MVP (Ruby on Rails) Session 2

Agenda – Wednesday November 7

1. Review of Last Session

2. Ruby Basicso Syntax and semanticso Practice makes perfect

3. Rails Models (but no Bottles)o ORM and SQL introductiono Migrationso Making the User modelo Signup/Signin/Signout

Page 3: Code for Startup MVP (Ruby on Rails) Session 2

Prework – Setup

• Windows (not recommended if possible):o http://railsinstaller.org/o Use Sublime Text for your text editor

• OSX:o http://railsinstaller.org/o This includes osx-gcc-installer (200mb)

• Linux:o http://blog.sudobits.com/2012/05/02/how-to-install-rub

y-on-rails-in-ubuntu-12-04-lts/

Page 4: Code for Startup MVP (Ruby on Rails) Session 2

Prework - Git

Install git if not already included:http://www.git-scm.com/book/en/Getting-Started-Installing-Git

Configure Git:git config --global user.name "Your Name“git config --global user.email

[email protected]

Page 5: Code for Startup MVP (Ruby on Rails) Session 2

Review of Last Session

1. The Web and How it Works

2. Git/Github

3. Rails and Ruby

4. Heroku

Page 6: Code for Startup MVP (Ruby on Rails) Session 2

The Web - Overview

Page 7: Code for Startup MVP (Ruby on Rails) Session 2

GIT/GITHUB

• What is GIT?• Distributed Version Control System (DVCS)

• Why should I care?o Never lose data or accidentally overwrite, delete fileso Collaborate with peers anywhere and stay in sync

automatically (no more _v1, _v2, _final, _final_final…)o Compare and track changes over time, and easily

revert changeso Deploy code to real web

Page 8: Code for Startup MVP (Ruby on Rails) Session 2

Rails

• Ruby on Rails is an open-source web framework that’s optimized for programmer happiness and sustainable productivity.

• It lets you write beautiful code by favoring convention over configuration.

• 80/20 Rule =>great for Startup MVP

Page 9: Code for Startup MVP (Ruby on Rails) Session 2

Heroku

What is Heroku?• a hosted platform built specifically for

deploying Rails and other web applications in 1 command

• Best thing since sliced bread

Page 10: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Programmer’s Best Friend

• Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write.

• We will only cover the necessary syntax needed to create a rails app

• Thankfully, its not a lot

Page 11: Code for Startup MVP (Ruby on Rails) Session 2

Interactive Ruby Shell

• For the following slides, you should follow along with the Interactive Ruby Shell (irb)

• Open a terminal, type irb and press enter

Page 12: Code for Startup MVP (Ruby on Rails) Session 2

Ruby - Strings

• Characters (letters, digits, punctuation) surrounded by quotes

• Can perform operations on strings, concatenation, length, empty, etc

food = "chunky bacon"puts "I'm hungry for, #{food}!">> "I'm hungry for, chunky bacon!"

“Hello” + “World”>> “Hello World"“Henry”.empty?>> false

Page 13: Code for Startup MVP (Ruby on Rails) Session 2

Ruby - Numbers

• Self Explanatory

• Can add different types of numbers directly

123.class>> Fixnum

(123.0).class>> Float

Page 14: Code for Startup MVP (Ruby on Rails) Session 2

Ruby - Symbols

• Characters (letters, digits, punctuation) preceded by colon (:)

• Lightweight strings• immutable

food = :hello:asf3fasdf.class>> Symbol

Page 15: Code for Startup MVP (Ruby on Rails) Session 2

Ruby - Array

• List surrounded by square brace and separated by commas, zero indexed

• Can perform operations on arrays, add, remove, reverse etc

a = [1, 2, 3]b = ('a'..'e').to_a # ["a", "b", "c", "d", "e"]c = %w[foo bar baz quux] # ["foo", "bar", "baz", "quux"]d = "foo bar baz".split # ["foo", "bar", "baz"]

a = a.reverse # [“world”, “hello”, 3, 2, 1]

a.push(“hello”) # [1, 2, 3, “hello”]a << “world” # [1, 2, 3, “hello”, “world”]

a[0] # 3

a.delete(“hello”) # [“world”, 3, 2, 1]

Page 16: Code for Startup MVP (Ruby on Rails) Session 2

Ruby - Hash

• Hash is a dictionary surrounded by curly braces• Dictionaries match words with their definitions

• New (better) hash notation in Ruby 1.9+

• Important for passing optional params (can omit braces if hash is last argument)

my_var = {:sup => "dog", :foo => "bar"}my_var[:foo]>> "bar“my_var[:nk] = “new” # {foo : "bar“, nk: “new” , sup : "dog" }

{sup : "dog", foo : "bar"}.class #Ruby 1.9+ >> Hash

Page 17: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Methods (Functions)

• Function that performs some operations when called and returns something when done

• Implicitly returns last expression in method• Use Ruby poetry style:

o a.should(be() >= 7) #bado a.should be >= 7

Page 18: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Blocks

• Block of Code surrounded by curly braces

• Can use Do and end to indicate block as well

• Can take argumentso variables surrounded by pipe (|)

2.times { puts "hello"}>> "hello">> "hello"

2.times do puts "hello“end

2.times do |i| puts "hello {#i}”end>> "hello 0">> "hello 1"

Page 19: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Blocks (Advanced Only)

• Blocks are closures: they carry their environment around with them

• Block are anonymous λ functions• Examples compared to scheme:

o (map '(lambda (x) (+ x 2)) mylist )

o mylist.map { |x| x+2 }

• Try this: ('a'..'z').to_a.shuffle[0..7].join

(map'(lambda (x) (+ x 2))

(filter '(lambda (x) (even? x)) mylist))

mylist.select {|x| x.even?}.map {|x| x+2 }

Page 20: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Blocks, Methods, Hashes

def list_hash(options = {:default => "foo"})options.each do |key, value|

puts "key '#{key}' points to '#{value}'"end

end

list_hash override : "bar")>> "key 'override' points to 'bar'"

list_hash multiple : "values", can : "be_passed")

>> "key 'multiple' points to 'values'"

>> "key 'can' points to 'be_passed'"

Page 21: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Hashes in Rails

• Used heavily as parameters

Page 22: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Classes and Objects

• Ruby, like many object-oriented languages, uses classes to organize methods; these classes are then instantiated to create objects

Page 23: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Classes and Objects

• Most common uses will be in Models and Controllers

• attribute accessors (attr_accessor) corresponding to a user’s name and email address.

• This creates “getter” and “setter” methods that allow us to retrieve (get) and assign (set) @name and @email instance variables

Page 24: Code for Startup MVP (Ruby on Rails) Session 2

Ruby Class and Object Example

• Save the above code into a file called example_user.rb• Run the following in irb

Page 25: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Classes and Objects (Advanced Only)class SavingsAccount < Account # inheritance

# constructor used when SavingsAccount.new(...) calleddef initialize(starting_balance=0) # optional argument@balance = starting_balance

enddef balance # instance method

@balance # instance var: visible only to this objectenddef balance=(new_amount) # note method name: like setter

@balance = new_amountend

def deposit(amount)@balance += amount

end@@bank_name = "MyBank.com" # class (static) variable# A class methoddef self.bank_name # note difference in method def@@bank_name

end# or: def SavingsAccount.bank_name ; @@bank_name ; end

end

Page 26: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Objects and Method Calls (Advanced Only)

1.send(:+, 2)my_array.send(:[], 4)my_array.send(:[]=, 3,"foo")if (x.send(:==, 3)) ...self.send(:my_func, z)

•  Even lowly integers and nil are true objects:57.methods

57.heinz_varietiesnil.respond_to?(:to_s) "

•  Rewrite each of these as calls to send:"–  Example: my_str.length => my_str.send(:length)1 + 2

my_array[4]my_array[3] = "foo"if (x == 3) ....my_func(z)

•  When you are calling a method, you are actually sendinga method call to the receiver object, which responds

Page 27: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Method Calls (Advanced Only)

yy

= [1,2] = y + ["foo",:bar] # => [1,2,"foo",:bar]

yy

<< 5<< [6,7]

# => [1,2,"foo",:bar,5] # => [1,2,"foo",:bar,5,[6,7]]

•  Remember! These are nearly all instance methods of Array—not language operators!"

•  So 5+3, "a"+"b", and [a,b]+[b,c] are all differentmethods named '+'"–  Numeric#+, String#+, and Array#+, to be specific"

•  Every operation is a method call

•  a.b means: call method b on object a– a is the receiver to which you send the method call,

assuming a will respond to that method"

Page 28: Code for Startup MVP (Ruby on Rails) Session 2

Ruby – Practice

• Tryruby.org (code in ruby on your browser and work through free exercises)

• Read Section 4.1 to 4.5 of Ruby on Rails Tutorial by Michael Hartl

Page 29: Code for Startup MVP (Ruby on Rails) Session 2

Rails - Models

We will focus on Models in this section

But First, we must understand the underlying datastore that actually stores the data

Databases, Tables, SQL

Page 30: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Database backed Models

• Store and access massive amounts of data• Table

o Columns (name, type, modifier)o Rows

Table:Users

Page 31: Code for Startup MVP (Ruby on Rails) Session 2

SQL

• Structured Query Languageo A way to talk to databases

• Operations (CRUD)o Createo Read (Query)o Updateo Deleteo Schema creation and modification

SELECT *FROM BookWHERE price > 100.00ORDER BY title;

Page 32: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Object Relational Mapping

• Maps database backend to ruby objects• ActiveRecord (Rail’s Default ORM)

>> userVariable = User.where(name: "Bob")

>> userVariable.name=> Bob

Generates:SELECTWHERE

"users".* FROM "users"(name = 'bob')

Page 33: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Object Relational Mapping

>> userVariable = User.where(name: "Bob")

• Plural of Model name is table name (User -> users)

• Subclassing from ActiveRecord::Base “Connects” a model to the databaseo Provides CRUD operations on the modelo Database table column names are getters & setters for model

attributeso Model attributes automagically defined from the database table

columns

models/user.rbclass User < ActiveRecord::Base attr_accesor :name, :emailend

Page 34: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Creating Users

• We could start from scratch and create all aspects of the Users models from scratch, but that wouldn’t be in the philosophy of an MVP

• What additional functions might a user model need?o Registrationo Log in/Log out (sessions)o Reset/Lost Passwordo Email confirmationso Invitations to friends

Page 35: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Creating Users - Devise

• We will use the awesome Gem: Devise• Gems are packages/libraries for your rails project• Before coding, always see if a gem exists at The Rails Toolbox

Page 36: Code for Startup MVP (Ruby on Rails) Session 2

Rails - Devise

• Create a new rails appo rails new MiniTwitter

• Open Gemfile (from last class)

• Add the line:Gem ‘devise’, ‘2.1.0’

• Run Bundle install from the console

• Install Devise by typing in the console: rails generate devise:install

• Generate the user by typing in the console:rails generate devise User

• Run the migration by typing in the console:Bundle exec rake db:migrate

Page 37: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Devise

• You may seem some hints/warnings:

Page 38: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Devise

• Go to http://localhost:3000/users/sign_up to see Devise in action!

• Sign up a fake user account and now try to log in at http://localhost:3000/users/sign_in

• Rails never shows or stores passwords in plaintext

Page 39: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Devise

• What did we just do?o rails generate devise User

o Focus on Migration and User Model

Page 40: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrations

• Create data structure in your database• Set a database’s schema incrementally

o Consistent across multiple machines (no conflicts)o Easy to upgrade, rollback, track changes, etc

• Migration is automatically created every time you create a model

• Open db/migrate/[timestamp]_devise_create_users.rb

Page 41: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrations• Creates a table named

Users

• Adds Columns:o Emailo Encrypted_passwordo Etc, etco T.timestamps creates the

columns created_at and updated_at autmagically

o Can pass parameters to columns, default values, nullable, etc

• Adds Indices:o Ensures uniquenesso Faster searchingo Index on email

Page 42: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrations

• Active Record Maps ruby objects to database• User.email

Page 43: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrations

• Database looks like:

• Same as what was specified in the migration

Page 44: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrations

• Run a migration

• Rollback (undo) a migration

>> bundle exec rake db:migrate

>> bundle exec rake db:rollback

Page 45: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Migrationsrails generate migration AddNameToUsers name:string

• Creates a migration automagically on the users table because we followed naming conventionso AddXXXToYYY followed by column name and type

• More info: http://guides.rubyonrails.org/migrations.html

Page 46: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models

• Open app/models/user.rb

• Attr_accessible is important for preventing mass assignment vulnerability

• Notice we don’t have any attributes explicitly defined from the database (ORM maps attributes implicitly in Rails’ Activerecord)o Can remind ourselves of the database columns using ‘annotate’ gem

Page 47: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Attributes

• Open app/models/user.rb

• Can add methods to the user modeldef unchanged_duration

updated_at – Time.now

end- Duration in which the user was not modified

Page 48: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models- Validations

• Check your parameters before save• Provided by ActiveModel

class Person < ActiveRecord::Basevalidates :title, :presence => true

end

bob = Person.create(title: nil)>> bob.valid?=> false>> bob.save=> false

Page 49: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models- Validations

• Rails’ built in validation

• Can also write your own validations

:acceptance => Boolean.:confirmation => Boolean.:exclusion => { :in => Enumerable }.:inclusion => { :in => Enumerable }.:format => { :with => Regexp, :on => :create }.:length => { :maximum => Fixnum }.:numericality => Boolean.:presence => Boolean.:uniqueness => Boolean.

class User < ActiveRecord::Basevalidate :my_custom_validationprivate

def my_custom_validationself.errors.add(:coolness, "bad") unless self.cool ==

“supercool”end

end

Page 50: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models and Migrations Exercises

• Create a migration to add first_name and last_name to the User table

• Add validation for user’s email, first_name and last_name such that they must be present

• Make a method full_name on user object to retrieve user’s full name by concatenating first and last name

Page 51: Code for Startup MVP (Ruby on Rails) Session 2

Rails - Models

• Further ReadingRuby on Rails Tutorial – Michael HartlSection 6.1 – 6.2 (6.3 optional)

Page 52: Code for Startup MVP (Ruby on Rails) Session 2

Git Commit

git initgit add .git commit –m “Initial Commit of MiniTwitter”(optional) git remote add origin

[email protected]:<username>/first_app.git(optional)git push –u origin master

Page 53: Code for Startup MVP (Ruby on Rails) Session 2

Heroku – New MiniTwitter App

• Sign up for Heroku (it’s Free!) http://api.heroku.com/signup

• Install the Heroku Toolbelt https://toolbelt.heroku.com/

• Heroku login• Heroku create

o This will create a heroku app and tell you the url of your app

• Git push heroku mastero This’ll deploy your code to Heroku. Let it do its magic!

• Heroku run rake db:migrate• Heroku open

Page 54: Code for Startup MVP (Ruby on Rails) Session 2

Next Time…

• Exploring Rails deeper• More about Controllers and Views• Building toward our Twitter app posts, friends,

followers, feeds, etc• Stay Tuned….

• Thanks!

Page 55: Code for Startup MVP (Ruby on Rails) Session 2

Rails - Appendix

• If we have time…

Page 56: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models - Create

•  Must call save or save! on an AR modelinstance to actually save changes to DB"– '!' version is “dangerous”: throws exception ifoperation fails"

– create just combines new and save

•  Once created, object acquires a primary key(id column in every AR model table)"– if x.id is nil or x.new_record? is true, xhas never been saved"– These behaviors inherited from ActiveRecord::Base—not true of Ruby objects in general"

Page 57: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models - Read

•  Class method where selects objects based onattributes

Movie.where("rating='PG’)Movie.where('release_date < :cutoff and

rating = :rating',:rating => 'PG', :cutoff => 1.year.ago)

Movie.where("rating=#{rating}") # BAD IDEA!•  Can be chained together efficiently

kiddie = Movie.where("rating='G')

old_kids_films =kiddie.where "release_date < ?",

30.years.ago

Page 58: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models - Read

Movie.find(3) #exception if not foundMovie.find_by_id(3) # nil if not found

•  Dynamic attribute-based finders using

Movie.find_all_by_rating('PG')Movie.find_by_rating('PG')Movie.find_by_rating!('PG')

• Find Models by id

Page 59: Code for Startup MVP (Ruby on Rails) Session 2

Rails – Models - Delete

•  Note! destroy is an instance methodm = Movie.find_by_name('The Help')m.destroy

•  Thereʼs also delete, which doesnʼt triggerlifecycle callbacks weʼll discuss later (so,avoid it)"

•  Once an AR object is destroyed, you canaccess but not modify in-memory object

m.title = 'Help'