code for startup mvp (ruby on rails) session 2

59
Learning to Code for Startup MVP Presented by Henry Shi

Upload: henry-s

Post on 01-Sep-2014

1.337 views

Category:

Documents


4 download

DESCRIPTION

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

TRANSCRIPT

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'