Code Academy Week 2 Notes Post 02

2012-01-19_08.01.49
Methods always return something, even nil
Put an at sign in front of variable makes it an instance variable
Class names get upper case – but when you enter rails generate command you can make the model name lower case
model: class name is singular – this is a particular row in the database
The generators are pretty forgiving
But the pluralization is important – you need to get that right
Model names are singular, table name is plural
Model methods: new, save, all, first,
Landmark.all -> talks to the table
To populate database in the rails console:

a = Landmark.new
a.name = "Soldier Field"
a.cost = 50
a.save

Undocumented trick in rails console: type name of class and press enter. If there is a model class with that name, it will print info about class
Another way: pass a hash

x = Landmark.new(:name => "Art Institute", :cost => 18)

Hash keys: Could be strings, people prefer symbols
symbol: like a lightweight string, faster to process, fewer methods you could run on it, like a number that’s easy to read
You still call x.save with hash
He used “x” as variable name twice
The old value went away
Another way:

Landmark.create(:name =>"City Hall", :cost => 0 )

Parentheses are optional in Ruby
Using create will save it in one step
What if I have another landmark with the same name as an existing one?
Landmark.find(4) where the arg is the ID number
The IDs start at one
To list them:

y Landmark.all

To list one

y Landmark.find(3)
x = Landmark.find(2)
call x.name = "jdjd"
x.save

How to delete?

x = Landmark.find 4
x.destroy

But variable x still has data in it, even though that record is not in database
Or you could call Landmark.destory(id_name)
You could do Landmark.find_by_cost(15)
That would show anything with a cost of 15
Landmark.find_by_$FIELD($ARG)
The find_by methods will only give you the first that it finds
It dynamically makes methods via code generation = kind of metaprogramming

Some of the HTML is done by app/views/layouts/application.html.erb
The yield method puts our stuff in there
You can have different layouts for different controllers

How to select one and show just that one?
Go to controller file:

@landmark = Landmark.find(ID)

Make a new route:

get "landmarks/5/show", :controller => 'landmarks;, :action => 'show'

That’s hard-coded

get "landmarks/:id/show", :controller => 'landmarks;, :action => 'show'

What about the controller? How to put that :id in call to Landmark.find?
Now, 5 is hard-coded in the controller. Here is the log:

Started GET "/landmarks/3/show" for 127.0.0.1 at 2012-01-19 09:25:56 -0600
  Processing by LandmarksController#show as HTML
  Parameters: {"id"=>"3"}
  Landmark Load (36.0ms)  SELECT "landmarks".* FROM "landmarks" WHERE "landmarks"."id" = ? LIMIT 1  [["id", 5]]
Rendered landmarks/show.html.erb within layouts/application (8.6ms)
Completed 200 OK in 152ms (Views: 113.2ms | ActiveRecord: 36.3ms)

The second time is better:

Started GET "/landmarks/3/show" for 127.0.0.1 at 2012-01-19 09:27:06 -0600
  Processing by LandmarksController#show as HTML
  Parameters: {"id"=>"3"}
  Landmark Load (0.1ms)  SELECT "landmarks".* FROM "landmarks" WHERE "landmarks"."id" = ? LIMIT 1  [["id", 5]]
Rendered landmarks/show.html.erb within layouts/application (4.0ms)
Completed 200 OK in 10ms (Views: 8.8ms | ActiveRecord: 0.4ms)

If you changed :id in the route to :jeff, you would get the same thing in the log except for timestamps, and

Parameters: {"id"=>"3"}

would be

Parameters: {"jeff"=>"3"}

So to get the id we send, put this in controller:

@landmark = Landmark.find params[:id]

or

@landmark = Landmark.find( params[:id])

Model: singular, controller is plural
Model: name.rb, Controller: names_controller.rb

To catch a bad :id in controller show method:

if Landmark.exists?(param[:id])
    @landmark = Landmark.find(params[:id])
else
    @landmark = Landmark.first
end

That’s not the best way, but it works for now

Change routes.rb:

get "landmarks", :controller => 'landmarks', :action => 'index'

Or

get "landmarks" => 'landmarks#index'

And for the other one:

get "landmarks" => 'landmarks#show'

This is only for Rails 3 and beyond
Put a link that takes us back to the home page:
IN the show template for show.html.erb
You could remove /public/index.html
and put this in routes.rb:

root :to => 'landmarks#index'

rake has a lot of good stuff

rake routes

will print the routes

ericm@finance:~/ruby/codeAcademy/tth/second$ rake routes
     root     /                             {:controller=>"landmarks", :action=>"index"}
landmarks GET /landmarks(.:format)          {:action=>"index", :controller=>"landmarks"}
          GET /landmarks/:id/show(.:format) {:controller=>"landmarks", :action=>"show"}

so if the route has a name, you can use it in a link_to method call

<%= link_to 'Home', landmarks_url %>

You need to run rake routes to see which ones have names
You could also do landmarks_path
This will just create a relative URL

You can give a route a name:

get "landmarks/:id/show" => 'landmarks#show', :as => :landmark

In the index when we iterate, we could:

<li><%= link_to landmark.name, "/landmarks/#{landmark.id}/show" %></li>

or

<li><%= link_to landmark.name, landmark_url(landmark) %></li>

or

<li><%= link_to landmark.name, landmark_url(landmark.id) %></li>

Let’s add a form
What should the URL be?
/landmarks/new
So put it in the routes.rb

get "landmarks/new", :as => :new_landmark

So put an action “new” in the landmarks controller
and create a file app/views/landmarks/new.html.erb

When to add a controller instead of a new method?
Is the activity still related to the same type? Or is it a new thing?
We do not need the “form” tag

<%= form_for @landmark do |form| %>
    <%= form.label :name %>
    <%= form.text_field :name %>
    <%= form.submit %>
<% end %>

Go to routes:

post "landmarks" => 'landmarks#create'

put a create method in the controller
The new method was just for the form
In log:

Started POST "/landmarks" for 127.0.0.1 at 2012-01-19 11:14:23 -0600
  Processing by LandmarksController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"FO5+OlbNWa0g7xO3a/2hWtXnIPx7u5Ml0du2Oij74Eg=", "landmark"=>{"name"=>"fghd"}, "commit"=>"Create Landmark"}
Completed 500 Internal Server Error in 3ms

ActionView::MissingTemplate (Missing template landmarks/create, application/create with {:handlers=>[:erb, :builder, :coffee], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* “/home/ericm/ruby/codeAcademy/tth/second/app/views”
):
In parameters, there is

"landmark"=>{"name"=>"fghd"}

So our data is in the hash. The data is the value of a hash, which itself is another hash
Do this:

params[:landmark][:name]

You could do:

form_data = params[:landmark]
@landmark.name = form_data[:name]

At the end of the create method

redirect_to root_url

the URL must be a named route

Started POST "/landmarks" for 127.0.0.1 at 2012-01-19 11:22:44 -0600
  Processing by LandmarksController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"FO5+OlbNWa0g7xO3a/2hWtXnIPx7u5Ml0du2Oij74Eg=", "landmark"=>{"name"=>"fghd"}, "commit"=>"Create Landmark"}
  SQL (3.4ms)  INSERT INTO "landmarks" ("cost", "created_at", "name", "updated_at") VALUES (?, ?, ?, ?)  [["cost", nil], ["created_at", Thu, 19 Jan 2012 17:22:44 UTC +00:00], ["name", "fghd"], ["updated_at", Thu, 19 Jan 2012 17:22:44 UTC +00:00]]
Redirected to http://localhost:3000/
Completed 302 Found in 160ms

Images:
app/assets/images
The tag is

<%= image_tag 'tower.jpg' %>
<%= image_tag 'tower.jpg', :size  => '200x100' %>

How to get rid of a landmark:
Is the show.html.erb

<%= link_to "Toast", landmark_url(@landmark) %>

In routes:

delete "landmarks/:id", :as => :landmark

But there is a name conflict in the route – we will look at this next week

To update in console: could get it, change it, save
or: call method update_attribute

Image from Wikimedia, assumed allowed under Fair Use. Image from the Vatican Virgil, a 5th century manuscript of poems by Virgil.

Code Academy Week 2 Notes Post 01

Here are my notes for the first day of week 2 at Code Academy.

 

2012-01-17_08.07.38
Methods:

Classes: Fundamental

Ruby On Rails:
Why use it?
Database-Backed Web Applications
Convention Over Configuration
Agile Development

Rails quickstart:

rails new myapp
cd myapp
rails server

go to http://localhost:3000

Webbrick is great for development. There is Apache, nginx for production.

rails generate controller landmarks index

The index arg is a method that will be created in the controller
There is also an index file in app/views/landmarks
Use plural for controllers
So we could view this at http://localhost:3000/landmarks/index

For a request, the route config will pick a controller

Models: software objects that represent real-world objects. We use Ruby classes to define models.
They go in the $APP_NAME/app/models folder
In models folder, create a file landmakrk.rb
Controllers are plural, models are singular
Make a model class, then fire up the “rails console”
like “rails server” you should be at the top level of the app
In the html.erb files:

<% ruby code %>

to print output of Ruby code:

<%= hancock.name  %>

This is like string interpolation, but it is called “embedding Ruby” when it is in an erb file
The variables are local to that view file. They die once the view is rendered
Controllers job is to decide what data to present, view decides how to present

Each method in controller corresponds to a view file – that is pairing
Instance variables in method are readable by the view
Now getting data from database

rails generate model product name:string color:string
rails generate model (generator) product (model name) name:string (model attribute) color:string (model attribute)

could run for help:

rails generate model -h
rails generate model landmark name:string cost:integer

This creates a file in db/migrate/20120117171507_create_landmarks.rb
and app/models/landmark.rb
Here is the migration file:

class CreateLandmarks < ActiveRecord::Migration
  def change
    create_table :landmarks do |t|
      t.string :name
      t.integer :cost

      t.timestamps
    end
  end
end

How to run it? with rake (or ruby make)

rake db:migrate

Now go to rails console:

ericm@finance:~/ruby/codeAcademy/tth/second$ rails console
Loading development environment (Rails 3.1.0)
ruby-1.9.2-p290 :001 > ballpark = Landmark.new
 => #<Landmark id: nil, name: nil, cost: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p290 :002 >

The object has fields, even though the model class is pretty empty

you get the attr_accessors automatically:

ruby-1.9.2-p290 :001 > ballpark = Landmark.new
 => #<Landmark id: nil, name: nil, cost: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p290 :002 > ballpark.name = "Wrigley Field"
 => "Wrigley Field"
ruby-1.9.2-p290 :003 > ballpark.cost = 10
 => 10
ruby-1.9.2-p290 :004 > ballpark
 => #<Landmark id: nil, name: "Wrigley Field", cost: 10, created_at: nil, updated_at: nil>

You can add stuff to database via the console

ruby-1.9.2-p290 :005 > ballpark.save
  SQL (54.8ms)  INSERT INTO "landmarks" ("cost", "created_at", "name", "updated_at") VALUES (?, ?, ?, ?)  [["cost", 10], ["created_at", Tue, 17 Jan 2012 17:23:53 UTC +00:00], ["name", "Wrigley Field"], ["updated_at", Tue, 17 Jan 2012 17:23:53 UTC +00:00]]
 => true

To list rake targets: rake –tasks

To delete database and recreate it with same structure:

rake db:migrate:reset

Now, how do I make a page for each landmark?
How about a show page?
add

get "landmarks/show"

in config/routes.rb
So we need a file app/view/landmarks/show.html.erb and a show method in the Landmarks controller
Action: Is method in controller and corresponding view page

Image from Wikimedia, assumed allowed under Fair Use. Image from the Vatican Virgil, a 5th century manuscript of poems by Virgil.

Code Academy HTML5 notes

Part of Code Academy is an HTML5 class that happens on Monday nights. The first class was on a Wednesday. I went to that one, and I plan on going to more in the future. The lecturer is Shay Howe, a designer at Groupon.

 

2012-01-18_17.58.26 - HTML5 & CSS class
Div and span
Divs are block-level, it does not break the flow, it will assume its full width and height
span is in-line, it could be in the middle of a paragraph or a div
Google uses h1 tags for SEO
Use the "strong" tag for bold, instead of "b". "b" gives no information
also: use "em" for italics
href means hyperlink reference
title attribute used for voice systems and in little window that pops up in mouse over

New HTML5 elements: header, article, section, aside, footer, and nav (I think nav was around)

Article: content that could stand on its own
aside tag: reserved for sidebars

head element is still here, even though we now have a "header" element
header is within body
aside element is positioned in CSS
articles can be in sections, or sections can be in articles

html5 microformats: hidden data
like when you search for "blackhawks" you get the upcoming games, or addresses for franchises -
that is how you use microformats
microformats.org is the wiki

also WAI-ARIA roles - also only for computers
this is an attribute in tags - for every structural tag
article (article), header (banner), aside (complementary), section (region), footer (contentinfo), nav (navigation)

w3schools.com

Image from Wikimedia, assumed allowed under Fair Use. Image from the Vatican Virgil, a 5th century manuscript of poems by Virgil.

Code Academy Notes Week 1

Here are my notes from Code Academy week 1.

2012-01-12_08.14.41
Almost everything is lower-case
Methods: def method_name to name

Lists in Ruby
Very important to be good with lists.

landmarks = [ "Wrigley Field", "Millenium Park", "John Hancock Center" ]

This is an array. You do not specify the size.
Iterate through array:

landmarks.each do |name|
  print_landmark name, "100"
end

irb is “Interactive Ruby”
for a variable or a class, you can type “x.methods” in irb to get all the methods you can call on it
to print them alphabetically, x.methods.sort
to get out of irb, type “exit”
An array is a list of single elements
A list of pairs is a hash:

landmarks = { "United Center" => "90",
              "Wrigley Field" => "40",
              "Millenium Park" => "0",
              "John Hancock Center" => "15" }

Braces instead of brackets
Iterate through hash:

landmarks.each do |name, fee|
  print_landmark name, fee
end

Any methods created in a variable are local to the method. They only have meaning within the method

CSS

Back to Ruby: String interpolation, use the pound and braces:

puts "#{landmark_name} --- #{cost_of_admission}"

Interpolation is a bit faster

To set the variable, single equal sign:

x = 10

To compare the variable, double equal sign:

x == 10

Ruby classes:

attr_accessor :name_of_symbol

give it a symbol (colon and some name)

Variables: @name, @address, @cost: Private variables to that object
attr_reader will allow you to set it only at initialization, and only read thereafter
You could make a variable @api_key to be private, just don’t provide an attr_accessor
In pure Ruby, there is no way to ensure that @cost is always greater than 0. I would have to write my own methods for that.

Image from Wikimedia, assumed allowed under Fair Use. Image from the Vatican Virgil, a 5th century manuscript of poems by Virgil.