#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:
###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://www.data.gov/developers/apis
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: