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/ 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, hashesno 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] Methodseveything 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 flowif/unless, while/until
Strings and Regex"string", %Q{string}, 'string', %q{string}
a=41 ; "The answer is #{a+1}" interpolate an expression. put any ruby expression Match Regexput any where side of the match operand
"fox@berkeley.EDU" =~ /(.*)@(.*)\.edu$/i //ignorecase regex match
/(.*)@(.*)\.edu$/i =~ "fox@berkeley.EDU" $1 = 'fox', $2='berkeley'
Objects5.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.
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
Remove parenthesis if they are not ambiguous
Classesclass 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?
Meta-programming === Reflection
Add method in run time
class Numeric
def euros ; self * 1.292 ; end end
Another cool language feature of Ruby is
respond_to?
...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
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.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? Mechanize: let's you write scripts against a remote webserver.
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 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 freeall?, 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.
Closure in javascript
$ 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!
Other Frameworks:
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
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
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?
Summaryc. 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!
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! |