Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

A tour on ruby and friends


Published on

Published in: Technology
  • Be the first to comment

A tour on ruby and friends

  1. 1. a Tour on Ruby and FriendsMinqi Pan (P.S.V.R)
  2. 2. “A Programmer’s Best Friend”3 Keywords: Dynamic... Ruby executes at runtime many common behaviors that other languages might perform during Reflective... Ruby can observe (do type introspection) and modify its own structure and behavior at runtime. Humanity... Ruby is designed for programmer productivity and fun.
  3. 3. Snippet #1. OO # The Greeter classclass Greeter  def initialize(name)    @name = name.capitalize  end   def salute    puts "Hello #{@name}!"  endend # Create a new objectg ="world") 
  4. 4. Snippet #2.Everything is an object Applying an action on a number... 5.times do print "We *love* Ruby -- its outrageous!" end
  5. 5. Snippet #3. Flexibility Essential parts of Ruby can be removed or redefined, at will... class Numeric   def plus(x)     self.+(x)   end end y = 6 # y is now equal to 11
  6. 6. Snippet #4. closures creating a function together with a referencing environment for the non-local variables of that# In an object instance variable (denoted with @), remembera block.def remember(&a_block) @block = a_blockend# Invoke the above method, giving it a block which takes aname.remember {|name| puts "Hello, #{name}!"}# When the time is right (for the object) -- call theclosure!"Jon")# => "Hello, Jon!"
  7. 7. Snippet #5. closures (cont.) creating a function together with a referencing environment for the non-local variables of thatdef create_set_and_get(initial_value=0) # Note the default value of 0 closure_value = initial_value return {|x| closure_value = x}, { closure_value }endsetter, getter = create_set_and_get # ie. returns two # => 21#You can also use a parameter variable as a binding for the closure.#So the above can be rewritten as...def create_set_and_get(closure_value=0) return proc {|x| closure_value = x } , proc { closure_value }end
  8. 8. Snippet #6. anonymous func 4 ways to create a function (or a subroutine) defined, and possibly called, without being bound to anproc {|arg| print arg} {|arg| print arg}lambda {|arg| print arg}->(arg) {print arg}
  9. 9. Snippet #7. meta-programming writing of programs that write or manipulate other programs (or themselves) as their data... COLORS = { :black => "000", :red => "f00", :green => "0f0", :yellow => "ff0", :blue => "00f", :magenta => "f0f", :cyan => "0ff", :white => "fff" } class String COLORS.each do |color,code| define_method "in_#{color}" do "<span style="color: ##{code}">#{self}</span>" end end end "Hello, World!".in_blue => "<span style="color: #00f">Hello, World!</span>"
  10. 10. Snippet #8. meta-prog (cont) specialising the behaviour of methods called on a specific object... a = foo class << a #opens up a’s singleton class (eigenclass)   def inspect     "bar"   end end a.inspect   # => "bar" a = foo   # new object, new singleton class a.inspect   # => "foo" "Hello, World!".in_blue => "<span style="color: #00f">Hello, World!</span>"
  11. 11. Snippet #9. eval# Defining a class method with instance_evalFixnum.instance_eval { def ten; 10; end }Fixnum.ten #=> 10# Defining an instance method with class_evalFixnum.class_eval { def number; self; end }7.number #=> 7Fixnum.instance_eval treats Fixnum as an instance(an instance of the Class class)Fixnum.class_eval treats Fixnum as a class andexecutes the code in the context of that class
  12. 12. Snippet #10. eval (cont.) class BindingTest def initialize(n) @value = n end def getBinding return binding() # using Kernel#binding end end obj1 = binding1 = obj1.getBinding obj2 =“Binding Test”) binding2 = obj2.getBinding puts eval(“@value”, binding1) #=> 10 puts eval(“@value”, binding2) #=> Binding Test puts eval(“@value”) #=> nil
  13. 13. I made this!( )Yukihiro Matsumoto
  14. 14. “Often people, especially computer engineers, focus on the machines. Theythink, "By doing this, the machine will run faster. By doing this, the machine willrun more effectively. By doing this, the machine will something somethingsomething." They are focusing on machines. But in fact we need to focus onhumans, on how humans care about doing programming or operating theapplication of the machines. We are the masters. They are the slaves. ”
  15. 15. Rails2 Keywords: Convention over Configuration... a developer only needs to specify unconventional aspects of the application. Dont repeat yourself... information is located in a single, unambiguous place..
  16. 16. how to build a blog engine in15 minutes with Ruby on Rails
  17. 17. Rails was created in 2003 byDavid Heinemeier Hansson I made that! In 2005 he was recognized by Google and OReilly with the Hacker of the Year award for his creation of Ruby on Rails. Hansson appeared on the cover of the July 2006 issue of Linux Journal
  18. 18. “ Flexibility is not free. It’s overrated. And if you trade thatflexibility in for some constraints, you get a lot of complexityremoved from the equation, you get a lot of productivity backfrom all the stuff you don’t have to do.”
  19. 19. How many source code does it take to make rails?
  20. 20. 4 lines#!/usr/bin/env rubyif File.exists?(File.join(File.expand_path(../.., __FILE__), .git)) railties_path = File.expand_path(../../railties/lib, __FILE__) $:.unshift(railties_path)endrequire "rails/cli"
  21. 21. It’s dependencies that matter  s.add_dependency(activesupport, version)  s.add_dependency(actionpack, version)  s.add_dependency(activerecord, version)  s.add_dependency(activeresource, version)  s.add_dependency(actionmailer, version)  s.add_dependency(railties, version)  s.add_dependency(bundler, ~> 1.0)
  22. 22. railtiesRails internals: application bootup, plugins,generators, and rake tasks.
  23. 23. require rails/ruby_version_checkrequire pathnamerequire active_supportrequire active_support/core_ext/kernel/reportingrequire active_support/core_ext/array/extract_optionsrequire active_support/core_ext/loggerrequire rails/applicationrequire rails/versionrequire active_support/railtierequire action_dispatch/railtie
  24. 24. module Rails autoload :Info, rails/info autoload :InfoController, rails/info_controller class << self def application @@application ||= nil end def initialized? @@initialized || false end ... endend
  25. 25. module Rails class Application < Engine autoload :Bootstrap, rails/application/bootstrap autoload :Configuration, rails/application/configuration endendmodule Rails module Generators autoload :Actions, rails/generators/actions autoload :ActiveModel, rails/generators/active_model ... endend
  26. 26. RailtiesRailties is responsible for gluing all frameworks together.Overall, it:* handles the bootstrapping process for a Rails application;* manages the +rails+ command line interface;* and provides Rails generators core.
  27. 27. activesupportA toolkit of support libraries and Ruby core extensions extractedfrom the Rails framework. Rich support for multibyte strings,internationalization, time zones, and testing.
  28. 28. irb(main):001:0> require active_support/all=> trueirb(main):002:0> person.pluralize=> "people"2.even? # => trueirb(main):004:0>> Sun, 11 Dec 2011 03:17:21 AKST -09:00
  29. 29. activesupportActive Support is a collection of utility classes and standard libraryextensions that were found useful for the Rails framework. These additionsreside in this package so they can be loaded as needed in Ruby projectsoutside of Rails.of great use to ruby learners!
  30. 30. actionpackAction Pack is a framework for handling and responding to webrequests. It provides mechanisms for *routing* (mappingrequest URLs to actions), defining *controllers* that implementactions, and generating responses by rendering *views*, whichare templates of various formats. In short, Action Pack providesthe view and controller layers in the MVC paradigm.
  31. 31. module ActionController class Base < Metal abstract! ... endend
  32. 32. actionpack* Action Dispatch, which parses information about the web request, handles routing as defined by the user, and does advanced processing related to HTTP such as MIME-type negotiation, decoding parameters in POST/PUT bodies, handling HTTP caching logic, cookies and sessions.* Action Controller, which provides a base controller class that can be subclassed to implement filters and actions to handle requests. The result of an action is typically content generated from views.* Action View, which handles view template lookup and rendering, and provides view helpers that assist when building HTML forms, Atom feeds and more. Template formats that Action View handles are ERB (embedded Ruby, typically used to inline short Ruby snippets inside HTML), and XML Builder.
  33. 33. activerecordActive Record connects classes to relational database tables to establish analmost zero-configuration persistence layer for applications. The libraryprovides a base class that, when subclassed, sets up a mapping between the newclass and an existing table in the database. In the context of an application,these classes are commonly referred to as *models*. Models can also beconnected to other models; this is done by defining *associations*.(c.f. mongoid)
  34. 34. module ActiveRecord module Associations # :nodoc: extend ActiveSupport::Concern module ClassMethods def has_many...
  35. 35. activerecord Automated mapping between classes and tables, attributes and columns. Associations between objects defined by simple class methods. Aggregations of value objects. Validation rules that can differ for new or existing objects. Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.). Observers that react to changes in a model. Inheritance hierarchies. Transactions Reflections on columns, associations, and aggregations. Database abstraction through simple adapters. Logging support Database agnostic schema management with Migrations.
  36. 36. activeresourceActive Resource (ARes) connects business objects andRepresentational State Transfer (REST)web services. It implements object-relational mapping for RESTweb services to provide transparentproxying capabilities between a client (ActiveResource) and aRESTful service (which is provided by Simply RESTful routingin ActionController::Resources).
  37. 37. how it worksModel classes are mapped to remote REST resourcesby Active Resource much the same way Active Recordmaps model classes to databasetables. When arequest is made to a remote resource, a REST XMLrequest is generated, transmitted, and the resultreceived and serialized into a usable Ruby object.
  38. 38. models/product.rbclass Product < ActiveResource::Base = "http://localhost:3000"endmodels/post.rbclass Post < ActiveRecord::Base def product @product ||= Product.find(product_id) unless product_id.blank? endendviews/posts/edit.html.erb<p> <%= f.label :product_id %> <%= f.collection_select :product_id, Product.find(:all), :id, :name %></p>views/posts/show.html.erb<% if @post.product %> <strong><%=h %></strong><% end %>
  39. 39. Philosiphy Active Resource attempts to provide a coherent wrapper object-relational mapping for REST web services. It follows the same philosophy as Active Record, in that one of its prime aims is to reduce the amount of code needed to map to these resources. This is made possible by relying on a number of code- and protocol-based conventions that make it easy for Active Resourceto infer complex relations and structures.
  40. 40. Philosophy (cont.)class Person < ActiveResource::Base = ""end<->
  41. 41. # Expects a response of # # <person><id type="integer">1</id><attribute1>value1</attribute1><attribute2>..</attribute2></person> # # for GET # ryan = Person.find(1)
  42. 42. # <person><first>Ryan</first></person>## is submitted as the body on## POST when save is called on a new Person object. An empty response is# is expected with a Location header value:## Response (201): Location: = => Ryan) # => # => # => # => 2
  43. 43. actionmailerAction Mailer is a framework for designing email-service layers.These layers are used to consolidate code for sending outforgotten passwords, welcome wishes on signup, invoices forbilling, and any other use case that requires a written notificationto either a person or another system.
  44. 44. class Notifier < ActionMailer::Base delivers_from def welcome(recipient) @recipient = recipient mail(:to => recipient, :subject => "[Signed up] Welcome #{recipient}") endend
  45. 45. message = Notifier.welcome # => Returns a Mail::Message objectmessage.deliver # => delivers the email View! Hello there, Mr. <%= @recipient %> Thank you for signing up!
  46. 46. and we get...Date: Mon, 25 Jan 2010 22:48:09 +1100From: system@loudthinking.comTo: david@loudthinking.comMessage-ID: <>Subject: [Signed up] Welcome david@loudthinking.comMime-Version: 1.0Content-Type: text/plain; charset="US-ASCII";Content-Transfer-Encoding: 7bitHello there,Mr. david@loudthinking.comThank you for signing up!
  47. 47. why directly calling on the class?module ActionMailer #:nodoc: class Base < AbstractController::Base class << self def method_missing(method, *args) #:nodoc: return super unless respond_to?(method) new(method, *args).message end end endend
  48. 48. Wait! where is activemodel? activerecord relies on this! activepack also relies on this!!! A toolkit for building modeling frameworks like Active Record and Active Resource. Rich support for attributes, callbacks, validations, observers, serialization, internationalization, and testing.
  49. 49. activemodel Used to build mongoid,etc as long as test is passed, free validation,callbacks,etc providedmodule ActiveModel module Lint module Testsdef test_model_naming assert model.class.respond_to?(:model_name), "The model should respond to model_name" model_name = model.class.model_name assert_kind_of String, model_name assert_kind_of String, model_name.human assert_kind_of String, model_name.singular assert_kind_of String, model_name.pluralend...end
  50. 50. all those are free Add attribute magic to objects Callbacks for certain operations Tracking value changes Adding +errors+ interface to objects Model name introspection Observer support Making objects serializable Internationalization (i18n) support Validation support Custom validators
  51. 51. Other Web Frameworks of Ruby?
  52. 52. Sinatrasmall and flexibleNO MVC"quickly creating web-applications in Ruby withminimal effort." require sinatra get /hi do "Hello World!" end
  53. 53. Nitro it does not dictate how a web application should be structured.<select name="day"> <option for="day in 1..31" selected_if="day ==">#{day}</option></select> One could use templates with embedded code!
  54. 54. CampingCamping is a webapplication frameworkwritten in Ruby whichconsistently stays under4kb - the completesource code can beviewed on a single page.
  55. 55. require "uri";require "rack";class Object;def meta_def m,&b;(class<<self;selfend).send:define_method,m,&b end end;module Camping;C=self; nil;P="<h1>Camping Problem!</h1><h2>%s</h2>";U=Rack::Utils;O={};Apps=[]class H<Hash;def method_missing m,*a;m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m.to_s]:super end;undef id,type if ??==63 end;class Cookies<H;attr_accessor :_p;def _n;@n||={}end;alias :_s :[]=;def set k,v,o={};_s(j=k.to_s,v);_n[j]={:value=>v,:path=>_p}.update o;end;def []=(k,v)set(k,v,v.is_a?(Hash)?v:{})endend;module Helpers;def R c,*g;p,h=/(.+?)/,g.grep(Hash);g-=h;raise"bad route"unless u=c.urls.find{|x|break x ifx.scan(p).size==g.size&&/^#{x}/?$/=~(x=g.inject(x){|x,a|x.sub p,U.escape((a.to_param rescue a))}.gsub(/(.)/){$1})};h.any?? u+"?"+U.build_query(h[0]):uend;def / p;p[0]==?/?@root+p :p end;def URL c=/,*a;c=R(c,*a) if c.respond_to?(:urls);c=self/c;c=@request.url[/.{8,}?(?=/|$)/]+c if c[0]==?/;URI c end endmodule Base;attr_accessor:env,:request,:root,:input,:cookies,:state,:status,:headers,:body;T={};L=:layout;def lookup n;T.fetch(n.to_sym){|k|t=Views.method_defined?(k)||(t=O[:_t].keys.grep(/^#{n}./)[0]and Template[t].new{O[:_t][t]})||(f=Dir[[O[:views]||"views","#{n}.*"]*/][0])&&,O[f[/.(w+)$/,1].to_sym]||{});O[:dynamic_templates]?t:T[k]=t} enddef render v,*a,&b;if t=lookup(v);r,@_r=@_r,o=Hash===a[-1]?a.pop: {};s=(t==true)?mab{send v,*a,&b}: t.render(self,o[:locals]||{},&b);s=render(L,o.merge(L=>false)){s}if o[L]or o[L].nil?&&lookup(L)&&!r&&v.to_s[0]!=?_;s;else;raise"no template: #{v}"end;end;def mab &b;(@mab||{},self)).capture(&b) end;def r s,b,h={};b,h=h,b if Hash===b;@status=s;@headers.merge!(h);@body=b end;def redirect *a;r 302,,Location=>URL(*a).to_s end;def r404 p;P%"#{p} not found"end;def r500 k,m,eraise e end;def r501 m;P%"#{m.upcase} not implemented"end;def serve(p,c)(t=Rack::Mime.mime_type p[/..*$/],nil)&&@headers["Content-Type"]=t;c;end;def to_a;@env[rack.session]=Hash[@state];,@status,@headers)@cookies._n.each{|k,v|r.set_cookie k,v};r.to_a end;def initialize env,mr=@request=Rack::;@root,@input,@cookies,@state,@headers,@status,@method=r.script_name.sub(//$/,),n(r.params),Cookies[r.cookies],H[r.session.to_hash],{},m=~/r(d+)/?$1.to_i: 200,m;@cookies._p=self/"/" enddef n h;Hash===h ?h.inject(H[]){|m,(k,v)|m[k]=n(v);m}: h end;def service *a;r=catch(:halt){send(@method,*a)};@body||=r;selfend end;module Controllers;@r=[];class<<self;def R *u;r=@r;{meta_def(:urls){u};meta_def(:inherited){|x|r<<x}}end;def D p,m,e;p=/if!p||!p[0];(a=O[:_t].find{|n,_|n==p}) and return [I,:serve,*a]{|k|{|x|return(k.method_defined? m)?[k,m,*$~[1..-1]]:[I, r501,m]if p=~/^#{x}/?$/}};[I,r404,p] end;{|_,x|x.downcase}.merge!("N"=>(d+),"X"=>([^/]+),"Index"=>);def M;def M;end;{|c|k=const_get(c);k.send:include,C,X,Base,Helpers,Models@r=[k]+@r if @r-[k]==@r;k.meta_def(:urls){["/#{c.to_s.scan(/.[^A-Z]*/).map(&N.method(:[]))*/}"]}if !k.respond_to?:urls}end end;I=R()end;X=Controllers;class<<self;defgoes m;Apps<<a=eval(S.gsub(/Camping/,m.to_s),TOPLEVEL_BINDING);caller[0]=~/:/,$`)=~/^__END__/&&(b=$.split /^@@s*(.+?)s*r?n/m).shift rescue nila.set :_t,H[*b||[]];end;def call e;X.Mp=e[PATH_INFO]=U.unescape(e[PATH_INFO]);k,m,*a=X.D p,e[REQUEST_METHOD].downcase,e;,m).service(*a).to_a;rescue;r500(:I,k,m,$!,:env=>e).to_a enddef method_missing m,c,*a;X.M;h=Hash===a[-1]?a.pop: {};e=H[Rack::MockRequest.env_for(,h.delete(:env)||{})];k=X.const_get(c).new(e,m.to_s);h.each{|i,v|k.send"#{i}=",v};k.service(*a) end;def use*a,&b;,*a,&b)meta_def(:call){|e|}end;def options;O end;def set k,v;O[k]=v end endmodule Views;include X,Helpers end;module Models;autoload:Base,camping/arHelpers.send:include,X,self end;autoload:Mab,camping/mabautoload:Template,camping/template;C end
  56. 56. == A Camping Skeleton module Blog::Views def layoutA skeletal Camping blog could look like this: html do require camping head { title "My Blog" } body do Camping.goes :Blog h1 "My Blog" module Blog::Models self << yield class Post < Base; belongs_to :user; end end class Comment < Base; belongs_to :user; end end class User < Base; end end end module Blog::Controllers def index class Index @posts.each do |post| def get @posts = Post.find :all h1 post.title render :index end end end end end end
  57. 57. Further Research
  58. 58. Thank you!