cs169


http://ruby.about.com/od/urlshort/ss/Creating-A-Url-Shortener-In-Rails.htm
http://fabianosoriani.wordpress.com/2011/09/11/when-to-ruby-on-rails-when-to-node-js/
http://www.quora.com/Node-js/Will-Nodejs-overtake-Ruby-on-Rails-and-other-web-development-options-in-future

“One reason was scale. The second is, if you look at Node, the thing it’s best at doing is talking to other services. The mobile app has to talk to our platform API and database. We’re not doing massive data analytics. Node showed us huge performance gains compared to what we were using before, which was Ruby on Rails.”

The improvements the team saw were staggering. They went from running 15 servers with 15 instances (virtual servers) on each physical machine, to just four instances that can handle double the traffic. The capacity estimate is based on load testing the team has done.


http://beta.saasbook.info/bookware-vm-instructions      http://beta.saasbook.info/students

beginner http://tryruby.org/levels/4/challenges/2     http://www.codecademy.com/tracks/ruby   
advanced https://rubymonk.com/   http://www.rubykoans.com/     http://ruby-doc.org/


dynamically typed - Objects have types but variables don't
add modify code at run time
 reflection

class is uppercase camel case
class FriendFinder ... end
methods and variables are snake
def learn_conventions ... end
def faculty_member? ... end           # returns T/F
def charge_credit_card! ... end       #dangerous method, might have side effects, be careful

CONSTANTS (scoped) & $GLOBALS (not scoped) 
TEST_MODE = true $TEST_MODE = true

Variables, Arrays, hashes

no declarations. nill until defined
array
[1, "two", :three]    subscripts are zero based
hash
w = {'a'=>1, :b=>[2, 3]}
w[:b][0] == 2
w.keys == ['a', :b]

Methods

eveything except integers are pass-by-references
def foo(x, y) return x+y  end
def foo(x, y = 0) return x+y  end   #can be called with one param

def foo(x, y=0) return [x , y+1]  end
a, b = foo(6)  # a=6, b = 7

Write Clean code

✔ raise("Boom!") unless              ✖ raise("Boom!")     # thisis a complete statement by itself, interpreter will not look for next line
   ship_stable                                  unless (ship_stable)

Control flow

if/unless, while/until
 1.upto(10)  do |i|  ... end
10.times do ... end
collection.each do |elt|  ... end
 Iterations, Objects that control their own traversal

Strings and Regex

"string",     %Q{string},           'string',          %q{string}

a=41 ; "The answer is #{a+1}"           interpolate an expression. put any ruby expression

Match Regex

put any where side of the match operand
"fox@berkeley.EDU" =~ /(.*)@(.*)\.edu$/i              //ignorecase regex match
 /(.*)@(.*)\.edu$/i =~ "fox@berkeley.EDU"
$1 = 'fox', $2='berkeley'

Objects

5.methods
nil.respond_to? (:to_s)

All of these really can be thought of as syntactic sugar around a single construct which is the send method. It's a language primitive. That's the one that says, “ Take the following method call and send it to the object.” We say that the object is the receiver in that case.

 method call
 equivalent
 1 + 2
 1.send(:+, 2)              //plus is the message and there is one argument for that message
 my_array[1]  my_array.send(:[], 1)
 my_array[3] = "foo"  my_array.send(:[]=, 3,"foo")
 if(x==3)  if(x.send(:==, 3))
 my_function(z)  self.send(:my_function, z)

Remember

a.b means: call method b on object a   (a is the receiver to which you send the method call, assuming a will respond to that method")
✖  does not mean: a is some kind of data structure that has b as a membe

Poetry Mode

Remove parenthesis if they are not ambiguous
 redirect_to login_page and return unless logged_in?  redirect_to(login_page) and return() unless logged_in?
 a should be >= 7
 a.should(be() >= 7)
 link_to    :controller => user, :action => show
  link_to(   { :controller => user, :action => show})

Classes

class SavingsAccount <= Account
# constructor called when SavingsAccount.new called (but the constructor itself in the class is called initialize)
def initialize(balance=0)   # default value 0
@balance = balance    #note instance vs local variable
end
def balance            # accessor
@balance    # in ruby the last value is always returned
end
def balance=(new_amount)    # setter with equal sign. you need to explicitly define getters  and setters
@balance=new_amount
end
def deposit(amount)
@balance += amount
end
@@bank_name = "MyBank"    # class variable with @@  (static)
def self.bank_name         # self specifies it is a class method    OR def SavingsAccount.bank_name @@bank_name end
@@bank_name
end
end         # you can't directly access myaccnt.@balance    ..........  there is no method name called @balance! :)

armando = Account.new(1000)


generate getter and setter with attr_accessor macro (not part of language).
attr_accessor is just a plain old method that uses metaprogramming...not part of the language!"
IF YOU CAN PRINT IT AT RUN TIME, YOU CAN EXECUTE IT AT RUN TIME.

Except some, all methods return a new copy of the object. except . This is functionally flavored, from the functional programming community.

Add methods to current classes!
class String 
   def curvy?   
        !("AEFHIKLMNTVWXYZ".include?(self.upcase)) 
    end
end

"foo".curvy?

Everything is an object, Everything is a method call


Meta-programming === Reflection
Add method in run time
class Numeric
  def euros ; self * 1.292 ; end
end

  1. class Numeric
  2.   def method_missing(method_id,*args,&block)  # capture all args in case need to call super
  3.     if method_id.to_s == 'euro'
  4.       self.send('euros')
  5.     else
  6.       super # You *must* call super if you don't handle the method, otherwise you'll mess up Ruby's method  lookup.
  7.     end
  8.   end

  9.     
          def respond_to?(meth)
            if meth.to_s =~ /euro/
              true
            else
              super
            end
          end
        
  10. end

Another cool language feature of Ruby is method_missing. It’s the feature that puts the magic in Rails’s find_by_* methods. You’ve probably seen them in examples before, but in case you haven’t, they look like this:

    Post.find_by_title("Awesomeness!")
    User.find_by_email("bob@example.com")
    User.find_by_email_and_login("bob@example.com", "bob")
you should also define a corresponding respond_to?

  1. class Numeric   # handle other currencies with a hashmap of currency name to conversion rate
  2.   @@currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019}
  3.   def method_missing(method_id, *args, &block)  # capture all args in case have to call super
  4.     singular_currency = method_id.to_s.gsub( /s$/, '')   #ignore last s (plural s)
  5.     if @@currencies.has_key?(singular_currency)
  6.       self * @@currencies[singular_currency]
  7.     else
  8.       super
  9.     end
  10.   end
  11. end

 ...so can have code that writes code (metaprogramming)"

class name . method missing is a class method
class name # method missing is a instance method.

Suppose we want to handle
 5.euros.in(:rupees)

What change to Numeric would be most appropriate?"
☐"Change Numeric.method_missing
to detect calls to 'in' with appropriate args"
☐ Change Numeric#method_missing to detect calls to 'in' with appropriate args
☐ Define the method Numeric#in ☐ Define the method Numeric.in


Use the simplest method that works, if a simple string takes care of that  just because you have these powerful mechanisms available doesn't mean you always     have to use them. In fact, you should do the simplest thing that     could possibly work. Remember, that's one of the mottos of     extreme programming. And in this case, a plain old instance     method will do absolutely fine. Any questions about that before     we move on? 



Blocks, Iterators, Functional Idioms

["apple", "banana", "cherry"].each do |string|                        # it is not for loop, it is each. With each element of collection do something
  puts string
end

for i in (1..10) do
  puts i
end

1.upto 10 do |num|    # a method call on numeric that takes an argument (10) followed by a block. A block is just a lambda expression, it is a procedure that has no names, in this case it is a procedure of one argument (num), and what it does it just prints that num. 
  puts num
end

3.times {  print "Rah, " }           # replace braces for do and end.            ============= 3.times do  print "Rah, " end




  • Iterators let objects manage their own traversal

  •  (1..10).each do |x| ... end

    (1..10).each { |x| ... } 1.upto(10) do |x| ... end => range traversal"

  •  my_array.each do |elt| ... end => array traversal"

  •  hsh.each_key do |key| ... end                         hsh.each_pair do |key,val| ... end

  • => hash traversal"

  •  10.times {...} # => iterator of arity zero

  •  10.times do ... end


Expression Orientation

You don't think in terms of, “ I'm going to do something to this collection.” Instead you think in terms of, “ Hey collection, I'm going to ask you for things and I'm going to do things to your elements.” For example, I can have a collection x which is just an array of strings and I can say, “ Sort yourself.” I can say, “ Take your unique elements.”

it returns a copy. X is not modified here, no x's have been harmed in the preparation of any of these examples.

x = ['apple','cherry','apple','banana']
x.
sort # => ['apple','apple','banana','cherry']            x.uniq.reverse # => ['banana','cherry','apple']             x.reverse! # => modifies x


x.map do |fruit|                     # result of overal map is a new collection in which each element is the result of calling the anonymous lambda.
       fruit.reverse
end.sort                # => ['ananab','elppa','elppa','yrrehc']

x.collect { |f| f.include?("e") }     # filter and return items of the collection that satisfy condition
x.any? { |f| f.length > 5 }    # does any of the items satisfy the condition?
Example
Mechanize: let's you write scripts against a remote webserver.

  1. require 'mechanize'
  2.  
  3. def get_clipper_value()
  4.   # local variables
  5.   url = 'https://clippercard.com/ClipperWeb/login.do'
  6.   username = 'xxx@xxx.com'
  7.   password = 'xxx'
  8.   # notice method chaining:
  9.   amount =
  10.     Mechanize.new.
  11.     # note passing of hash argument
  12.     post(url, :username => username, :password => password).
  13.     # not use of regular expression as hash value
  14.     link_with(:href => /cardValue/i).
  15.     click.
  16.     parser.xpath("//tr/td[contains(.,'Clipper Cash')]").first.
  17.     next_sibling.next_sibling.
  18.     content.match(/\$(\d+\.\d+)/)
  19.   html($1)
  20. end


Mixins and Duck Typing

Ruby emphasises what do you do, what methods do you respond to instead of what class are you.

If it responds to the same methods as a duck...it might as well be a duck"
Similar to Java Interfaces but easier to use"

  my_list.sort [5, 4, 3].sort
  ["dog", "cat", "rat"].sort
  [:a, :b, :c].sort
  IO.readlines("my_file").sort   # sort file line by line

Module

A collection of method that is not a class (is not instantiable)
Important use of modules: mix its methods into a class: 

class A ; include MyModule ; end
–  A.foo will search A, then MyModule, then
method_missing in A & B, then A's ancestor"
–  sort is actually defined in module Enumerable,"   which is mixed into Array by default"
can be mixed into any class that knows how to enumerate the elements of itself.

A mix-in is like a contract: e.g if you agree to implement each, Enumerable will give you these methods for free
all?, any?, collect, find, include?, inject, map, partition, ....
So, if you have a colection that corresponds to each, you get the above and furthermore if elements corespond to <=> (a <=> b is -1 if a<b, 0 if a=b and +1 if a>b) then you have to do zero work for that thing to be sorted.

Another module comparable says if you impelement <=> and you mixin me I give you below
< <= => > == between?

SO: The class of objects doesn't matter, only the methods it corresponds to!


Example: Sorting a file:
–  File.open returns an IO object
–  IO objects respond to each by returning each line as a String
•  So we can say
File.open('filename.txt').sort –  relies on IO#each and String#<=>
•  Which lines of file begin with vowel?"
  File.open('file').select { |s| s =~ /^[aeiou]/i }

You don't want to reuse implementation, you want to reuse behavior

each is a promis tgat I can manage to traverse my data myself.
times: repeat a block that many times

yield: transfer control back to the thing called me, because it has a block waiting for me.
So, when we call each and the argument of it is a block, the block is what's gonna get called with the argument of yield.
  1. class RandomSequence
  2.   def initialize(limit,num)
  3.     @limit,@num = limit,num
  4.   end
  5.   def each
  6.     @num.times { yield (rand * @limit).floor }
  7.   end
  8. end
  9.  
  10. i=-1
  11. n = RandomSequence.new(10,4).each do |num|
  12.   i = num if i < num          # this block is called when yield is called with yield's argument as argument here
  13. end

 # in File class
def open(filename)
  ...open a file...
end
def close
  ...close a file...
end
# in your code
def do_everything
  f = File.open("foo")
  my_custom_stuff(f)
  f.close()
end

Without yield(): expose 2 calls in other library"
 # in some other library
def open(filename)
  ...before code...
  yield file_descriptor
  ...after code...
end
# in your code
def do_everything
  File.open("foo") do |f|
    my_custom_stuff(f)
  end
end
With yield(): expose 1 call in other library"


Closure in javascript
// Return a list of all books with at least 'threshold' copies sold.
function bestSellingBooks(threshold) {
  return bookList.filter(
      function (book) { return book.sales >= threshold; }
    );
}

BDD & TDD

behavior driven design and test driven design

  1. require 'dessert'
  2. require 'debugger'
  3.  
  4. describe Dessert do
  5.   describe 'cake' do
  6.     subject { Dessert.new('cake', 400) }
  7.     its(:calories) { should == 400 }
  8.     its(:name)     { should == 'cake' }
  9.     it { should be_delicious }
  10.     it { should_not be_healthy }
  11.   end
  12.   describe 'apple' do
  13.     subject { Dessert.new('apple', 75) }
  14.     it { should be_delicious }
  15.     it { should be_healthy }
  16.   end
  17.   describe 'can set' do
  18.     before(:each) { @dessert = Dessert.new('xxx', 0) }
  19.     it 'calories' do
  20.       @dessert.calories = 80
  21.       @dessert.calories.should == 80
  22.     end
  23.     it 'name' do
  24.       @dessert.name = 'ice cream'
  25.       @dessert.name.should == 'ice cream'
  26.     end
  27.   end
  28. end

autotest


$ nc -l 8000
in browser go to http://localhost:8000

in terminal type hello world , Ctrl-C and browser shows response.

------------
presentatin tier is the first point client sees from server: e.g. apache web server/microsoft iis/webrick
logic tier: Rack+Rails
persistense layer: relational datasbe


MVC: Each entity has a model, controller, & set of views!
 Controller:
    To view: User actions
                  directives for rendering data
    To Model: Read/update data
     dat provided from model to view through controller
 one conroller might communicate with ther controllers to fulfill a task
 
 

Other Frameworks:
 Page controller:
every page a user could view has a controller associates with it.
for an app that does a few simple fixed actions. if your web app is like this, this might be easier design.
 One master dispatecher that everything comes through
a central point that is the app file itself.
 php an example for pure temlate view application. there are different models, but there is just a collection of views, that gets inter spersed with that model. So the relationship is between a bunch of models and a bunch of views.
 
 
 


Basic Operations on Objects: CRUD (create, remove, update, delete)
Active Record: everymodel knows how to CRUD itself, using common mechanisms
Unlike e.g. php where there is an object that does the querying and getting the results
 Unlike Data Mapper model (e.g. used on Google app engine)
Data Mapper associates separate mapper with each model!
– Idea: keep mapping independent of particular data store used => works with more types of databases!
– Con: can’t exploit
 RDBMS features to
 simplify complex
 queries & relationships
keep mapping strategy independent pf type of storage
 
For MongoDB you CAN NOT use active record, because it relies heavily on relational data model. You'd have ti use data mapper.
Most SaaS apps today they do not use Active Record. they use something like data mapper.



Rest:
What design decisions would allow our app to support Service- Oriented Architecture?!
What are poor design decsisions that would make it difficult for an app to participate in a service oriented architecture.
Rest: Representational State Transfer
☐ A resource may be existing content or a request to modify something.! a resource could be a list of movies
☐ In an MVC app, every route must eventually trigger a controller action. !
☐ One common set of RESTful actions is the CRUD actions on models. !




template views, a way we can handle views in an MVC app
template view pattern basically you have a view that consists of a certain amount of fixed markup, stuff that does not change, no matter what the request is and then at runtime you interpolate selective data into that view template.
e.g. a generic template for displaying a movie
at run time whichever movie is selected will fill out the information


Template View pattern!
• View consists of markup with selected interpolation to happen at runtime!
– Usually, values of variables or result of evaluating short bits of code!
• In Elder Days, this was the app (e.g. PHP)! • Alternative: Transform View !


We use Haml
alternaive is erb
alternative is directly passing out json/xml as response



Haml

html tags specified by %
indentation specifies scope
for CSS, # specifies id and . specifies class

%h1.pagename All Movies                 class
%table#movies                                     id
%thead %tr
      %th Movie Title
      %th Release Date
      %th More Info
%tbody
    - @movies.each do |movie|                     execute this code
%tr
%td= movie.title                                    substitute value
%td= movie.release_date
%td= link_to "More on #{movie.title}", |                                 for multi-line code
movie_path(movie) |
= link_to 'Add new movie', new_movie_path

erb is like php, all by itself means not to use them!!
the real erason for haml is fewer marks on the page, easier to follow indentation, easier to debug,

in MVC views and controllers should be extremely extremely thin. in MVC everything should be in the model, model centric
So if     you writing control methods, and there are more than like five     or ten lines long, there is a problem right. There is a real     tendency for code to creep into places where it does not belong.     The province of computing interesting things and dealing with     data is the province of the model. So if you find yourself doing     stuff like that in controllers or in views, that should be a     sort of a self check for you to ask why did not I put this in     the model before, why is it in there now?




Summary

c. 2008: “Rails doesn’t scale”!

 Scalability is an architectural concern—not confined to language or framework!
•  The stateless tiers of 3-tier arch do scale!
–  With cloud computing, just worry about constants!
•  Traditional relational databases do not scale!
•  Various solutions combining relational and non- relational storage (“NoSQL”) scale much better!
–  DataMapper works well with some of them!
•  Intelligent use of caching (later in course) can greatly improve the constant factors!

Architecture is about Altenatives


As you work on other SaaS apps beyond this course, you should find yourself considering different architectural choices and questioning the choices being made.

Model-view-controller is a well known architectural pattern for structuring apps!
•  Rails codifies SaaS app structure as MVC!
•  Views are Haml w/embedded Ruby code, transformed to HTML when sent to browser!
•  Models are stored in tables of a relational database, accessed using ActiveRecord!
•  Controllers tie views and models together via routes and code in controller methods!













Comments