Skip to content

Instantly share code, notes, and snippets.

@amysimmons
Last active December 26, 2017 06:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save amysimmons/c62409f2ef47cf3ac0ae to your computer and use it in GitHub Desktop.
Save amysimmons/c62409f2ef47cf3ac0ae to your computer and use it in GitHub Desktop.

#WDI Week 4 Notes

##Monday

###Warmup

Bob:

https://gist.github.com/epoch/ea1798f7269f454f2445

My solution (exclusing the extension):

class Bob

    def sure
        puts "sure"
    end
    # if you ask him a question

    def whatever
        puts "whatever"
    end
    # if you tell him something

    def chill
        puts "woah, chill out!"
    end
    # if you yell at him

    def fine
        puts "fine, be that way!"
    end
    # if you address him without actually saying anything

    def loser_speak
        puts "loser speak"
    end
    #Start any sentence with "Bro, " and he'll translate the rest of it into l33t sP34k for you.

    def chat(say)
        if say.start_with?"Bro, "
            loser_speak
        elsif say.include? '?'
            sure
        elsif say.empty? || say == " "
            fine
        elsif say == say.upcase
            chill
        else
            whatever
        end  
    end

end

bob = Bob.new

bob.chat("Bro, ")
bob.chat("sup?") 
bob.chat(" ") 
bob.chat("") 
bob.chat("SUP") 
bob.chat("You're a fool")

###CRUD demos

Homework over the weekend was to create a CRUD system.

I made a blog, with no styling:

https://github.com/amysimmons/wdi8_homework/tree/master/amy/blog

###Patterns

Design Patterns: Elements of Reusable Object-Oriented Software (book)

###Rails appetiser

Movies example:

rails new movie_night

rails server

localhost:3000

rails generate scaffold movie title:string in_theatres:boolean released:date rating:string description:text

rake db:migrate (updating the database to include the movies table)

rails server

localhost:3000/movies

Intro example:

Rails has three different environments:

  • Development

  • Test

  • Production

We added the following gems to Gemfile...

group :development do
    gem 'pry-rails'
    gem 'pry-stack_explorer'
    gem 'annotate'
    gem 'quiet_assets'
    gem 'better_errors'
    gem 'binding_of_caller'
    gem 'meta_request'
end

... then ran bundle in the terminal.

in routes.rb

Rails.application.routes.draw do

  get '/home' => 'pages#home'
  # if someone makes a get request to /home
  # go and look in our pages controller and go and find the method called home

end

in pages_controller.rb

class PagesController < ApplicationController

    def home

    end
    #we need a home method here because we have a page called /home

end

In views, we created a new folder called pages, which sits alongside layout. We then created a file in the pages folder called home.html.erb

Here's how Rails will work when we run the server:

  • When I bring up the rails server it will look into my routes.rb file to see what urls are available

  • If someone visits /home, rails will go to the pages controller to find the method

  • If Rails sees that there is no code in the method, it will then go and look for a view that matches the name of this method, so it will find the view called home.html.erb

Routes:

  • Runnign rake routes in the terminal will tell you how many urls are involved in the project

  • Or you can go to localhost:3000/rails/info/routes

  • We identify the root/home page by including in the routes.rb file

root :to => 'pages#home'

Debugging:

Rather than using binding.pry, use a raise like this:

class AutoController < ApplicationController

    def color
        raise "Something bad happen"
        raise params.inspect
    end

    def engine
    end

end

###Lab: Movie Stock

https://gist.github.com/wofockham/ae2479856769f8dbc804

##Tuesday

###Warmup

Decoding messages:

https://gist.github.com/epoch/21c0133143f03226cee0

My crappy solution, but it works!

message  = "FRZDUGV GLH PDQB WLPHV EHIRUH WKHLU GHDWKV, WKH YDOLDQW QHYHU WDVWH RI GHDWK EXW RQFH."

message_arr = message.split(//)

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

alphabet_arr = alphabet.split(//)

alphabet_shift = "DEFGHIJKLMNOPQRSTUVWXYZABC"

alphabet_shift_arr = alphabet_shift.split(//)

message_arr.each do |letter|

    if letter != " "
        index = alphabet_shift_arr.index(letter)
        correct_letter = alphabet_arr[index]
        print correct_letter
    else
        print " "
    end

end

###Single Model CRUD - Planets

Create path '/'

Define our database

Create planets table

  • id integer autoincrement

  • name text

  • mass float

  • moons integer

  • distance integer

####The long SQL process

Step 1: Setting up the database

rails new solar_systems_app

Create planets.sql in db file

CREATE TABLE planets (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    image TEXT,
    orbit FLOAT,
    diameter FLOAT,
    distance FLOAT,
    mass FLOAT,
    moons INTEGER
);

Table name must be plural, the model itself must be singular

create the database by running rake db:create

it will create a file called development sqlite 3

we can then cd into the db folder

run sqlite3 development.sqlite3 < planets.sql in the terminal

this pushes the planets table into the database

to test that it worked run sqlite3 development.sqlite3 .schema and it should return the table structure

Step 2: Creating a model

Now we need to create a model to make this work

The model goes in the app folder, in a folder called models

create new file planet.rb

into that file put

class Planet < ActiveRecord::Base
end

gem install annotate

run annotate

this inserts a big comment into my planet.rb file which shows the table name and characteristics

An alternative to pry:

in order to deal with pry we can type rails console in the terminal

then we can start running commands like Planet.all

In order to be in pry rather than console,

put these into my gemfile

group :development do
    gem 'pry-rails'
    gem 'pry-stack_explorer'
    gem 'annotate'
    gem 'quiet_assets'
    gem 'better_errors'
    gem 'binding_of_caller'
    gem 'meta_request'
end

then run bundle

then run rails console again

you could do earth = Planet.new

and then set all the properties

or you can do this

venus = Planet.create :name => 'Venus', :mass => 3, :diameter => 11, :distance => 1, :moons => 2

Planet.destroy_all will destory all planets

Planet.count should now show zero

Step 3: Seed data

The seeds.rb file is for seed data

Planet.create(:name => 'Earth', :orbit => 1, :moons => 1)
Planet.create(:name => 'Mars', :orbit => 1.5, :moons => 2)
Planet.create(:name => 'Venus', :orbit => 0.7, :moons => 0)
Planet.create(:name => 'Jupiter', :orbit => 3.7, :moons => 7)
Planet.create(:name => 'Pluto', :orbit => 5, :moons => 3)

Enter some seed data and then run rake db:seed in terminal

This connects the seed data with the database

to test that it worked, in the console, run Planet.count / Planet.all and the seed data should be there

if you make a mistake while playing around with your data, you can restore the original seeded data by reseeding them

first you need to add Planet.destroy_all to the top of the seeds.rb file

then when you re-run rake db:seed it will first destroy all existing planets, then reseed the original ones

rake db:drop (deletes the database)

delete sql file

so all that's in db folder is the seeds file


####Rails generating the migration for us, without us having to write SQL

in solar_system_app run

rails generate migration create_planets

the rb file should appear in the migrate folder

it tells rails to create a table

so this is the equivalent of our sql stuff, but its a lot more rubyish

class CreatePlanets < ActiveRecord::Migration
  def change
    create_table :planets do |t|
    end
  end
end

so we want to insert into the do block our table details

class CreatePlanets < ActiveRecord::Migration
  def change
    create_table :planets do |t|
        t.string :name
        t.text :image
        t.float :orbit
        t.float :mass
        t.float :diameter
        t.float :distance
        t.integer :moons
        t.timestamps
    end
  end
end

this table works across all databases now

rake db:create (creates the db)

rake db:migrate (finds any unapplied migrations and performs them)

at this point you can run annotate, then go back to the planet.rb file to check thar the table is there

at this stage we have set up the M part of our MVC model, but we haven't set up any routes

Setting up the routes:

in the routes.rb file

get '/planets' => 'planets#index'

in terminal run rails generate controller planets index

this means rails will create the file for me and create the views folder and put an index.html.erb file in there ready for me to customize

rake db:seed

rails console

Planet.all

Recap of the above steps:

rails new something -T

cd something

rails generate migration create_whatever

subl . #fill in the migration

rake db:create

rake db:migrate

touch app/models/whatever.rb

annotate

rake db:seed


http://localhost:3000/info/routes

will show you the urls and the methods to get to those urls


we changed the new planet form so that all the name values were formatted like this - planet[moons]

this is so we can view the planets better in the controller

>> params
=> {"name"=>"", "planet"=>{"image"=>"", "orbit"=>"", "mass"=>"", "diameter"=>"", "distance"=>"", "moons"=>""}, "controller"=>"planets", "action"=>"create"}
>> params[planet]
!! #<NameError: undefined local variable or method `planet' for #<PlanetsController:0x007fc52bedecc8>>
>> params["planet"]
=> {"image"=>"", "orbit"=>"", "mass"=>"", "diameter"=>"", "distance"=>"", "moons"=>""}
>> params["planet"]["name"]
=> nil
>> params["planet"].keys
=> ["image", "orbit", "mass", "diameter", "distance", "moons"]
>>

###Lab: Single Model CRUD - Oceans or Mountains

https://github.com/amysimmons/wdi8_homework/tree/master/amy/oceans_app

###Reading: Active Record Helpers

http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-image_tag

###Reading: Active Record Migrations

http://guides.rubyonrails.org/active_record_migrations.html

You can think of each migration as being a new 'version' of the database. A schema starts off with nothing in it, and each migration modifies it to add or remove tables, columns, or entries. Active Record knows how to update your schema along this timeline, bringing it from whatever point it is in the history to the latest version.

##Wednesday

http://postgresapp.com/ - a fancier version of sqlite3

###Art Gallery code along

Thinking through the tables:

We are going to have two tables - Artists and Works

One artist can have many works.

An artist will have:

  • name (string)
  • nationality (string)
  • dob (date)
  • period (string)
  • image (text)

An artwork will have:

  • title (string)
  • year (string)
  • medium (string)
  • style (string)
  • image (text)
  • artist_id (int) *this is the association

the above layout assumes only one artist has worked on an artwork.

if you needed to have multiple artistis on one work, then you could have a third table, a join table, that just stores the ids.

it would be called artist works, with two columns, an artistid column, and a work id column.

Setting up the rails app:

rails new moma -d postgresql -T

the above won't include the sqlite gem in gemfile and will use the pg gem instead. it's telling rails which database system to use.

-t tells rails not to include any development files

add the following gems to gemfile and run bundle

group :development do
    gem 'pry-rails'
    gem 'pry-stack_explorer'
    gem 'annotate'
    gem 'quiet_assets'
    gem 'better_errors'
    gem 'binding_of_caller'
    gem 'meta_request'
end

config database.yml file, need to make some changes to the development group

we need to specify the host and username

host: localhost
  username: amysimmons

these go under the line that says database: moma_development

then we deleted everything below those lines

run rake db:create to create the database

Creating the first table:

rails generate migration create_artists

this tells it to make an artists table in the database folder, which needs to be plural, because the table will store many artists

go and add your table elements in your migrate folder

class CreateArtists < ActiveRecord::Migration
  def change
    create_table :artists do |t|
        t.string  :name
        t.string :nationality
        t.date :dob
        t.string :period
        t.text :image
        t.timestamps
    end
  end
end

then run rake db:migrate

check your schema.rb file and the table should be there

next step is to create my model

touch app/models/artist.rb

in the artist.rb file add

class Artist < ActiveRecord::Base
end

now we need to make sure the Artist class needs to be able to find the table that is associated with it

the easiest way to test it is to run annotate

then go check the artist.rb file in models folder to check that the annotation comments are there

all annotate does is add the comment at the top of that file

Creating the second table:

rails generate migration create_works

in the migrate folder add the table elements

class CreateWorks < ActiveRecord::Migration
  def change
    create_table :works do |t|
        t.string :title
        t.string :year
        t.string :medium
        t.string :style
        t.text :image
        t.timestamps
    end
  end
end

repeat above steps to set up the model and make sure the class is connected with the new table.

Adding seed data:

Added the following to the seeds.rb file

Artist.destroy_all
Work.destroy_all

Artist.create(:name => 'Joan Miro', :nationality => 'Spanish', :dob => '1893/04/20', :period => '20th century', :image => 'http://upload.wikimedia.org/wikipedia/commons/5/5c/Portrait_of_Joan_Miro%2C_Barcelona_1935_June_13.jpg')
Work.create(:title => 'The Flight of the Dragonfly in Front of the Sun', :year => '1968', :medium => 'oil on canvas', :style => 'Abstract Art', :image => 'http://uploads0.wikipaintings.org/images/joan-miro/the-flight-of-the-dragonfly-in-front-of-the-sun.jpg')

rake db:seed to run the seed file

rails console

Artist.all should get me all artists

Work.all should get me all works

Start building the routes:

in the routes file you can say i want you to create resources for artisists, it writes all those routes for you

Rails.application.routes.draw do
  resources :artists
end

resources :artists resources :works

this creates the same seven set of routes that we have been working with previously. AMAZE!!

moma $ rake routes
     Prefix Verb   URI Pattern                 Controller#Action
    artists GET    /artists(.:format)          artists#index
            POST   /artists(.:format)          artists#create
 new_artist GET    /artists/new(.:format)      artists#new
edit_artist GET    /artists/:id/edit(.:format) artists#edit
     artist GET    /artists/:id(.:format)      artists#show
            PATCH  /artists/:id(.:format)      artists#update
            PUT    /artists/:id(.:format)      artists#update
            DELETE /artists/:id(.:format)      artists#destroy

Create controller with all actions in one go:

rails generate controller artists index create new edit show update destroy

it will also create all the views for me, we don't need views for all of these, but we can go and delete the views that we don't want

delete all gets from routes.rb because the resources :artists line is doing this

check artists controller file and all methods should be there

http://localhost:3000/info/routes

Adding to the pages:

Creating a form for a new artist/work:

rather than writing a form from scratch, rails can generate a secure form for you.

go to artist new.html.erb and wrtie a form like this:

<%= form_for @artist do |f| %>

    <%= f.label :name %>
    <%= f.text_field :name %>

    <%= f.label :nationality %>
    <%= f.text_field :nationality %>

    <%= f.label :dob, "Date of birth"%>
    <%= f.text_field :dob %>

    <%= f.label :period %>
    <%= f.text_field :period %>

    <%= f.label :image %>
    <%= f.url_field :image %>

    <%= f.submit %>

<% end %>

we still need to add a private method at the bottom of the artist controller called artist_params

  private
  def artist_params
    params.require(:artist).permit(:name, :nationality, :dob, :period, :image,)
  end

this is so that we can write our create method

  def create
    artist = Artist.create artist_params
    redirect_to artist
  end

How to create the edit form, instead of copying and pasting from the new form:

we want to create a partial

so in the artists folder create a file called this

_form.html.erb

cut and paste the form from the new page into the _form.html.erb file

<%= form_for @artist do |f| %>

    <%= f.label :name %>
    <%= f.text_field :name, :autofocus => true %>

    <%= f.label :nationality %>
    <%= f.text_field :nationality %>

    <%= f.label :dob, "Date of birth"%>
    <%= f.text_field :dob %>

    <%= f.label :period %>
    <%= f.text_field :period %>

    <%= f.label :image %>
    <%= f.url_field :image %>

    <%= f.submit %>

<% end %>

then tell the new and edit html views to go and get the form from somehwere else

<%=render :partial => 'form'%>

include the above code in your new and edit html.erb files

repeat the above process for the works form

(see below for associations)


What if I make a mistake in my table?

rake db:rollback undoes the most recent migration

fix the code

then run rake db:migrate again

then annotate again and check that it's been fixed


Date formatting:

http://www.strfti.me/


###Associations

to make an association, to inc

rails generate migration add_artist_id_to_works

then go into the migration and add this line

 def change
    add_column :works, :artist_id, :intger
  end

adds a column to the works table which is called artist_id and is an integer

then run rake db:migrate

check schema.rb and the column should be added

run annotate

and check the work model and the comment should have changed

in artist.rb

class Artist < ActiveRecord::Base
    has_many :works
end

in work.rb

class Work < ActiveRecord::Base
    belongs_to :artist
end

this is saying go and look for an artist id column in this table

There are two ways that you can add an artist id to a work:

  • miro.works << flight (miro's works is an array so we just attach the flight to that array. if an artist has many works then you can append it)

  • flight.artist = miro (the artist who did this flight is miro)

it's good to test this in the console during our projects:

Artist.first.works

Work.first.artist

should show the relationship working both ways

Associations in the seed data:

this is how you write your seed data with associations:

Artist.destroy_all
Work.destroy_all

a1 = Artist.create(:name => 'Joan Miro', :nationality => 'Spanish', :dob => '1893/04/20', :period => '20th century', :image => 'http://upload.wikimedia.org/wikipedia/commons/5/5c/Portrait_of_Joan_Miro%2C_Barcelona_1935_June_13.jpg')
w1 = Work.create(:title => 'The Flight of the Dragonfly in Front of the Sun', :year => '1968', :medium => 'oil on canvas', :style => 'Abstract Art', :image => 'http://uploads0.wikipaintings.org/images/joan-miro/the-flight-of-the-dragonfly-in-front-of-the-sun.jpg')

a1.works << w1

The next step is to update the edit form with a select menu that maps the artist name and artist id

<%=f.label :artist_id %>
<%=f.select :artist_id, Artist.all.map{|artist|[artist.name, artist.id]} %>

And don't forget to whitelist the artist id!

###Lab: Books and Authors

https://github.com/amysimmons/wdi8_homework/tree/master/amy/bookstore

###Homework

Exercise:

https://gist.github.com/epoch/7e567f138f97c71904a5

APIs:

https://data.gov.au/dataset

https://www.data.gov/developers/apis

https://angel.co/api

http://www.publicapis.com/

http://en.wikipedia.org/wiki/List_of_open_APIs

##Thursday

###Tunr

Setting up the rails app and crearting the database:

rails new tunr -T -d postgresql

added development gems to gemfile

also added gem 'haml'

bundle

rake db:create

Creating the tables:

Follow the below steps for songs, genres, albums, artists, users, mixtapes, etc

tunr $ rails generate migration create_songs

add the table elements to the migration , eg:

t.string :name
t.text :image
t.timestamps

rake db:migrate

touch app/models/song.rb

class Song < ActiveRecord::Base
end

annotate

Settig up the associations:

add the belongs_to and has_many in the classes

Testing in the console that the associations are set up:

tunr $ rails console
Loading development environment (Rails 4.2.0)
[1] pry(main)> thriller = Song.new
=> #<Song:0x007fb600efff70
 id: nil,
 name: nil,
 filename: nil,
 album_id: nil,
 artist_id: nil,
 created_at: nil,
 updated_at: nil>
[2] pry(main)> thriller.artist_id
=> nil
[3] pry(main)> thriller.artist
=> nil
[4] pry(main)> thriller.album
=> nil
[5] pry(main)> barry = User.new
=> #<User:0x007fb600705388
 id: nil,
 name: nil,
 image: nil,
 created_at: nil,
 updated_at: nil>
[6] pry(main)> barry.mixtapes
=> []
[7] pry(main)> m = Mixtape.new
=> #<Mixtape:0x007fb6028b1388
 id: nil,
 name: nil,
 user_id: nil,
 created_at: nil,
 updated_at: nil>
[8] pry(main)> m.user
=> nil
[9] pry(main)> 

Create the many to many join tables:

rails generate migration create_mixtapes_songs

*the table name has to be in alphabetical order

in the migration fill out the properties

class CreateMixtapesSongs < ActiveRecord::Migration
  def change
    create_table :mixtapes_songs, :id => false do |t|
        t.integer :mixtape_id
        t.integer :song_id
    end
  end
end

id is set to false becase we don't need this third column in the table.

you don't need a model for mixtape_song

this table is just a join table to join two other models together

we just need to explain the relationship in the mixtape and the song models

class Mixtape < ActiveRecord::Base
    belongs_to :user
    has_and_belongs_to_many :songs
end 

class Song < ActiveRecord::Base
    belongs_to :artist
    belongs_to :album
    has_and_belongs_to_many :mixtapes
end

test the association in the console:

[1] pry(main)> m = Mixtape.new
=> #<Mixtape:0x007fb600ba53c0
 id: nil,
 name: nil,
 user_id: nil,
 created_at: nil,
 updated_at: nil>
[2] pry(main)> m.songs
=> []
[3] pry(main)> thriller = Song.new
=> #<Song:0x007fb6004d7688
 id: nil,
 name: nil,
 filename: nil,
 album_id: nil,
 artist_id: nil,
 created_at: nil,
 updated_at: nil>
[4] pry(main)> thriller.mixtapes
=> []

Repeat the above steps for genres_songs table

The different types of associations:

has_many

belongs_to

has_and_belongs_to_many - when you have a join table

has_many_through - lets you go from one to two steps away

Addding seed data:

Genre.destroy_all
Song.destroy_all
Album.destroy_all
Artist.destroy_all
User.destroy_all
Mixtape.destroy_all

g1 = Genre.create(:name => 'Rock')
g2 = Genre.create(:name => 'Alternative')
g3 = Genre.create(:name => 'Pop')

s1 = Song.create(:name => 'Best Of You')
s2 = Song.create(:name => 'Torrent')
s3 = Song.create(:name => 'I Think I Wanna Marry You')

a1 = Album.create(:name => 'Greatest Hits')
a2 = Album.create(:name => 'In The Silence')
a3 = Album.create(:name => 'Doo-Wops & Hooligans')

r1 = Artist.create(:name => 'Foo Fighters')
r2 = Artist.create(:name => 'Asgeir')
r3 = Artist.create(:name => 'Bruno Mars')

u1  = User.create(:name => 'Amy')
u2  = User.create(:name => 'Julia')
u3  = User.create(:name => 'Liam')

m1 = Mixtape.create(:name => 'Friday Night')
m2 = Mixtape.create(:name => 'Bus Trip Home')
m3 = Mixtape.create(:name => 'Sunday Afternoon')


#associate songs and artists 
s1.artist = r1
s1.save
s2.artist = r2
s2.save
s3.artist = r3
s3.save

#associate songs and genres
#appending here because genres is an array
s1.genres << g1
s2.genres << g2
s3.genres << g3

#associate songs and albums
s1.album = a1
s1.save
s2.album = a2
s2.save
s3.album = a3
s3.save

#associate songs and mixtapes
m1.songs = [s1, s2, s3]
m1.save
m2.songs = [s1, s2]
m2.save
m3.songs = [s2]
m3.save

#associate mixtapes and users
m1.user = u3
m1.save
m2.user = u1
m2.save
m3.user = u2
m3.save

Setting up the routes:

Rails.application.routes.draw do
  get 'users/new'

  root :to => 'pages#home'
  get '/home' => 'pages#home'

  resources :users, :only => [:new]

end

rails generate controller Users new

make the new user form

Password security:

Never store your user's password in plain text

You know if someone is storing the data in plain text if you click the forgot my password link, and they email you back your password

Use something like md5 which encrypts the passwords and stores the encrypted password in the database

Creating new users:

Create our users form, whcih allow for a password and password confirmation

This is how we let rails know that we are storing an encrypted version of the password, running password_digest:

generate migration add_password_digest_to_users password_digest:string

rake db:migrate

uncomment the gem 'bcrypt', '~> 3.1.7' in gemfile and rebundle

run annotate

password_digest :string solumn should be added to the user.rb model

add has_secure_passowrd to the user model

class User < ActiveRecord::Base
    has_secure_password
    has_many :mixtapes
end

the create def should look like this

   def create
        @user = User.new user_params
        # this will creata  new user with this parameters but it wont save them in the database
        # first i want to see if their passwords match
        if @user.save  
            redirect_to root_path
        else
            render :new
        end
    end

and the form should look like this

%h1 Sign up

- if @user.errors.any?
    %ol
        - @user.errors.full_messages.each do |msg|
            %li= msg


= form_for @user do |f|
    = f.label :name
    = f.text_field :name, :autofocus => true

    = f.label :password
    = f.password_field :password

    = f.label :password_confirmation
    = f.password_field :password_confirmation

    = f.submit "Sign up"

i want to say that a user cant be created if they dont have a name

to do this, add this line - validates :name, :presence => true - to the user model

this says one of the things that makes a user valid is the presence of a name, and if they dont give a name, report it as an error and dont include them in the database

add required to the name, password and password confirmation fields - this is client side validation, but we also need the back end validation, which is what we have done above, because clients can get around the client side validation

in the user.rb file

validates :name, :presence => true, :uniqueness => true

add uniqueness is true to the email field - or the name field.

we would probably use email field in our projects, or username

lastly update the seed user data with password and password confirmation

###Homework

joel.turnbull [3:36 PM]

also this afternoon/tonight: review all of the railsguides we've looked at so far. the better you know the things rails can do for you the less work you'll have to do. validations are an excellent example

guidelines for tomorrow's proposals:

  • the problem you're solving
  • the models you think you'll need
  • any gems and APIs you intend to use
  • sketches of any important pages/flows
  • any aspects you think will be particularly tricky

##Friday

###Authentication:

Passwords:

We want somehting like a CRUD system for users, but we don't want to store their passwords in plain text.

So we comment in the bcrypt gem.

This gives you the magic box which turns the password into an encrypted version of the password.

So we then include password_digest :string

IN your seed data, store a password and passworc confirmation

You add has_secure_password to the USer class.

Do the vailadation with an email, presence is true and uniqueness is true.

That sort of validation information belongs in the model.

Has secure password also gives you some sort of vaildation, that the passwords should match.

In new.html.erb go through all the erros and list an error message if there is one.

From the controllers view, then all we need to say is if we are able to save the user, take them to the root path.

Logins:

Once theyve created the account they get taken to the sign in page

the users controlle is to do with creating new users and deleting user accounts

but now we need a new controller called the session controller, which creates a session, which happens to be related to a user, but isn't the same thing

In the routes.rb add the following:

  get '/login' => 'session#new'
  post '/login' => 'session#create'
  delete '/login' => 'session#destroy'

rails generate controller Session new create destroy

in the new.html.erb file (convert from haml)

%h1 Log in

= form_tag login_path do 
    = label_tag :username
    = text_field_tag :username, nil autofocus => true
    = label_tag :password
    = password_field_tag :password
    = submit_tag 'Log in'

In the session controller

  def create
    user = User.find_by :name => params[:username]
    if user.present? && user.authenticate params[:password]
        session[:user_id] = user.id
        redirect_to(root_path)
    else
        redirect_to(login_path)
    end
    # user fills in username and password, do we havea user with this name?
    # if we have a user, if the user has something in it, 
    # and the authenticate method returns true
    # then we can log them in
  end

We don't need to include a model for the session

Fixing the navigation menu:

Added an application helper for the nav menu, so i can call the nav menu from any view

Recap:

session controller gives you the ability to create and destroy sessions

we use the authenticate method to check that they have the right passowrd

in the applicatiojn controller to use this when they log in we set up a session id

to tie it all togetehr we need the before action in the application controller

How to log in when sign up:

what is the hting that happens when someone logs in?

you want to take that thing and add it to the sign up process

whats the thing that happens when someone logs in? that's all you need to know.

###Authorisation:

rails generate migration add_is_admin_to_users is_admin:boolean

add in the default false line

add_column :users, :is_admin, :boolean, :default => false

rake db:migrate

annotate

Bootstrap:

https://github.com/twbs/bootstrap-sass

include gem 'bootstrap-sass'

this incudes the bootstrap css file and fonts and icons etc into my assets folder

then run bundle

then add

@import "bootstrap-sprockets";
@import "bootstrap";

to the application.css file

this link will make sure the website is set up for mobile devices

http://getbootstrap.com/getting-started/ look at the examples here

form example:

added div with a class of form-group and then added a class of form-control


= form_for @user do |f|
    %div.form-group
        = f.label :name
        = f.text_field :name, :autofocus => true, :required => true, :class => 'form-control'

        = f.label :password
        = f.password_field :password, :required => true, :class => 'form-control'

        = f.label :password_confirmation
        = f.password_field :password_confirmation, :required => true, :class => 'form-control'

        = f.submit "Sign up"

###Proposals:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment