#WDI Week 6 Notes
##Monday
###You only need one method for testing
####Bob
class Bob
def chat(input)
if input.strip.end_with? "?"
"Sure"
elsif input == input.upcase
"Whoa chill out"
elsif input.empty?
"fine whatever"
end
end
end
require 'minitest/autorun'
require 'minitest/reporters'
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
class BobTest < Minitest::Test
def test_ask_question
bob = Bob.new
assert_equal "Sure", bob.chat('question?')
end
def test_ask_question_with_trailing_spaces
bob = Bob.new
assert_equal "Sure", bob.chat('question? ')
end
def test_shouting_at_bob
bob = Bob.new
assert_equal "Whoa chill out", bob.chat("HURRY")
end
end
tdd $ ruby bob.rb
Started with run options --seed 18791
BobTest
test_shouting_at_bob PASS (0.00s)
test_ask_question_with_trailing_spaces PASS (0.00s)
test_ask_question PASS (0.00s)
Finished in 0.00157s
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
####Phone numbers
In test.rb file:
require 'minitest/autorun'
require "minitest/reporters" # optional
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new() # optional
require_relative './phone'
class PhoneTest < MiniTest::Test
def test_cleans_number
number = Phone.new("(123) 456-7890").number
assert_equal "1234567890", number
end
def test_cleans_number_with_dots
# skip
number = Phone.new("123.456.7890").number
assert_equal "1234567890", number
end
def test_valid_when_11_digits_and_first_is_1
# skip
number = Phone.new("11234567890").number
assert_equal "1234567890", number
end
def test_invalid_when_11_digits
# skip
number = Phone.new("21234567890").number
assert_equal "0000000000", number
end
def test_invalid_when_9_digits
# skip
number = Phone.new("123456789").number
assert_equal "0000000000", number
end
def test_area_code
# skip
number = Phone.new("1234567890")
assert_equal "123", number.area_code
end
def test_pretty_print
# skip
number = Phone.new("1234567890")
assert_equal "(123) 456-7890", number.to_s
end
end
In phone.rb file:
class Phone
def initialize(number)
@number = number
end
def number
if @number.length < 10
return "0000000000"
end
if @number.length == 11 && @number[0] != "1"
return "0000000000"
end
if @number.length == 11
return @number.sub(/[1]/, '')
end
@number.scan(/\d/).join
end
def area_code
@number[0..2]
end
def to_s
return "(#{area_code}) #{@number[3..5]}-#{@number[6..9]}"
end
end
# Alternate - Mario's code:
# class Phone
# def initialize(number)
# @number = number
# end
# def number
# @number = @number.scan(/\d/).join
# # gsub first char substitution would have taken less lines
# if @number.length == 11 && @number[0] == '1'
# @number.slice!(0)
# return @number
# end
# unless @number.length == 10
# return "0000000000"
# end
# @number
# end
# def area_code
# @number[0..2]
# end
# def to_s
# s = "(#{area_code}) "
# s += @number[3..5]
# s += '-'
# s += @number[6..9]
# s
# end
# end
###Project 1 code review
-
Most of your logic should be inside the model, not the controller
-
If you use an ActiveRecord metod, eg Tweet.all.order, this is
-
Authorisation (making sure the user can't get to another route just by typing it in, even though they can't see the link):
class Post
def can_edit?(user)
user.is_admin? || is_owner?(user)
end
def is_owner?(user)
self.user == user
end
end
# views
<% if @post.can_edit?(@current_user) %>
<%= link_to 'edit' %>
<% end %>
# controller
def edit
@post = Post.find(params[:id])
if @post.can_edit?(@current_user)
else
redirect_to no_access
end
end
- Check if success before create:
def create
artist = Artist.new artist_params
if artist.save
redirect_to artist
else
render :new
end
end
###Why JavaScript?
When the broswer makes a certain reuqest, the controller works out how to respond to that
It gets back a bunch of HTML
But what happens on the page is static
JavaScript allows further processing to happen in the browser itself
JS can also make requests to the server, and put them into the page without needing to refresh (Ajax)
Nodejs means you can replace ruby on rails on the server, and have javascript on both ends, so you can build the entire stack out of javascript
http://repl.it/languages/JavaScript
Variables:
Javascript needs a semi colon after everything
You always need brackets ()
Always make sure you use a var
If you don't the default is that the variable is global
var makes it a local variable
eg
var x;
x = 5;
console.log(x);
var x = 5;
console.log(x);
Primitive data types:
Strings
Variable names:
must begin with letters, $ sign or underscore
js prefers camel case
var x = 2 + 2; var y = x * 3;
https://gist.github.com/wofockham/c857b8d2c869010c8887
// Store the following into variables: number of children, partner's name, geographic location, job title. Output your fortune to the screen like so: "You will be a X in Y, and married to Z with N kids."
var NumberOfChildren = 5;
var PartnersName = "Alex";
var GeographicLocation = "Paris";
var JobTitle = "Amazing dev";
console.log("You will be a " + JobTitle + " in " + GeographicLocation + ", and married to " + PartnersName + " with " + NumberOfChildren + " kids.");
// Ever wonder how much a "lifetime supply" of your favorite snack is? Wonder no more!
// Store your current age into a variable.
// Store a maximum age into a variable.
// Store an estimated amount per day (as a number).
// Calculate how many you would eat total for the rest of your life.
// Output the result to the screen like so: "You will need NN to last you until the ripe old age of X".
var age = 27;
var maxAge = 50;
var amountPerDay = 2;
var calc = (maxAge - age) * 365 * amountPerDay;
console.log("You will need " + calc + " mars bars to last you until the ripe old age of " + maxAge + ".");
// Calculate properties of a circle, using the definitions at http://math2.org/math/geometry/circles.htm
// Store a radius into a variable.
// Calculate the circumference based on the radius, and output "The circumference is NN".
// Calculate the area based on the radius, and output "The area is NN".
var r = 25;
var c = 2 * 3.14 * r;
var a = Math.PI * r * r;
console.log("The circumference is " + c + ".");
console.log("The area is " + a + ".")
// It's hot out! Let's make a converter based on the steps at http://www.mathsisfun.com/temperature-conversion.html
// Store a celsius temperature into a variable.
// Convert it to fahrenheit and output "NN°C is NN°F".
// Now store a fahrenheit temperature into a variable.
// Convert it to celsius and output "NN°F is NN°C."
var celcius = 47;
var farenheight = 1.8 * celcius + 32;
console.log(farenheight);
farenheight - 116.6;
celcius = (farenheight - 32)/1.8;
console.log(celcius);
// Adding numbers function
var addNumbers = function(num1, num2) {
var result = num1 + num2;
console.log(result);
}
addNumbers(7, 21);
addNumbers(2, 3);
JS Scope:
-
if the variable is outside of a function you can access it inside the function
-
but if the variable is set inside the function, it is not accessible on the outside
The if statement:
if (condition) {
//statements to execute
}
= (asignment)
== (equality/comparison)
using double equals converts the things to the same type
eg is 3 == '3' would return true
=== (strict comparison - will recognise the diffeence in types)
so is 2 === '2' would return false
Homework:
https://gist.github.com/wofockham/4c897f89695009b782eb
https://gist.github.com/wofockham/dbd3967ecd01a397abe9
https://gist.github.com/wofockham/7658dd6baf784e710a12
https://developer.mozilla.org/en-US/docs/Web/JavaScript
http://discover-devtools.codeschool.com/
##Tuesday
###Warm up
###Recap
var name = 'Groucho';
var greet = function(name){
console.log('Greetings to you ' + name);
}
greet();
greet('harpo');
var doubler = function(i){
return i * 2;
}
var twiceSeven = doubler(7);
console.log(twiceSeven);
if(twiceSeven === 14){
console.log('doubler() seems to be working');
}else {
console.log('doubler() not working');
}
// initial
var i = 5;
// conditional
while(i > 5){
console.log(i);
// update
i = i - 1;
}
for (var i = Things.length - 1; i >= 0; i--) {
Things[i]
};
for ( iniit; conditional; update ){
}
for ( var i = 5; i > 0; i-- ){
console.log(i);
}
###Objects (aka hashes)
This is what a JS object looks like:
var box = {};
box.material = "cardboard";
var box = {"material" : "cardboard"}
the above two lines are both setting the key value pair
var cb = box.material;
var cb would contain the string of cardboard
box.size would retrun undefined
box = {}
box.material = 'cardboard';
var key = 'material'
box[key]; returns material
but if i say box['key'] as a string it won't work because it will go and look for a key called key whcih doesnt exist
if you ever have your key inside a varible you need to use square brackets
if i say box.key it will also return undefined because it is saying look up a key called key
var vices = {}
vices.groucho = 'cigars'
i can look up groucho by doing either of these two things:
vices['groucho']
vices['gro' + 'ucho]
box["size"] = {
"height": 2;
"width": 80;
};
box.size.height gives me a 2
box.size.width gives me 80
box["size"]["width"]
box.size['width']
box.area = function() {
}
Object exercises:
// https://gist.github.com/wofockham/222f4fc589441028eacd
// Never forget another recipe!
// Create an object to hold information on your favorite recipe.
// It should have properties for title (a string), servings (a number),
// and ingredients (an array of strings).
// On separate lines (one console.log statement for each), log the recipe
// information so it looks like:
// Mole
// Serves: 2
// Ingredients:
// cinnamon
// cumin
// cocoa
var recipe = {
Title : 'Brownies',
Serves : 10,
Ingredients : ['self raising flour', 'cocoa', 'eggs', 'butter', 'choc chunks', 'sugar']
};
console.log(recipe.Title);
console.log("Serves: " + recipe.Serves);
console.log("Ingredients: ");
for ( var i = 0; i < recipe.Ingredients.length; i++ ){
console.log(recipe.Ingredients[i]);
}
// Keep track of which books you read and which books you want to read!
// Create an array of objects, where each object describes a book and has
// properties for the title (a string), author (a string), and alreadyRead
// (a boolean indicating if you read it yet).
// Iterate through the array of books. For each book, log the book title
// and book author like so: "The Hobbit by J.R.R. Tolkien". Now use an
// if/else statement to change the output depending on whether you read it
// yet or not. If you read it, log a string like 'You already read "The Hobbit"
// by J.R.R. Tolkien', and if not, log a string like 'You still need to read
// "The Lord of the Rings" by J.R.R. Tolkien.'
var books = [
{
title:'Eloquent JS',
author:'Dont know',
alreadyRead: false
},
{
title:'Eloquent Ruby',
author:'Not sure',
alreadyRead: false
},
{
title:'Pragmatic Programmer',
author:"Can't remember",
alreadyRead: true
}
]
for ( var i = 0; i < books.length; i++ ){
if (books[i].alreadyRead){
console.log("You already ready " + books[i].title + " by " + books[i].author);
}else {
console.log("You still need to read " + books[i].title + " by " + books[i].author);
}
}
// It's like IMDB, but much much smaller!
// Create an object to store the following information about your
// favorite movie: title (a string), duration (a number), and stars
// (an array of strings).
// Create a function to print out the movie information like so:
// "Puff the Magic Dragon lasts for 30 minutes. Stars: Puff, Jackie,
// Living Sneezes."
var favouriteMovie = {
Title : 'Titanic',
Duration : 100,
Stars : ['leonardo decaprio', 'kate winselt', 'someone else']
};
var printFavouriteMovie = function(movie) {
var Title = movie.Title
var Duration = movie.Duration
var Stars = movie.Stars
console.log( Title + " lasts for " + Duration + " minutes. Stars: " + Stars.join(", "))
}
printFavouriteMovie(favouriteMovie);
// https://gist.github.com/wofockham/cc7c6be88ae0cf1fe709
// triangles:
// Given the following object, write an area function in JavaScript
// that calculates the area of triangle:
// var triangle = {
// sideA: 3,
// sideB: 4,
// sideC: 5
// };
// Make sure your program detects triangles with invalid sizes
// (e.g. there are no triangles with sides 1, 1 and 15)
var triangle = {
sideA: 3,
sideB: 4,
sideC: 5
};
var area = function(triangle){
var sideA = triangle.sideA;
var sideB = triangle.sideB;
var sideC = triangle.sideC;
var sides = (sideA + sideB + sideC) / 2;
// console.log(sides);
var area = Math.sqrt(sides*(sides-sideA)*(sides-sideB)*(sides-sideC));
// console.log(area);
if((sideA + sideB > sideC) && (sideA + sideC > sideB) && (sideB + sideC > sideA)){
console.log(area);
}else{
console.log("not a triangle");
}
}
area(triangle);
// calculator:
// create a calculator object that has funcitons add subtract etc inside it
// Create a calculator in JavaScript.
// Requirements
// Prompt the user to enter an operator and two operands.
// Support the following operations: addition, subtraction, multiplication, and division.
// Output may appear in the console or in an alert.
// Bonus
// Support the modulus operator.
// Support the square root operator.
// Support more than two operands.
calc = {
// tidy: function(a) {
// return parseInt(a);
// },
// #returns pars int of a
add: function(firstNum, secondNum){
var result = parseInt(firstNum) + parseInt(secondNum);
console.log(firstNum + " + " + secondNum + " = " + result)
},
subtract: function(firstNum, secondNum){
var result = parseInt(firstNum) - parseInt(secondNum);
console.log(firstNum + " - " + secondNum + " = " + result)
},
multiply: function(firstNum, secondNum){
var result = parseInt(firstNum) * parseInt(secondNum);
console.log(firstNum + " * " + secondNum + " = " + result)
},
divide: function(firstNum, secondNum){
var result = parseInt(firstNum) / parseInt(secondNum);
console.log(firstNum + " / " + secondNum + " = " + result)
},
modulo: function(firstNum, secondNum){
var result = parseInt(firstNum) % parseInt(secondNum);
console.log(firstNum + " % " + secondNum + " = " + result)
},
sq: function(firstNum){
var result = Math.sqrt(parseInt(firstNum));
console.log("The sq of " + firstNum + " = " + result)
}
};
var firstNum = prompt("Enter the first number: ");
console.log("The number is, " + firstNum);
var operator = prompt("Enter an operator: ");
console.log("Operator: " + operator);
if (operator != "sq"){
var secondNum = prompt("Enter the second number: ");
console.log("The number is, " + secondNum);
}
if(operator === '+'){
calc.add(firstNum, secondNum);
}else if (operator === '-'){
calc.subtract(firstNum, secondNum);
}else if (operator === '*'){
calc.multiply(firstNum, secondNum);
}else if (operator === '/'){
calc.divide(firstNum, secondNum);
}else if (operator === '%'){
calc.modulo(firstNum, secondNum);
}else if (operator === 'sq'){
calc.sq(firstNum);
}else {
"unknown operation";
}
###Guest speaker
###Homework: MTA in JS
-
MTA
-
Good Parts Video
-
Eloquent JS
-
Speaking JS
##Wednesday
###Review
###Callbacls
###DOM
###Node.js
##Thursday
##Warm up: Allergies
https://gist.github.com/epoch/add2bfb1dcfb744727e3
##Continue Dancing Cats
##jQuery Intro
##ATM Lab
##Friday
###COLR
###PAINTR
###Something about DT
DT's talk about objects
everything u normally put in a class is for new instances of that class eg
class Hacker
def write_code
"blah blah"
end
end
may = Hacker.new
may.write_code
=> "blah blah"
except when you put a self method in the class, it's for the self, which is the class, which is just another object
which is why when you call a self method it called like this: for example Hacker.binge
class Hacker
def self.binge
"bingo"
end
end
Hacker.binge
=> "bingo"
###Homework
-
Allergies multiple foods
-
Refactor ATM code, get background color change working
-
Add more to Dancing Cats
-
Make Paintr pretty
-
MTA with jQuery
-
MAke a Froyo machine - http://www.teaching-materials.org/jsdom/exercises/instructions.html