Code Academy Week 11 Notes

2012-03-20_08.52.33
Look at rspec
to not include default testing framework:

In Gemfile:

to update test database

History for rails and rspec project:

 

Dave Hoover
He had to create his own software engineering education
His advice:
1. seek out mentors
2. kindred spirits
3. Community

He tries to be the worst person on the team
Keep diving deeper into Rails, know about testing
he uses TestUnit – no RSpec back then
Expand your bandwidth, drink from the firehose
Learning is fun, but debugging may not be
Learn how to expand/contract your bandwidth
After Code Academy: Don’t be discouraged
Very few people just walk right into a job
It takes some time
Reach out, ask people in the community, find out what is out there
Apprentice: 8th Light, Groupon, Trunk Club
You will need to hustle

——
.rspec file:

We want a model without a database table

No migration generated, but it still has ActiveRecord in it

so take out “< ActiveRecord::Base”

If you just run “rake”, it will run your tests
Jeff do not test your views, just your models and controllers

2012-03-22_08.30.05
Modules: you can include or extend a module
you can extend a module and use its methods as class methods by calling with “extend”
in irb: you can require or include files

if it is in same dir from which you called irb
You could also “load” a file

This will reload the file if you call it again
in the file you can call “require relative ‘modules'” which goes from pwd of the file
Modules extend a class that extends Kernel

It is better to use composition than inheritance many times
inheritance cements the relationships. It only works for one kind of re-use: is-a

In modules you can make a method self.method_name and you can make those available at module level
No instance needed

self keyword: it refers to the current object
class scoped code is executed when code is read/loaded/class initialized
It is only run once

That second self will print “main” even though you are not in a class, “out in hyperspace” as Jeff puts it

In class scope, self returns name of table, inside an instance method, self refers to the instance

— look for a “collect” method

We could make a method called “method_missing” that will handle any calls to undefined methods

m is a symbol that is the name of the ghost method
*args is an array of args

This may be how Rails does find_by_column name:
it uses regular expressions in method_missing

You could also call super in method_missing

Another use of modules: namespacing

If you have two classes with the same name, you will get the union of the classes
If the same method name is used, the last method defined wins

You could add to String, Array, Hash

modules package stuff for re-use and good for namespacing

You can call instance.respond_to?(length) to see if it will respond to that method call

You may get stuff in a variable

will give the gems with “acti” in the name

will tell you where the gem was installed

In rails apps, there is a lib/tasks directory
Make a file called flights.rake

it must go in a block

Then you can call “rake jeff”
To see in the list, put
desc “sample rake task”
in the file – before line with :task

This will make the :jeff task run the :prereq task first

What if you deal with models?

You can namespace your tasks

Code Academy Week 10 Notes

2012-03-13_08.54.13
Hidden field in a form: f.hidden_field(:list_id)

Nested resources:

But is a top-level list of grades any good?

Do this in routes.rb

students/1
students/1/grades
students/1/grades/4
1 is :student_id, 4 is :id for grade

Coffeescript:
coffeescript.org
It is the default syntax for Rails 3.1 and up

becomes

For code block, you indent instead of using braces. Indentation is meaningful. So use soft tabs.
We need parentheses if the function takes 0 parameters.

HAML:
Put in two gems:

 

So we get haml:

In HAML, whitespace is significant
For classes for p tag, you could do this:
p.red.something

Back from break
If you have a list of items with an association:

you can use :dependent with :delete, :delete_all will delete without calling callbacks (like if you have some email actions), :nullify removes foreign key

Use twitter authentication
Create a sessions controller

The create action will be called by Twitter

Routes:

Use the omniauth gem
This gem will add routes to your application.
1. Register your app with twitter at https://dev.twitter.com
You get Access Level, Consumer Key, Consumer Secret, Request Token URL, Authorize URL, Access Token URL, Callback URL
We set the callback URL
You need to put in 127.0.0.1 instead of localhost for dev
2. In gem file
You need to add a gem for each “strategy” https://github.com/intridea/omniauth/wiki/List-of-Strategies

There is no base omniauth that we need to add.
The strategy gems depend on the base omniauth gem, and they will fetch it.
3. Write an omniauth initializer
in config/initializers: any code there will be run once – no naming standard
Create a file called config/initializers/omniauth.rb
Add this:

In routes put

match will map to any HTTP verb

In application layout: add a signin link

So your user model could just have a column for Provider and UID
You could get other stuff from hash

They have provider :twitter, ENV[‘TWITTER_KEY’], ENV[‘TWITTER_SECRET’]
environment variables are part of operating system
To view them:
env | sort
in irb, type “ENV”
ENV[“PATH”] is the OS “path” environment variables
So you can add it in the environment. It only works on a specific machine. Good luck deploying to Heroku
In terminal:

print them out:

2012-03-15_08.28.54
cron tasks:
devcenter.heroku.com/articles/cron

1. create a file lib/tasks called cron.rake
2.
3.
4. desc “import tweets”
5. task :cron => environment do
6.
7. end
heroku rake cron
——————

a
This is from Entry form. Entry belongs_to runner, runner has many entries
So :runner_id is the field in Runner, id is from runner, name is also from runner
foreign key, table, what to save as the foreign key, what to display

Code Academy Week 9 Notes

2012-03-06_08.01.48
Shay Howe: design is not a veneer, it is very important
HTML: Markup (content, structure, meaning)
CSS: presentation language (style)
HTML: elements, attributes, tags
Elements: designators that build objects on a page
Attributes: provide more info to element
tags: elements and attributes together
elements can be block and inline
block: bigger, larger elements of the page, push everything else below them
inline: do not begin on a new line
head is metadata for browsers, servers, etc
body: what the user sees

CSS: selectors, properties and values
selector is an HTML element
property: style to be applied
value: behavior of property
id and class selectors in addition to element selectors
ID can be used once on a page
class can appear many times on a page
ID is with a pound, class with a decimal point
#logo – ID
li.tumblr – class
you can chain them

the box model
every element is a rectangle
has height, width, can have border, padding and margin
adding border, padding and margin will increase the size of the box

floats:
can float to the right or left
long-hand numbers for margin, padding: top, right, bottom, left: clockwise
You may have to clear stuff

Back to Jeff:

Until you call .all or .each you can keep chaining methods on the proxy
joins method: put in a symbol that is a has_many or belongs_to symbol
You cannot just pick anything you want
You can chain them

Now: John McCaffrey, a mentor
@J_McCaffrey
What happens next?
don’t waste time doing stuff you’ve already done before
Capture what you know, from books, people, etc
Write it all down
Take lots of notes, make them searchable, reachable
Tools: Editor, Evernote, GoogleDocs
He gets pdf versions of all the tech books he buys/reads, puts them on Google docs, so he can search

Code = Executable notes
save and organize your projects
create tests to document what you know
follow interesting projects on github

Links and sites: Write them down, google history, delicious

User other people’s notes:
gem install cheat
it gives you other people’s notes

Local docs:
gem server: starts a local server, then go to
http://localhost:8808

Look into ri and rdoc to get local documentation
sdoc is good

Do what you can to capture what you know right now
When you find something useful, write it down

What about afterward:
Finish Hartl tutorial
He said many people die after chapter three. I personally have no idea why.
CodeSChool.com
railsforzombies.org has some ruby jobs – also a good tutorial
rubykoans are good, since a lot of Rails people hit a wall because they do not know a lot of Ruby
Javascript: ejohn.org/apps/learn – good thing to know – knowing JQuery is a good way to get ahead
RailsCasts
peepcode.com: pay site
Getting help:
20 minute rule: If I can’t figure it out after 20 minutes, start asking. Sometimes asking the question can help you figure the answer
Campfire/IM:
Local docs
Stackoverflow.com

Google better:
exclude with –
“quoted search”
fuzzy search ~
site:specific search
define:antidisestablishmentarianism
range ’28gb ssd $100..$230′
Time in New York

how to ask a tech question:
Do some background search
Document what you’ve tried
Find the right place to ask
Post your question with summary
Link to full details (gist)
be willing to back up a few steps
Post the resolution

Honing your skills:
can you build a report, parse a spreadsheet, keep builing apps – a lot of them
help the next batch of CA students
help out on Stack Overflow

Build your profile:
github, heroku, workingwithrails.com

Freelance:
elance.com, odesk.com, rentacoder.com, donanza.com, cloudspokes.com

Build stuff
colloborate wiht CA students
participate in startup weekend
look for volunteer opportunities: taprootfoundation.org, grassroots.org, overnightwebsitechallenge.com

techstars.org
killerstartups
startupsopensourced.com

master your info
collaborate
—–
Back to shay :
Take Eric Meyer’s reset CSS file
Puts it in app/assets/stylesheets/global

How to change the order of the stylesheets?
In application.css:

the aside tag: This will put stuff over to one side. I think.

He makes a stylesheet called mobile.css.scss. He wants to load it last, so he has to go into application.css and adds all the other ones, and puts mobile.css last

Put a media query in that style sheet. Everything that got a width somewhere else gets a width here

He is using a chrome plugin called window resizer

—-
Back to Jeff

Javascript:
A whole new language
Has nothing to do with Java
Same IPO pattern: input, process, output
Sort of object-oriented
more function-oriented
Define functions, pass function as a argument to another function
Runs inside the browser

Why Javascript?
1. To change HTML code in the browser
You can respond to user events
2. For asynchronous HTTP requests. More subtle, more powerful
This is how Google maps is done

Ruby vs Javascript

parentheses in javascript are required
semi-colon at the end of the line
Another semi-colon to close function

Functions without names:

HTML support:

In HTML5, javascript will be the default target, so you can just say
<script>

How to call the function:

Obtrusive Javascript: how it was done for a long time
To comment out: // stuff
Or /* jfjfjfj */
Like in C, C++
In the h1 tag:
<h1 oclick=”saySomething()”>
Header
</h1>

callbacks:

 

JQuery in Rails:
Rails 3.1+ has built-in support for jQuery Core and jQuery UI
jQuery UI is not included by default

JQuery will usually start with dollar sign
<p>Hello</p>
$(“p”)
You put a CSS selector in the call
This will return 0 or more elements that match the CSS criteria
$(document).ready(f);
This will grab the whole document, and call the ready method, supply a callback function
Or you could just do

Lab:

In routes:

 

In app/assets/javascripts/application.js

2012-03-08_08.38.45
To get jQuery to work:

in the head. For some reason you have to close the tag with another closing tag, instead of just the ” />”

How would we work this into a Rails app?
User story: I want to write an app that will maintain my personal Aha! list

get calendar from jqueryui.com
Datepicker: http://jqueryui.com/demos/datepicker/
We will put this in our app somewhere:

add this to app/assets/javascripts/application.js

go to the form and make the date field a text field

Can we do a delete without a full request cycle?
Now, we want to change destroy
AJAX: Asynchronous Javascript And XML
Asynchronous: The user does not have to wait
XML: It could be JSON or HTML
3-step recipe
1. :remote => true
You can add this to any link or form. It then becomes an AJAX request, instead of a non-blocking request
2. Respond to JS: enhance your respond_to block to accept JS requests
3. Generate a JS response: instead of HTML.

Go to the index page

Add another option

Go to the controller action destroy

Then create app/views/entries/destroy.js.erb, so format.js has something to render
We can embed Ruby in this template. Jeff will write some JQuery that will execute

How to get the CSS ID?
In the index table, put an id in the tr field

Prepend entry_ in case we have multiple tables
That ID will be sent in the link_to for destroy

We have @entry in the destroy action

We could refactor

In the index page, change tr to use dom_id:

or

For the create.js.erb

create a partial
from table row in index.html.erb

in the partial
<tr>

</tr>

So in JS:

You need another helper
Some of the markup will have quotes in it. That can mess up the Javascript
So do this:

Or just use the synonym “j”, but escape_javascript is clearer

Don’t forget the

Code Academy Week 8 Notes

2012-02-28_08.18.14
undefined method model name for NilClass:Class
Means there is a problem with the model
So instantiate it in the controller from the session

How to override application.html.erb for a controller or action

For orders controller, app/views/layouts/order.html.erb
To specify layout:
in controller:

or in def new:

we need to encrypt the credit card number. Look in config/application.rb
We will look at
config.filter_parameters +=[:password]
This will filter password out of the log
So we can add to the array
config.filter_parameters +=[:password, :card_number]

asset pipeline: We will talk about it throughout the week. Look in the assets folder. Images, javascript and stylesheets.
It takes all the javascript and puts it in one file, so the browser only has to make one request
Same for css
For css, you should go to application.css and specify files and/or directories

require_tree will do everything aplhabetically. You can put them in your own order.

In development mode, there is no asset pipeline. You use it in production.

In config/environments/development.rb

if you set that to false, you won’t see the GET requests in the logs for EVERY js and css file

Jeff can get to other order pages as well as his own
We have authentication. What about authorization?
In orders controller:

WHat if that ID is not in the order table?

You could do this:

But then it looks like redirect is the default.
Or

Moving this to a one-liner could make it a but confusing
You could also do

or

Stay at same level of abstraction throughout the html.erb files
if you have render tags with low-level html, that could look bad

Class method that makes an ActiveRecord call
Use the scope facility
Instead of:

 

scope creates a class-level method, and returns rows
You cannot just return one row

Maybe we want to pass a param from the view to the class-level method or scope

Easy for method.
For a scope:

Orders Controller:
We have a before_filter
We have model callbacks in cart_item.rb
Those are sort of like lambdas as well.
We do not call it, Rails calls it for us at some point.

Let’s do a scope on price for products:

Then in the view you could chain the scopes

Lambda with a default value for min:

Getting the data you want:

You can also use % for wildcards

In Products Controller:

or

So why not do this? Jeff will explain
You could get SQL injection
So do this:

Use the question mark placeholder

ActiveRecord will create the SQL for you
Fuzzy search:

Then in the controller you could chain the methods

It is not until you get to the @products.each (or a .all) in the view that you run the query

Should you use the products controller for searching, or make a search controller?
the form_tag goes to ‘/products’ with a get, which will go to the index action
—-
New app:
User Story Analysis
1. Identify resources
2. Create Models
3. Implement business rules
4. Create User Interface

Some people go in the opposite order

Air Academy User story
1. As a visitor, list the flights

In Rails 3.2, when you generate model, if you do not specify the types it will assume that it is a string
rails g model Airport code:string city:string
ericm@finance:~/ruby/ca_files/air$ more db/migrate/20120228174012_create_airports.rb

emacsnw db/migrate/20120228174012_create_airports.rb

For flights, we need two airports, not just one departure_airport_id, arrival_airport_id

If you say belongs_to :blah, the table needs a column blah_id
If that is the only belongs_to, Rails will assume there is a Blah model

2012-03-01_08.38.49
Pagination:
Kaminari, Will_paginate, roll your own

User story: As a user, I want to make a reservation
As opposed to doing something “as a visitor”
Different permissions, etc
So for “As a user” that user story needs an account
User story analysis
1. Identify resources
2. Create models
3. Implement business rules
4. Create user interface

reservation model has user, a flight, chosen departure date, credit card number
Associations:
user can have many reservations
flight has many reservations
reservation belongs to flight and belongs to user

departs_on for dates, departs_at for times

How to decide to model or scaffold? How much of scaffold will you use?

add_index on the reservation table
add_index is outside the create_table block

Good to have indexes for foreign keys
Then run

rake db:migrate:reset will drop database and recreate tables
rake db:seed
You could do

——————
Now JC from DevMynd is talking
database: structured set of data on a computer, accessible in various ways
five categories: relational, graph, key-value, document, column family databases
Relational database: built around relational theory (first-order predicate calculus), schema defined in tables of columns and rows, data is related through matching keys
Graph: based on graph theory. These DBs use nodes, properties and edges to describe a “web” of data. They can be powerful for complex ancestral queries (Amazon: People who bought X bought Y)
Key-value: primary way of retrieving objects is by a single key. What can be stored as a value varies.
Redis is used for queing systems
Document database: storing document-oriented, semi-structured data. Normally within a loose schema and the ability to store/retrieve nested structures
Column-family database: inverse of relational model. Big table.
Choosing data store can be pretty complex.
Considerations: indexing, querying, scaling, modeling, mapping, analyzing, recovering
Indexes: a parallel description of your data optimized for fast lookup
If you will ever do an order_by or a conditional query
Finding by department and last name is different than index that finds by last name and first name
Querying: getting info from db. Do we use a template object, a query language, or a string key?
Mongo can use query syntax, or you can pass in a template doc
scaling: scale up (faster, bigger hardware) or out (distributing data, indices and queries across more machines, aggregating the results)
mongo can shard well, so can redis
modeling: is your schema fixed or flexible? a few large things, lots of small things
Mapping (ORM) – ActiveRecord for RDBMS, Mongoid for MongoDB, Redis ruby driver
how will you interact with db?
analysis: what does the database provide?
recovery: relational: replication, push log to another system
Mongo: backup and restore tools
Heroku, other cloud backups are not that great

optimization: this is usually the first bottleneck
universal: careful indexing, duplication
relational: de-normalization, pivoting, materlialized views
normalized: each concept in a different table, less repetition
pivot: making rows into columns, and vice versa
materialized views:
non-relational: nest relationships, parallel queries
downside of indexing: it can take a LOT of space, plus index might be held in memory instead of disk
Put query logic in your model, not your controller
So if you change the datastore, you can just change it in the model class
relational tables good for complex joins
Think carefully about uniqueness and nullability early on

——————
Back to Jeff
For flight page, give some info about flight
the user is part of the session
reservation for
So in reservation controller, in new method: @user = User.find(session[:user_id])
You could do it from show page for a flight
@user = User.find()
Get stuff from flight show page
Reuse the flight_details partial

But we could get a Nil
So in the reservations controller
We will do something in def new
We could have a link from flight show page
@flight.id) %>
So in new,

So we want to put that link in an if on the flight show page
Put a filter on the reservations new controller

@flight.id) %>

In reservation form:

in reservation controller.new:

validation on reservations:

create method in reservationcontroller:

Sending email in Rails – it could depend on your host

In our reservation controller, we will use this in respond_to block

in ReservationMailer

So in app/views/reservation_mailer/confirmation.text.erb
Hello, ,
Thanks for sending us $300.

Flight details
———————
Flight number:

Image from World Digital Library, assumed allowed under Fair Use. Image from the Ashburnham Pentateuch, or Tours Pentateuch, a Latin manuscript of the first five books of the Old Testament from the 6th century or 7th century. Its place of origin is unknown.

Code Academy Week 7 Notes

2012-02-21_08.02.14

3 more weeks of core material
The building weeks there might be breakout topics
This week:
Model callbacks
User auth
Nest resources
Search
Pagination
Mailers
Environmental variables

Weeks 8-10
Twitter/Facebook auth
File uploads
Credit cards/PCI
HAML
Asset pipeline
Javascript and JQuery
AJAX
Coffeescript
Database Scaling
RSpec/Testing

Model Callbacks:
For a user story:
As a user, I want to see the total price in the shopping cart before I check out.
When jeff did it, he put it in the view. This is generally considered bad. Need to calculate outside the view.
How about showing total of the Cart?
So we need to add that column, since we don’t have one now.
Or add a method to the cart

Why not do this in the controller
Views cannot call controller methods
You also might need to know the total in another page
But do not call number_to_currency on sum in the model. Do not do any formatting in the model, do not calculate in the view.

Now he is doing total with inject method

You give it 0 arg because that is where you will start. It is another way of doing +=
It returns the final total at the end
Or on one line:
cart_items.inject(0) { |total, item| total + item.product.price }

————————-
@fredlee from ENova is here.
How to succeed at Enova:
– Skillnacity: skill + tenacity. He thinks tenacity is important. Skill can be learned.
– Takes initiative: it is better to ask for forgiveness than permission.
– Selfish giver: willing to give and take
– Networking: Bell Labs: star engineers were good at networking

His thoughts on Design
– Every design decision trends towards “wrong”
– or, every design get a little more wrong each second. The world changes
– design does not matter. Kind of.
So what does matter?
1. Tests. Preferably automated tests that validate system behavior.
2. Short iterations
3. Courage to throw it all away.

Too much technology!
xml, html, css, js, json, erb, yaml
This too shall pass
So what stays the same?
– Users first!
– Speed/scale/performance
– Money (your ability to generate revenue validates your purpose)

Thoughts On Code Quality:
– It does not matter. As long as it works. But higher quality is better
– Lean Startup: If you do not know who the customer is, you do not know what quality is
– Quality is defined by user
– Or, there is no universal objective definition of quality

——————-

Back to Jeff
CartItem model. Create one in memory, add/edit attritbutes, save it. You might later change it, later delete it.
.new
.save
.update_attributes
.destroy

Model validations can affect some of those methods. You cannot save an invalid object.
So first some validation runs. 1 of 2 things will happen.
The Creation case or the update case.
The create path is the first time this object goes into database. It will assign an ID to that object.
If it has already been saved, it will do the update case.
Which case is run will determine the callbacks you can run.
After creation, we can update a total column in the cart.
We write a hook method for callback. Callback meaning we write it but we do not explicitly call it. Rails will call it.
So we run a migration to add a total to the cart.

 

That could also go in an “up” method
If I want to undo it, make a “down” method

# I missed a bit in here due to wireless issues
So now we have a total method, but Jeff already defined a total method
His version will take priority. You can redefine methods.
But it is not a good idea

So in CartItem model:
Add a callback:

Look at the guides to find the callbacks. The symbol is the name of a method that Rails will call.

We could do this in the cart_items_controller
But what if I manipulate my models some other way
Callback: When one model changes another model
This after_create is creation in the database, no necessarily the controller “create” method.
Model callbacks: business process events.
Controllers generate the response. If you can have models talk to each other, that is better.
Javascript and jquery use a LOT of callbacks.
1. Add a total column to the cart model
2. Show the total inside the cart in the view
3. Add an after_create callback to update the total whenever a new cart item is created
rails g migration AddTotalToCart total:integer

The user model:
1. Add “bcrypt-ruby” to your Gemfil
2. Create a User model that includes a string column named “password_digest”
3. Use “has_secure_password” in the model

The user form will have attributes password and password_confirmation, even though they are not in the database. Only password_digest is a column. has_secure_password adds those memory-only attributes.
has_secure_password will also validate that the two password fields are the same
Add a login field.
He did not get in, so he used the logger method
logger.debug “Started sign in action”
Make the link to sign out go to /logout
In routes:

Session is not a regular ActiveRecord class
In the destroy method:

2012-02-23_08.16.47
Authentication (who are you) versus authorization (what can you do)
Authentication: indentifying a user, making them identify themselves – usually username and password
Authorization: Permissions

Only let people check out if they are checked in. You could put this inthe shared/cart partial:
button_to “check out”, orders_url if session[:user_id].present?

Or you could do it in the checkout action
In OrdersController.create:

This could give the double render error
the redirect_to has not effect on control flow. You should end the if block with “return”

But we would need that in the index method as well. That gets messy.
You can also call show with /orders/6
We don’t want this code in three places. How to DRY up controller code? Before filters.

Since we get @user in the filter, we ccan remove all the User.find method calls
If the filter renders or redirects, the action will not be run.

To list all the tables from within the console:

In shopping app, we want to remove the item from the cart.
So in CartItem we put in another callback: after_destroy

We can just call product since we have belongs_to :product in the model
after_destroy is better. It will keep it in memory after it deletes the row in the database. It is better to do after_destroy instead of before_destroy since something may go wrong between before_destroy and the actual destruction

Now we want to add some administrators to manage product catalog.

Let’s change the migration file:
add_column :users, :administrator, :boolean, :default => false

you can use conditional logic in the view:
Instead of class.boolean == true
you can say
class.boolean?

In all those pages. There has to be an easier way.
Put this is a helper. Partial is good for markup. Helper is good for logic.
app/helpers/application_helper.rb

In the pages, do this:

Now we want to sort the data. Use the order method. We have done Product.all, Product.first, etc, now we have

You can also call it on the association proxies

To limit how much you get back:

Most recently added item:
application layout file:
Above the cart:

We don’t have Product.recent_items,
But we have columns in database: created_at and updated_at

But let’s not put that in the view. That could be in the controller instead of the view. Or in the model.

So in the view you can say Product.most_recent.each.do
But this is not an instance method. We want this to be a class method.
So you can do it this way:

or

So you could even do this:

Or self.order. But if you did that, you would still need “self” in the method signature to keep it a class method.

Image from Wikimedia, assumed allowed under Fair Use. Image from the Ambrosian Iliad, a 5th century manuscript of the Iliad.

Code Academy Week 6 Notes

2012-02-14_08.04.44
product has many reviews
There is a proxy for the data – it is a subclass of Array

What is there is no product with that ID?
The “find” method will raise an exception (actually params[:product_id] is nil)
How to make it more forgiving

the find_by_* methods (aka dynamic finders) are more forgiving
You could even get rid of if

How to hide the product pull down in the review form?
Hidden form field
In _form.html.erb for review:

Why do we need an equal sign for if it’s a hidden field?

It still needs to be emitted to the HTML
In Rails, we have 2 methods: present? and blank?
blank? is like nil?
if a string is ”  “, that is not nil, but it is blank
present? is the opposite of blank?
Why have both? Just negate one of them.
!a.blank? is “not the Ruby way” according to Jeff

Matz does not like minimal interface. Sometimes map will feel right, and sometimes collect will.

map is an iterator, like each

map wants a return value from each iteration of the block

<% if @review.product.present? %>
could also be
<% if @review.product %>

show.html.erb for reviews has this at the top:

This method will emit what ever is in the :notice key in the redirect from your controller
This will only live long enough to be redirected
This is called a flash message in Rails
it is a hash
the “flash hash”
You could also set the notice just before the redirect_to

You could make it flash[:zebra]
and call

in the html.erb file

http is stateless, so each request has to provide all the information the next request needs
Putting the query string in the URL has been one way to keep information
User story:
as a user, I want to add several products into a shopping cart
Jeff does it:
Carts and Products
This is many to many
But many carts will want to have products
Make a join model in between
CartItem
Cart has_many :cartItems
cart_item belongs_to a single :cart
A product will have many cart items
a cart item will belong_to a product
cart_itme will have cart_id and product_id

add has_many :cart_item to product
The file name is Pascal case. In code or console, you use underscores

Jeff says the modelling is the hard part of Rails
In the console, you can do this:

in console, this will reload items from database
cart.cart_items(true)
or: cart.cart_items.create :product => Product.last
cart.cart_items.build will make a new cart in memory only.
cart.cart_items.new does not exist on the proxy

Add item to a cart. How to add another item to same cart?
Use cookies
Session data
Each has a name and a value
name/value pair, like a hash in Ruby
Expiration is optional – session by default
cookie data lives in the browser
How to add cookies:

Each cookie is limited to 4K of data
Do not put an ActiveRecord object into a cookie
Cookies are stored on the client machine
deal with session hash in your controllers
It is defined in ApplicationController’s parent
session[:cart_id] = cart.id
The session data is encrypted
In the create method for Cart controller:

Put the cart stuff in a partial that everything can see.
app/views/share/_cart.html.erb

Instead of accessing session hash inside view, make a helper method
Use view helpers

Seed file
Pagination
Seed file will help you pull in test data

Vince did pagination

Checkout: cart becomes an order
Cart partial:

In routes:
resources for :orders
Create an orders controller

Look at guides for sessions and cookies

2012-02-16_08.20.30
In grandma example, they used a form_tag, not a form_for since they did not use a model.
form_tag(“/ask”, :method => “get”) do
put form tags here

routes:
get ‘ask’ => ‘grandmas#ask’

What we started:

Jeff recommends irb or rails console

Two methods:
a.upcase will check if the string contained in a is uppercase
a.upcase! will change the string to uppercase

Some people used regular expressions

Now going back to the shopping cart.
New models: Order, OrderItem

reset_session will reset the whole session
how to just get rid of cart?

Cycle through the cart creating order items, and call order.save afterwards. Fewer transactions.

New app for users

Do not store passwords as strings. We will go over that later.

You could put this in the seeds.rb:

etc, etc, etc,

To wipe out existing items in database, you could add this at the top of seeds.rb
Item.destroy_all
He added users and items to routes with resources

Signup is easy: Just add user to database
Signin and signout are session management
If they are in database, when they sign in just make a session cookie

We create a sessions controller, inherits from application controller

There will also be a folder for sessions, with a new.html.erb
We use form_tag instead of form_for since we have no model

Now in app layout:
if session[:user_id].present?
Hello, User.find(session[:user_id]).name

In routes:
post “/logout” => ‘sessions#destroy’, :as => :logout
link_to “Sign Out”,
button_to will create a post

Make the password a password_field_tag
To do password confirmation:
add a text field in form: password_confirmation, which you can do even though we are in a form_for
Then in model for User:
validates :password, :confirmation => true

For password security:
add “bcrypt-ruby” to Gemfile, run “bundle install”
To user, add a column called “password_digest” as a string
add line “has_secure_password” to the model

If you make a mistake,

Put line “has_secure_password” into the model
For user form partial:
Remove the password digest field from the form
Put in password and password_confirmation

Create an account and sign in at the same time
In users controller in create

So how do people sign in? We don’t want them to know their digest
In console:

That should work
It will encrypt the input, it will not decrypt the string in the database

Image from Wikimedia, assumed allowed under Fair Use. Image from the Ambrosian Iliad, a 5th century manuscript of the Iliad.

Code Academy Week 5 Notes

2012-02-07_08.32.40
He went over SQL in Ruby/Rails
Team has many players, Player belongs to Team

User story:
As a user, I want to see a list of products I can buy
A product has a name, color, and price. A product belongs to a single brand.
Prices are always in exact dollar amounts (no cents).
As a user, I want to add a review to a product
A review has a rating from 1-5 and a brief description

new rails app
products and brands
products belong to brand, brand has many products
Generate scaffold for brand and product
go back to index after create

Go over the scaffold
To get the brand in the collection select
Go to the form partial for the product
Only change the number field, not the label field
brand_id is the foreign key

:id is param for Brand.all, :name is the field in the brand. That is what will be displayed
You may not want to always do Brand.all. We will go over that later.
View should not decide what data to show.
Put a variable in the new method in the controller

Now listing the products, we still get the brand ID

Make the description for a form a text field, not string

For rating, we want a list of  to 5

You should still add a validates method in the model
What if you want 1 to 100?
There is a way to do a range

to_a converts it to an array
Make the description box smaller. Go to the form partial
:rows => 5

Gems:
You can have more than one version

You may see:

That will install it with admin rights
With rvm: never use sudo
It will install latest by default
gem will handle dependencies
railties is the guts/engines of rails
You can call
gem sources
to see where it will look for gems

Vince’s app:
We could edit the Gemfile

Then run

Back to Jeff
How to get words to appear on pull-down
Numbers:

Or

or

To validate that the rating will be between 1 and 5
Jeff starts with the guides
Jeff used

Test in the Rails console

2012-02-09_08.25.05
To support 1 URL: pages/social
One way:

rails new friendBC
cd friendBC

-> Memorize the routes for resources
in routes.rb
get “pages/social”
in app/controllers add a controller: PagesController < ApplicationController
add a method called “social”
add app/views/pages/social.html.erb
get an image, put it in

in assets/global directory
Make the background grey
app/assets/stylesheets/application.css

How to get JSON data?
He put some stuff in his controller

Put result in view file
In hashes, symbols and strings are not interchangeable. Usually they are.
To get the image:
in the view:

Now he is calling @result @channel

Now Jeff is going through it
Agile practices: single responsibility, clear intention, DRY
These are the top 3
Rails cries out to help you do those things
When you download someone else’s code, you may need to run “bundle install”
Jeff moved some of the HTML onto a partial
Then change the variable in partial to one called “channel”
Then in the view call

In the partial, do not use raw “a” and “img” tags

Now add the image:

Now back in view, we call the render three times. What if we pull another channel, we will have to add another line.
So in controller, create an array

In the view:

Now they do not need to be instance variables in the controller
We still have repetition

Then in other method:

This is Ruby skillz

A good pattern to know:
An array of strings. You are transforming the array into another array.

map is like each
Look it up
collect is another good one to look up.

Could be

We saw one-line blocks in scaffolds in index

Look in the dev/tth/shop folder
—————————————————–
Now: git and github
Look up “git – the simple guide”

makes a new repository

to checkout a repository
Workflow:
working dir has files, index to stage commits, the head is the last commit
adding and committing

Now it is in the head, but not remote

afterwards, you can just do git push
To add a branch

to reset:

gitk – is a good GUI
Neal making live changes

He is on master branch

git status now tells him he made a change

or just

There is also heroku

or

Heroku requires postgres

Neal makes a new app

It would be nice to stop an existing rails server
You could also specify a port

It is now live on our local machine

go to github.com
make a new repository

No good

Now put it up to heroku

ssh keys are a pain

They have different stacks. bamboo is the current stack, good for rails up to 3.0. For rails 3.1 use cedar
Now push it to heroku
Update the gem file Gemfile to add postgres

Put sqlite3 in group :development
bundle install
now commit changes to git

Now push to heroku

another command: heroku open
assets, like images, there could be some problems
another command is heroku logs
or

it’s like an irb for heroku

in file app/config/environments/production.rb

You can go to gitref.org
————————————————————–
Working with Shop app:
Get the average of reviews for a product

Calling product.reviews: It gets rows from our table. It looks like an array, and behave like an array, but it can do more than what an array can do. It returns a proxy class. It is a proxy for the data you want.
So you can say p.reviews.count – it makes an SQL statement
You can do a lot of array stuff: p.reviews.first, p.reviews.sum(“rating”)
Arrays do not have sum method, but ActiveRecord does have sum method
p.reviews.average(“rating”) it gives us a BigDecimal instance
p.reviews.average(“rating”).to_s

Another association concept
A brand has many products.
A product has many reviews.
A brand has many products throught its products.

The lines must be in that order
Review does not have brand id, but product has brand id, and review has product ID
So you can just do Brand.reviews without looping
Users want to see average rating for brand
So in brand show page – put it there for each brand
So to brand index page:

Rating:

For reviewing the product form, it would be great if it knew which product you were using
No params hash for /reviews/new
Put a placeholder in the route
Put it in URL via ?key=value
Now you have a params hash
In product/show.html.erb

So now you see ?product_id=1 in url for new form
so in controller, look at new action in review controller

so in reviews/new.html.erb
New review for

Next: Leave out the pull-down form. But get product ID
replace collection_select with a hidden field

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

Code Academy Week 4 Notes

I only seem to have notes for the second day of week 4.

2012-02-02 Notes

Scaffolding notes:
respond_to
partials: Like a server side include

Look up respond_to method

JSON only:

You could use curl as well.

Try getting a png:

I did not know there was a code 406.

There is a method called responds_with :html, :json, :xml
Not used too often.  That was intended for all actions, but people did not want universal responders.

Scaffold does not provide any security out of the box.

New action also has a block to send json back
526  curl -v “http://localhost:3000/runners/new.json” -H “Accept: application/json”
returns

This could help other developers know what data fields your classes have

The create action has an if block in the respond_to call to handle both a successful and unsuccessful creation.

In Ruby 1.9, you can use a new syntax for hashes

You could also do it like JSON

You can only use the colon for keys if your key is a symbol.
So if you mix key types like in hash i, things get a bit ocnfusing. Your value can be a symbol, but that colon must still be on the left.

Assigment: look at the destroy. What is head :no_content about?

Memorize the RESTful Design chart with the routes, URLs, actions, etc

Let’s look at new and edit
TextMate tip: could go to the drawer. There is another way to get there. Command-T pops up a window, type in the name of your file. You can type something in the middle.
Look at the “new.html.erb” page. Where is the form?
Look at the “edit.html.erb” page. Where is the form?
We see this in each file:

There is a file app/views/runners/_form.html.erb
Partials begin with underscores.
You just use the render method.
You can use instance variables in the partial.

From index.html, you could take this and put it in a partial:

into a file called _list_of_runners.html.erb
and replace it with

It makes the index.html clearer, but clutters up the directory.

Back to associations:
One-to-Many
One movie has many actors:

User stories:
As a user, I want to see the list of teams in our softball league.
A team has a company name and a nickname.
As a user, I want to select a team, and see the list of players on the team.
A player has a name and a jersey number.

What about many-to-many?
Actors are in many movies, and movies have many actors.
There is the notion of a “Role” in between Movie and Actor. That joins them together.
Movie <-> Role <-> Actor
Movie has many roles, and an Actor can have many roles
Roles would have id, movie_id and actor_id

    belongs_to :movie

    belongs_to :actor
end

 

 

User <-> Review <-> Landmark

You just generate a model for a role
rails g scaffold Movie title:string year:integer
rails g scaffold Actor name:string
rails g model role movie_id: integer actor_id:integer character:string
Add the has_many and belongs_to statements

IN the console:
the hard way

Another way to create a role

Some stuff on migrations and controller filters
What about the salary for the role?
You cannot put it in the old migration file and re-run that
The timestamps are on there for a reason

You need to create a new migration for the new field
rails generate migration $NAME $FIELD:$TYPE
rails generate migration AddSalaryToRole salary:integer
It might generate the right thing. You would need this:

Then type rake db:migrate to make changes
rake db:version

Controller filters:
In the controller, we do

quite a few times. (This would be better for something that is multiple lines.)
Make a method
def find_the_movie
It might generate the right thing.
end
You can call that when you need to
But there is still some repetition
If you want to call a method at the beginning of an action or method, that is a before filter
Put this at the top:

So even though destroy action has @movie in the first line, you won’t get an error since you get @movie from the filter
But index method does not get params[:id]. You will get an error
So how to run it only for certain actions

or to exclude some methods

DRY-ing code:
partials in views, pull them in with renders
controllers: use filters to extract common code

You can make your db lookups faster with indexes:

You can put these in a migration
You probably want this for foreign keys

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

Code Academy Week 3 Notes Post 02

2012-01-26_08.08.55 notes
Web requests: URL, method, format
In the routes.rb file, you can have the same URL, but different methods

If you are having trouble naming controllers, go into the Rails console, call the “pluarlize” or “singularize” methods. This will give you the Rails conventions.

In browsers, when you type something in the address bar it will automatically be an HTTP get request

Hashes

Rails forms will have hashes and sub-hashes

3 parts to HTTP request: URL, method and format
The R is resources
Stop thinking pages, start thinking resources

1. web request
params hash contains the data
2. Rails App

3. Web response

Forms in Rails
use the form_for method.

So you should see params[:station] with :station as a hash in the hash, and containing a key called :name

In the train station app, we could also do
Station.create params[:station]

How to change things in the database?
We use the HTTP method is PUT
We have to name our URLs in the routes.rb file

The form knows to label button “Update Record”
In the rails console, you can call x.new_record?
Rails can support HTTP put method with a “_method” param with a value of “put”

To list methods well:

y puts it in yaml
Cheating:

TO get rid of it:

New is paired up with create, edit paired up with update conceptually, so pair them in your routes.rb file
In the update method of the controller, we could call @station.update_attributes(params[:station])

It is best to use named routes
If there is a URL with multiple HTTP methods, you only need to name them once
In the controllers, you use

If the path is stations:

But what if you need the ID?

You could also do station_path
that will do the relative path
path gives you less data to the client
Only good if you will be in the same domain
Problem if you have a redirect

If you send an ActiveRecord object to a route in a link_to call, you could just send it @the_station instead of @the_station.id
The ID is the only one you could leave off. Everything else must be specified.

We will have a lot of controllers in a web app.
You will be creating, deleting, updating a lot of stuff
You could just do
resources :stations
There will be a cheat sheet for the routes

A lot of people never learn the long way like we did, they just learn the resources :model
Even Hartl does not go over that, which kind of surprises me.

Scaffold:
singular for model, plural for controllers, singular for scaffold
It will make a lot of stuff for you

It creates something for a new station, as well as some edit, destroy, etc

and