• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
A tour on ruby and friends
 

A tour on ruby and friends

on

  • 875 views

 

Statistics

Views

Total Views
875
Views on SlideShare
855
Embed Views
20

Actions

Likes
0
Downloads
4
Comments
0

3 Embeds 20

http://blog.ofpsvr.org 18
http://www.hanrss.com 1
http://ofpsvr.org 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

A tour on ruby and friends A tour on ruby and friends Presentation Transcript

  • a Tour on Ruby and FriendsMinqi Pan (P.S.V.R)
  • “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.
  • Snippet #1. OO # The Greeter classclass Greeter  def initialize(name)    @name = name.capitalize  end   def salute    puts "Hello #{@name}!"  endend # Create a new objectg = Greeter.new("world") 
  • Snippet #2.Everything is an object Applying an action on a number... 5.times do print "We *love* Ruby -- its outrageous!" end
  • Snippet #3. Flexibility Essential parts of Ruby can be removed or redefined, at will... class Numeric   def plus(x)     self.+(x)   end end y = 5.plus 6 # y is now equal to 11
  • 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!@block.call("Jon")# => "Hello, Jon!"
  • 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 Proc.new {|x| closure_value = x}, Proc.new { closure_value }endsetter, getter = create_set_and_get # ie. returns two valuessetter.call(21)getter.call # => 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
  • 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}Proc.new {|arg| print arg}lambda {|arg| print arg}->(arg) {print arg}
  • 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>"
  • 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>"
  • 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
  • Snippet #10. eval (cont.) class BindingTest def initialize(n) @value = n end def getBinding return binding() # using Kernel#binding end end obj1 = BindingTest.new(10) binding1 = obj1.getBinding obj2 = BindingTest.new(“Binding Test”) binding2 = obj2.getBinding puts eval(“@value”, binding1) #=> 10 puts eval(“@value”, binding2) #=> Binding Test puts eval(“@value”) #=> nil
  • I made this!( )Yukihiro Matsumoto
  • “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. ”
  • 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..
  • how to build a blog engine in15 minutes with Ruby on Rails
  • 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
  • “ 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.”
  • How many source code does it take to make rails?
  • 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"
  • 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)
  • railtiesRails internals: application bootup, plugins,generators, and rake tasks.http://rubygems.org/gems/railties
  • 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
  • module Rails autoload :Info, rails/info autoload :InfoController, rails/info_controller class << self def application @@application ||= nil end def initialized? @@initialized || false end ... endend
  • 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
  • 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.
  • activesupportA toolkit of support libraries and Ruby core extensions extractedfrom the Rails framework. Rich support for multibyte strings,internationalization, time zones, and testing.http://rubygems.org/gems/activesupport
  • irb(main):001:0> require active_support/all=> trueirb(main):002:0> person.pluralize=> "people"2.even? # => trueirb(main):004:0> Time.now.in_time_zone(Alaska)=> Sun, 11 Dec 2011 03:17:21 AKST -09:00
  • 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!
  • 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.http://rubygems.org/gems/actionpack
  • module ActionController class Base < Metal abstract! ... endend
  • 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.
  • 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)http://rubygems.org/gems/activerecord
  • module ActiveRecord module Associations # :nodoc: extend ActiveSupport::Concern module ClassMethods def has_many...
  • 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.
  • 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).http://rubygems.org/gems/activeresource
  • 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.
  • models/product.rbclass Product < ActiveResource::Base self.site = "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 @post.product.name %></strong><% end %>
  • 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.
  • Philosophy (cont.)class Person < ActiveResource::Base self.site = "http://api.people.com:3000/"end<->http://api.people.com:3000/people/
  • # Expects a response of # # <person><id type="integer">1</id><attribute1>value1</attribute1><attribute2>..</attribute2></person> # # for GET http://api.people.com:3000/people/1.xml # ryan = Person.find(1)
  • # <person><first>Ryan</first></person>## is submitted as the body on## POST http://api.people.com:3000/people.xml## when save is called on a new Person object. An empty response is# is expected with a Location header value:## Response (201): Location: http://api.people.com:3000/people/2#ryan = Person.new(:first => Ryan)ryan.new? # => trueryan.save # => trueryan.new? # => falseryan.id # => 2
  • 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.
  • class Notifier < ActionMailer::Base delivers_from system@loudthinking.com def welcome(recipient) @recipient = recipient mail(:to => recipient, :subject => "[Signed up] Welcome #{recipient}") endend
  • message = Notifier.welcome # => Returns a Mail::Message objectmessage.deliver # => delivers the email View! Hello there, Mr. <%= @recipient %> Thank you for signing up!
  • and we get...Date: Mon, 25 Jan 2010 22:48:09 +1100From: system@loudthinking.comTo: david@loudthinking.comMessage-ID: <4b5d84f9dd6a5_7380800b81ac29578@void.loudthinking.com.mail>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!
  • 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
  • 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.
  • 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
  • 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
  • Other Web Frameworks of Ruby?
  • Sinatrasmall and flexibleNO MVC"quickly creating web-applications in Ruby withminimal effort." require sinatra get /hi do "Hello World!" end
  • Nitro it does not dictate how a web application should be structured.<select name="day"> <option for="day in 1..31" selected_if="day == Time.now.day">#{day}</option></select> One could use templates with embedded code!
  • CampingCamping is a webapplication frameworkwritten in Ruby whichconsistently stays under4kb - the completesource code can beviewed on a single page.
  • 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;S=IO.read(__FILE__)rescue 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])&&Template.new(f,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||=Mab.new({},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];r=Rack::Response.new(@body,@status,@headers)@cookies._n.each{|k,v|r.set_cookie k,v};r.to_a end;def initialize env,mr=@request=Rack:: Request.new(@env=env);@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;Class.new{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]@r.map{|k|k.urls.map{|x|return(k.method_defined? m)?[k,m,*$~[1..-1]]:[I, r501,m]if p=~/^#{x}/?$/}};[I,r404,p] end;N=H.new{|_,x|x.downcase}.merge!("N"=>(d+),"X"=>([^/]+),"Index"=>);def M;def M;end;constants.map{|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]=~/:/IO.read(a.set:__FILE__,$`)=~/^__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;k.new(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;m=a.shift.new(method(:call),*a,&b)meta_def(:call){|e|m.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
  • == 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
  • Further Researchhttp://www.ruby-lang.org/http://www.rubyonrails.org/http://www.railscasts.com/
  • Thank you!