SlideShare ist ein Scribd-Unternehmen logo
1 von 80
Ruby Programming
    Language
About Me
> 8 years of developing experience

retail, e-commerce, logistics,
fashion, multi-media, etc.

lead developer, team leader,
project manager, functional
analysts, architect.

a runner and a mountain lover



             elimi
  @I   ndritS
Why Ruby
Everything is an Object
Dynamic typing
Open
Mix-ins
Functional support
Methods vs Keywords
(Meta)programming
‘Scripting’ support
LBNL: Testing
Everything is
  an object
Classical
                            class MyClass
                              def method
                                @v = 1
                              end
                            end

          Object                                 Class
                 Instance       class       MyClass

                @v = 1                  method()

Code:
        obj = MyClass.new
        obj.methods == MyClass.instance_methods # => true
        obj.methods != MyClass.methods # => true
Everything is an Object

                         superclass
               Object                 Module

inst   class       superclass             superclass


                           class
               MyClass                Class
                                           class
Classes
Code:
class Cls < Array
  def sum
    inject{ |sum, element| sum + element}

  end
end
Classes
Code:
class Cls < Array                                 Cls = Class.new(Array) do
  def sum                                           def sum
    inject{ |sum, element| sum + element}             inject{|sum, element| sum + element}

  end                                               end
end                                               end
Classes
Code:
class Cls < Array                                 Cls = Class.new(Array) do
  def sum                                           def sum
    inject{ |sum, element| sum + element}             inject{|sum, element| sum + element}

  end                                               end
end                                               end
Classes
Code:
class Cls < Array                                      Cls = Class.new(Array) do
  def sum                                                def sum
    inject{ |sum, element| sum + element}                   inject{|sum, element| sum + element}

  end                                                    end
end                                                    end




                                Classes are nothing but objects,
                            class names are nothing but constants.
Classes
Code:
class Cls < Array                                      Cls = Class.new(Array) do
  def sum                                                def sum
    inject{ |sum, element| sum + element}                   inject{|sum, element| sum + element}

  end                                                    end
end                                                    end




           !                    Classes are nothing but objects,
                            class names are nothing but constants.
Dynamic Typing
Dynamic Typing
Code:
        class CreditCard
          def pay; #credit code; end
        end

        class Cod
          def pay; #cod code; end
        end

        class WireTransfer
          def pay; #wrt code; end
        end

        def process(payment)
          ...
          payment.pay
          ...
        end
Ruby is an open
language by design
Class Opening
Code:
Class Opening
Code:
  3.times do
    class Cls
      puts “Hi”
    end
  end
Class Opening
Code:
  3.times do
    class Cls
      puts “Hi”
    end
  end




  => Hi
     Hi
     Hi
Class Opening
Code:
  3.times do      def Cls.hi
    class Cls       puts “Hi Class”
      puts “Hi”   end
    end
  end




  => Hi
     Hi
     Hi
Class Opening
Code:
  3.times do      def Cls.hi
    class Cls       puts “Hi Class”
      puts “Hi”   end
    end
  end




  => Hi           Cls.hi #=> Hi
     Hi
     Hi
Class Opening
Code:
                  def Cls.hi          obj1 = Cls.new
  3.times do
                    puts “Hi Class”   obj2 = Cls.new
    class Cls
      puts “Hi”   end
                                      def obj1.hi
    end
                                          puts “Hi”
  end
                                      end




  => Hi           Cls.hi #=> Hi
     Hi
     Hi
Class Opening
Code:
                  def Cls.hi          obj1 = Cls.new
  3.times do
                    puts “Hi Class”   obj2 = Cls.new
    class Cls
      puts “Hi”   end
                                      def obj1.hi
    end
                                          puts “Hi”
  end
                                      end




  => Hi           Cls.hi #=> Hi       obj1.hi # => Hi
     Hi
     Hi
Class Opening
Code:
                  def Cls.hi          obj1 = Cls.new
  3.times do
                    puts “Hi Class”   obj2 = Cls.new
    class Cls
      puts “Hi”   end
                                      def obj1.hi
    end
                                          puts “Hi”
  end
                                      end




  => Hi           Cls.hi #=> Hi       obj1.hi # => Hi
     Hi                               obj2.hi # =>
     Hi                               NoMethodError
Mixins
Modules
  Code:
    module Mod
      CONSTANT = 'Outer'
      class Cls
        CONSTANT = 'Inner'
      end
    end
Modules
  Code:
    module Mod
      CONSTANT = 'Outer'
      class Cls
        CONSTANT = 'Inner'
      end
    end




    Mod::CONSTANT => “Outer”
    Mod::Cls::CONSTANT => “Inner”
Modules
Code:
  module Mod
    def my_method
      'M#my_method()'
    end
  end

  class Cls
    include Mod
  end



  class Cls
    extend Mod
  end
Modules
Code:
  module Mod
    def my_method
      'M#my_method()'
    end
  end

  class Cls
    include Mod   Cls.new.my_method # =>“M#my_method()”
  end



  class Cls
    extend Mod
  end
Modules
Code:
  module Mod
    def my_method
      'M#my_method()'
    end
  end

  class Cls
    include Mod   Cls.new.my_method # =>“M#my_method()”
  end



  class Cls
    extend Mod    Cls.my_method # =>“M#my_method()”
  end
Modules
Code:
  module Mod
    def my_method
      'M#my_method()'
                         private instance
    end                      method
  end                       of Module

  class Cls
    include Mod   Cls.new.my_method # =>“M#my_method()”
  end



  class Cls
    extend Mod    Cls.my_method # =>“M#my_method()”
  end
Modules
Code:
  module Mod
    def my_method
      'M#my_method()'
                            private instance
    end                         method
  end                          of Module

  class Cls
    include Mod    Cls.new.my_method # =>“M#my_method()”
  end
                  Object#extend


  class Cls
    extend Mod     Cls.my_method # =>“M#my_method()”
  end
Functional
 Support
Blocks
Code:
def three_times
  yield
  yield
  yield
end

three_times { puts "Hello" }



# =>
 Hello
 Hello
 Hello
Blocks

Code:
    File.open("path/file", "r") do |file|
      file.each_line do |line|
        name, surname = line.split(',')
        ...
      end
    end
Blocks

Code:
        def my_method
          x = “Hello”
          yield("cruel")
        end

        x = "Goodbye"
        my_method {|y| "#{x}, #{y} world" }

        # => "Goodbye, cruel world"
Scope
                                              Class

                                              Module

Code:                                         Method
    v1 = 1
    class Cls             # SCOPE GATE: entering class
      v2 = 2
      local_variables     # => ["v2"]

        def my_method     # SCOPE GATE: entering def
          v3 = 3
          local_variables # => ["v3"]
        end               # SCOPE GATE: leaving def

      local_variables     # => ["v2"]
    end                   # SCOPE GATE: leaving class
Variables
Code:
        $v1 = ‘global variable’
        def Cls
          v2 = ‘local variable’

          @v3 = ‘class instance variable’

          def my_method
            @v3 = ‘instance variable’
          end

          @@v4   = ‘class hiearchy variable’
        end
Blocks
   Code:
             def define_methods              Dynamic
                                             Method
  Scope        shared = 0
Flattening
               Kernel.send :define_method, :counter do
                 shared
               end

               Kernel.send :define_method, :inc do |x|
                 shared += x
               end
             end



             counter       # => 0
             inc(4)
             counter       # => 4
Proc and Lambda

                                       Deferred
Code:                                  Evaluation

    plus_one = Proc.new {|x| x + 1 }
    ...
    plus_one.call(2) # => 3


    plus_one = lambda {|x| x + 1 }
    plus_one.call(2) # => 3
Proc and Lambda
             (& and to_proc)

Code:
    [1, 2, 5].inject(0){|sum, e| sum + e} # => 8
Proc and Lambda
             (& and to_proc)

Code:
    [1, 2, 5].inject(0){|sum, e| sum + e} # => 8




    [1, 2, 5].inject(0, &:+)   # => 8
Proc and Lambda
             (& and to_proc)

Code:
    [1, 2, 5].inject(0){|sum, e| sum + e} # => 8


                               Symbol

    [1, 2, 5].inject(0, &:+)   # => 8
Proc and Lambda
             (& and to_proc)

Code:
    [1, 2, 5].inject(0){|sum, e| sum + e} # => 8


                               Symbol

    [1, 2, 5].inject(0, &:+)   # => 8



    Class Symbol
      def to_proc
        proc { |obj, *args| obj.send(self, *args) }
      end
    end
Methods vs Keywords
Method Visibility



class Cls
! def public_method
! ! self.private_method
  !end
!
! private
!
! def private_method; end
end
Method Visibility



class Cls
! def public_method
! ! self.private_method
  !end
!
! private
!
! def private_method; end
end


C.new.public_method #=> NoMethodError: private method
Method Visibility


                                 class Cls
                                   (1..5).each do |i|
                                     define_method(“m#{i}”){}
class Cls                          end
! def public_method              !
! ! self.private_method            public     :m1, m2
  !end                             private    :m3, m4
!                                  protected :m5 ! !
! private                        end
!
! def private_method; end
end


C.new.public_method #=> NoMethodError: private method
Method Visibility




          Code:                  Dynamic
                                 Dispatch

                  c = Cls.new
                  c.send :private_method
Context           c.instance_eval {private_method}
 Probe            c.instance_eval {@var}
Exceptions
Code:
 begin
   raise “blew up”
 rescue => ex
   puts “I #{ex}”
 end
Exceptions
Code:                       begin
                              ...
 begin                        fail “error”
   raise “blew up”            ...
 rescue => ex               rescue StandardError => ex
   puts “I #{ex}”             puts “Failed: ” + ex
 end                          raise
                            else
                              ...
                            ensure
                              # clean up
                              ...
                            end
Exceptions
Code:                                        begin
                                               ...
 begin                                         fail “error”
   raise “blew up”                             ...
 rescue => ex                                rescue StandardError => ex
   puts “I #{ex}”                              puts “Failed: ” + ex
 end                                           raise
                                             else
                                               ...
                                             ensure
                                               # clean up
 tries = 0                                     ...
 begin                                       end
   tries += 1
   puts "Trying #{tries}..." raise "Didn’t work"
 rescue
   retry if tries < 3
   puts "I give up"
 end
Exceptions
Code:                                        begin
                                               ...
 begin                                         fail “error”
   raise “blew up”                             ...
 rescue => ex                                rescue StandardError => ex
   puts “I #{ex}”                              puts “Failed: ” + ex
 end                                           raise
                                             else
                                               ...
                                             ensure
                  Retry                        # clean up
 tries = 0                                     ...
 begin                                       end
   tries += 1
   puts "Trying #{tries}..." raise "Didn’t work"
 rescue
   retry if tries < 3
   puts "I give up"
 end
Exceptions
                       (raise)
Code:   def raise(error_cls_or_obj, msg, backtrace)
          error = error_cls_or_obj.exception(msg)
          #...
        end
Exceptions
                       (raise)
Code:   def raise(error_cls_or_obj, msg, backtrace)
          error = error_cls_or_obj.exception(msg)
          #...
        end

        # Bang!
        module RaiseExit
          def raise(msg_or_exc, msg=msg_or_exc, trace=caller)
            warn msg.to_s
            exit!
          end
        end

        class Object
          include RaiseExit
        end
Exceptions
    (dynamic rescue clauses)

Code:
        ignore_exceptions(IOError, SystemCallError) do
          open("NONEXISTENT_FILE")
        end


        def ignore_exceptions(*exceptions)
             yield
          rescue *exceptions => e
            puts "IGNORED: ’#{e}’"
        end
(Meta)Programming
(Meta)Programming
                  Class Macros Example
Code:
 Class Customer
   def name
     @name
   end

   def name=(n)
     @name = n
   end
   ...

  def age
     @age
   end

   def age=(a)
     @age = a
   end
 end
(Meta)Programming
                  Class Macros Example
Code:
 Class Customer              class Customer
   def name                    attr_accessor :name, :surname, :age
     @name                   end
   end

   def name=(n)
     @name = n
   end
   ...

  def age
     @age
   end

   def age=(a)
     @age = a
   end
 end
(Meta)Programming
                      Class Macros Example
Code:
 Class Customer                         class Customer
   def name                               attr_accessor :name, :surname, :age
     @name                              end
   end

   def name=(n) class Customer
     @name = n    def self.attr_accessor(*accessors)
   end              accessors.each do |accessor|
   ...                define_method(accessor) do
                        instance_variable_get("@#{accessor}")
  def age             end
     @age
   end                define_method("#{accessor}=") do |accessor_value|
                          instance_variable_set("@#{accessor}", accessor_value)
   def age=(a)          end
     @age = a         end
   end              end
 end              end
Hook Methods
                    (a.k.a. callbacks)
Method related hooks
                                 Class and module related
                                 hooks
• method_missing
• method_added                   • append_features
• method_removed                 • const_missing
• method_undefined                • extend_object
• singleton_method_added         • extended
•                                • included
singleton_method_removed
•                                • inherited
singleton_method_undefined
                                 • initialize_copy


Object marshaling                Coercion
hooks                            hooks

• marshal_dump                   • coerce
• marshal_load                   • induced_from
                                 • to_xxx
Method Missing
 Code:
 config = {
     :host => 'ws.contactlab.it',
     :path => '/RPC2',
     :use_ssl => true
 }

 class ContactLab
   def initialize(c)
     @ws_client = XMLRPC::Client.new(c)
   end

   def method_missing(rpc_method_name, *params)
     @ws_client.call("contactlab.#{rpc_method_name}",
 params)
   end
 end

 ContactLab.new(config).addNewRecipient(recipient)
Scripting
Expressions

Code:
  song_type = if song.mp3Type == MP3::Jazz
                if song.written < Date.new(1935, 1, 1)
                   Song::TradJazz
                else
                   Song::Jazz
                end
              else
                Song::Other
              end
Infrastructure as code



Code:
 package "rabbimq-server" do
   action :install
 end

 service "rabbitmq-server" do
   supports :status => true, :restart => true, :reload => true
   action[:enable, :start]
 end
Testing
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new
    @stack.push :item
  end
  describe "#peek" do
    it "returns the top element" do
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do
      @stack.peek
      @stack.size.should == 1
    end
  end
  describe "#pop" do
    it "returns the top element" do
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do
      @stack.peek
      @stack.size.should == 1
    end
  end
  describe "#pop" do
    it "returns the top element" do
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do
      @stack.peek
      @stack.size.should == 1
    end
  end
  describe "#pop" do
    it "returns the top element" do
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do    expect{do_something_risky}.to raise_error /too risky/
      @stack.peek
      @stack.size.should == 1
    end
  end
  describe "#pop" do
    it "returns the top element" do
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do    expect{do_something_risky}.to raise_error /too risky/
      @stack.peek
      @stack.size.should == 1
    end                               array.empty?.should == true <--> array.should be_empty
  end
  describe "#pop" do
    it "returns the top element" do
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do    expect{do_something_risky}.to raise_error /too risky/
      @stack.peek
      @stack.size.should == 1
    end                               array.empty?.should == true <--> array.should be_empty
  end
  describe "#pop" do                  field.players.select{|p| p.team == home_team}
    it "returns the top element" do                                           .length.should == 9
      @stack.pop.should == :item
    end
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do    expect{do_something_risky}.to raise_error /too risky/
      @stack.peek
      @stack.size.should == 1
    end                               array.empty?.should == true <--> array.should be_empty
  end
  describe "#pop" do                  field.players.select{|p| p.team == home_team}
    it "returns the top element" do                                           .length.should == 9
      @stack.pop.should == :item
    end
                                      home_team.should have(9).players_on(field)
    it "removes the top element" do
      @stack.pop
      @stack.size.should == 0
    end
  end
end
Code:
describe Stack do
                            RSpec
  before(:each) do
    @stack = Stack.new                expect {
    @stack.push :item                   User.create!(:role => "admin")
  end                                 }.to change{ User.admins.count }.by(1)
  describe "#peek" do
    it "returns the top element" do   result.should be_close(5.25, 0.005)
      @stack.peek.should == :item
    end
    it "doesn’t remove the top" do    expect{do_something_risky}.to raise_error /too risky/
      @stack.peek
      @stack.size.should == 1
    end                               array.empty?.should == true <--> array.should be_empty
  end
  describe "#pop" do                  field.players.select{|p| p.team == home_team}
    it "returns the top element" do                                           .length.should == 9
      @stack.pop.should == :item
    end
                                      home_team.should have(9).players_on(field)
    it "removes the top element" do
      @stack.pop                      a_politician.should have_at_least(3).escorts
      @stack.size.should == 0
    end
  end
end
Code:
                        Cucumber
  Feature: Google Search
    In order to learn something
   As an internet user
    I want to search for information on Google

   Scenario: Learn about Scrat
    Given I am on google.com
    When I search for "Scrat"
    Then I should see search results about Scrat

                                When /^I search for ['"](.*)['"]$/ do |query|
                                  fill_in('q', :with => query)
                                  click_button('Google Search')
                                end

                                Then /^I should see search results about (.*)$/
                                do |term|
                                  response_body.should include(term)
                                end
The Object Model Revisited
Splash                                               "motherboard" =~ /board/
class String                                                in_place!
                                 %w(a b c).freeze
 alias :real_length :length
                                                                        empty?                 :symbol
 def length                                                                                                       a ||= []
   real_length > 5 ? 'long' : 'short'
 end                                    raise InvalidFormat unless Formats.include?(format)
end
                     [1,2,3].map{ |e| e * e } #=> [1,4,9]

                     [1,2,3].inject{|sum, e| s + e} #=> 6

                     [1,2,3].select{|e| e % 2 != 0} #=> [1, 3]



                                            class Singleton              RSpec
spec = Gem::Specification.new do |s|
  s.name = “My Gem name”                      class << self
  s.version = “0.0.1”                           def instance                File.instance_methods.grep(/.*each.*/)
  # ...                                           @instance ||= new
end                                             end
                                                                  chars = "hello world".tap {|x| puts "original object: #{x.inspect}"}
                                                                   .each_char           .tap {|x| puts "each_char returns: #{x.inspect}"}
                                               private :new        .to_a                .tap {|x| puts "to_a returns: #{x.inspect}"}
                                             end                   .map {|c| c.succ } .tap {|x| puts "map returns: #{x.inspect}" }
                                            end                    .sort               .tap {|x| puts "sort returns: #{x.inspect}"}
Why Ruby?
Why Ruby?
Your own choice!!!
ns?
    stio
 ue
Q
References
Than
    k you
   :)    !

Weitere ähnliche Inhalte

Ähnlich wie Why I choosed Ruby

Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in RubyConFoo
 
Lightning talk
Lightning talkLightning talk
Lightning talknpalaniuk
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the BasicsMichael Koby
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby MetaprogrammingNando Vieira
 
Ruby — An introduction
Ruby — An introductionRuby — An introduction
Ruby — An introductionGonçalo Silva
 
Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013rivierarb
 
Pharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellPharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellMarcus Denker
 
Introduction to ruby eval
Introduction to ruby evalIntroduction to ruby eval
Introduction to ruby evalNiranjan Sarade
 
Runtime Tools
Runtime ToolsRuntime Tools
Runtime ToolsESUG
 
Pharo, an innovative and open-source Smalltalk
Pharo, an innovative and open-source SmalltalkPharo, an innovative and open-source Smalltalk
Pharo, an innovative and open-source SmalltalkSerge Stinckwich
 
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfPython Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfSudhanshiBakre1
 
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfPython Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfSudhanshiBakre1
 

Ähnlich wie Why I choosed Ruby (20)

Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
 
Lightning talk
Lightning talkLightning talk
Lightning talk
 
Ruby Basics
Ruby BasicsRuby Basics
Ruby Basics
 
Metaprogramming in Ruby
Metaprogramming in RubyMetaprogramming in Ruby
Metaprogramming in Ruby
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby Metaprogramming
 
Ruby — An introduction
Ruby — An introductionRuby — An introduction
Ruby — An introduction
 
Ruby basic3
Ruby basic3Ruby basic3
Ruby basic3
 
Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013Ruby object model at the Ruby drink-up of Sophia, January 2013
Ruby object model at the Ruby drink-up of Sophia, January 2013
 
Ruby singleton class
Ruby singleton classRuby singleton class
Ruby singleton class
 
Python advance
Python advancePython advance
Python advance
 
Pharo: Syntax in a Nutshell
Pharo: Syntax in a NutshellPharo: Syntax in a Nutshell
Pharo: Syntax in a Nutshell
 
Introduction to ruby eval
Introduction to ruby evalIntroduction to ruby eval
Introduction to ruby eval
 
Ruby objects
Ruby objectsRuby objects
Ruby objects
 
Runtime Tools
Runtime ToolsRuntime Tools
Runtime Tools
 
ruby1_6up
ruby1_6upruby1_6up
ruby1_6up
 
ruby1_6up
ruby1_6upruby1_6up
ruby1_6up
 
Pharo, an innovative and open-source Smalltalk
Pharo, an innovative and open-source SmalltalkPharo, an innovative and open-source Smalltalk
Pharo, an innovative and open-source Smalltalk
 
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfPython Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
 
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdfPython Classes_ Empowering Developers, Enabling Breakthroughs.pdf
Python Classes_ Empowering Developers, Enabling Breakthroughs.pdf
 

Kürzlich hochgeladen

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 

Kürzlich hochgeladen (20)

"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 

Why I choosed Ruby

  • 1. Ruby Programming Language
  • 2. About Me > 8 years of developing experience retail, e-commerce, logistics, fashion, multi-media, etc. lead developer, team leader, project manager, functional analysts, architect. a runner and a mountain lover elimi @I ndritS
  • 3. Why Ruby Everything is an Object Dynamic typing Open Mix-ins Functional support Methods vs Keywords (Meta)programming ‘Scripting’ support LBNL: Testing
  • 4. Everything is an object
  • 5. Classical class MyClass def method @v = 1 end end Object Class Instance class MyClass @v = 1 method() Code: obj = MyClass.new obj.methods == MyClass.instance_methods # => true obj.methods != MyClass.methods # => true
  • 6. Everything is an Object superclass Object Module inst class superclass superclass class MyClass Class class
  • 7. Classes Code: class Cls < Array def sum inject{ |sum, element| sum + element} end end
  • 8. Classes Code: class Cls < Array Cls = Class.new(Array) do def sum def sum inject{ |sum, element| sum + element} inject{|sum, element| sum + element} end end end end
  • 9. Classes Code: class Cls < Array Cls = Class.new(Array) do def sum def sum inject{ |sum, element| sum + element} inject{|sum, element| sum + element} end end end end
  • 10. Classes Code: class Cls < Array Cls = Class.new(Array) do def sum def sum inject{ |sum, element| sum + element} inject{|sum, element| sum + element} end end end end Classes are nothing but objects, class names are nothing but constants.
  • 11. Classes Code: class Cls < Array Cls = Class.new(Array) do def sum def sum inject{ |sum, element| sum + element} inject{|sum, element| sum + element} end end end end ! Classes are nothing but objects, class names are nothing but constants.
  • 13. Dynamic Typing Code: class CreditCard def pay; #credit code; end end class Cod def pay; #cod code; end end class WireTransfer def pay; #wrt code; end end def process(payment) ... payment.pay ... end
  • 14. Ruby is an open language by design
  • 16. Class Opening Code: 3.times do class Cls puts “Hi” end end
  • 17. Class Opening Code: 3.times do class Cls puts “Hi” end end => Hi Hi Hi
  • 18. Class Opening Code: 3.times do def Cls.hi class Cls puts “Hi Class” puts “Hi” end end end => Hi Hi Hi
  • 19. Class Opening Code: 3.times do def Cls.hi class Cls puts “Hi Class” puts “Hi” end end end => Hi Cls.hi #=> Hi Hi Hi
  • 20. Class Opening Code: def Cls.hi obj1 = Cls.new 3.times do puts “Hi Class” obj2 = Cls.new class Cls puts “Hi” end def obj1.hi end puts “Hi” end end => Hi Cls.hi #=> Hi Hi Hi
  • 21. Class Opening Code: def Cls.hi obj1 = Cls.new 3.times do puts “Hi Class” obj2 = Cls.new class Cls puts “Hi” end def obj1.hi end puts “Hi” end end => Hi Cls.hi #=> Hi obj1.hi # => Hi Hi Hi
  • 22. Class Opening Code: def Cls.hi obj1 = Cls.new 3.times do puts “Hi Class” obj2 = Cls.new class Cls puts “Hi” end def obj1.hi end puts “Hi” end end => Hi Cls.hi #=> Hi obj1.hi # => Hi Hi obj2.hi # => Hi NoMethodError
  • 24. Modules Code: module Mod CONSTANT = 'Outer' class Cls CONSTANT = 'Inner' end end
  • 25. Modules Code: module Mod CONSTANT = 'Outer' class Cls CONSTANT = 'Inner' end end Mod::CONSTANT => “Outer” Mod::Cls::CONSTANT => “Inner”
  • 26. Modules Code: module Mod def my_method 'M#my_method()' end end class Cls include Mod end class Cls extend Mod end
  • 27. Modules Code: module Mod def my_method 'M#my_method()' end end class Cls include Mod Cls.new.my_method # =>“M#my_method()” end class Cls extend Mod end
  • 28. Modules Code: module Mod def my_method 'M#my_method()' end end class Cls include Mod Cls.new.my_method # =>“M#my_method()” end class Cls extend Mod Cls.my_method # =>“M#my_method()” end
  • 29. Modules Code: module Mod def my_method 'M#my_method()' private instance end method end of Module class Cls include Mod Cls.new.my_method # =>“M#my_method()” end class Cls extend Mod Cls.my_method # =>“M#my_method()” end
  • 30. Modules Code: module Mod def my_method 'M#my_method()' private instance end method end of Module class Cls include Mod Cls.new.my_method # =>“M#my_method()” end Object#extend class Cls extend Mod Cls.my_method # =>“M#my_method()” end
  • 32. Blocks Code: def three_times yield yield yield end three_times { puts "Hello" } # => Hello Hello Hello
  • 33. Blocks Code: File.open("path/file", "r") do |file| file.each_line do |line| name, surname = line.split(',') ... end end
  • 34. Blocks Code: def my_method x = “Hello” yield("cruel") end x = "Goodbye" my_method {|y| "#{x}, #{y} world" } # => "Goodbye, cruel world"
  • 35. Scope Class Module Code: Method v1 = 1 class Cls # SCOPE GATE: entering class v2 = 2 local_variables # => ["v2"] def my_method # SCOPE GATE: entering def v3 = 3 local_variables # => ["v3"] end # SCOPE GATE: leaving def local_variables # => ["v2"] end # SCOPE GATE: leaving class
  • 36. Variables Code: $v1 = ‘global variable’ def Cls v2 = ‘local variable’ @v3 = ‘class instance variable’ def my_method @v3 = ‘instance variable’ end @@v4 = ‘class hiearchy variable’ end
  • 37. Blocks Code: def define_methods Dynamic Method Scope shared = 0 Flattening Kernel.send :define_method, :counter do shared end Kernel.send :define_method, :inc do |x| shared += x end end counter # => 0 inc(4) counter # => 4
  • 38. Proc and Lambda Deferred Code: Evaluation plus_one = Proc.new {|x| x + 1 } ... plus_one.call(2) # => 3 plus_one = lambda {|x| x + 1 } plus_one.call(2) # => 3
  • 39. Proc and Lambda (& and to_proc) Code: [1, 2, 5].inject(0){|sum, e| sum + e} # => 8
  • 40. Proc and Lambda (& and to_proc) Code: [1, 2, 5].inject(0){|sum, e| sum + e} # => 8 [1, 2, 5].inject(0, &:+) # => 8
  • 41. Proc and Lambda (& and to_proc) Code: [1, 2, 5].inject(0){|sum, e| sum + e} # => 8 Symbol [1, 2, 5].inject(0, &:+) # => 8
  • 42. Proc and Lambda (& and to_proc) Code: [1, 2, 5].inject(0){|sum, e| sum + e} # => 8 Symbol [1, 2, 5].inject(0, &:+) # => 8 Class Symbol def to_proc proc { |obj, *args| obj.send(self, *args) } end end
  • 44. Method Visibility class Cls ! def public_method ! ! self.private_method !end ! ! private ! ! def private_method; end end
  • 45. Method Visibility class Cls ! def public_method ! ! self.private_method !end ! ! private ! ! def private_method; end end C.new.public_method #=> NoMethodError: private method
  • 46. Method Visibility class Cls (1..5).each do |i| define_method(“m#{i}”){} class Cls end ! def public_method ! ! ! self.private_method public :m1, m2 !end private :m3, m4 ! protected :m5 ! ! ! private end ! ! def private_method; end end C.new.public_method #=> NoMethodError: private method
  • 47. Method Visibility Code: Dynamic Dispatch c = Cls.new c.send :private_method Context c.instance_eval {private_method} Probe c.instance_eval {@var}
  • 48. Exceptions Code: begin raise “blew up” rescue => ex puts “I #{ex}” end
  • 49. Exceptions Code: begin ... begin fail “error” raise “blew up” ... rescue => ex rescue StandardError => ex puts “I #{ex}” puts “Failed: ” + ex end raise else ... ensure # clean up ... end
  • 50. Exceptions Code: begin ... begin fail “error” raise “blew up” ... rescue => ex rescue StandardError => ex puts “I #{ex}” puts “Failed: ” + ex end raise else ... ensure # clean up tries = 0 ... begin end tries += 1 puts "Trying #{tries}..." raise "Didn’t work" rescue retry if tries < 3 puts "I give up" end
  • 51. Exceptions Code: begin ... begin fail “error” raise “blew up” ... rescue => ex rescue StandardError => ex puts “I #{ex}” puts “Failed: ” + ex end raise else ... ensure Retry # clean up tries = 0 ... begin end tries += 1 puts "Trying #{tries}..." raise "Didn’t work" rescue retry if tries < 3 puts "I give up" end
  • 52. Exceptions (raise) Code: def raise(error_cls_or_obj, msg, backtrace) error = error_cls_or_obj.exception(msg) #... end
  • 53. Exceptions (raise) Code: def raise(error_cls_or_obj, msg, backtrace) error = error_cls_or_obj.exception(msg) #... end # Bang! module RaiseExit def raise(msg_or_exc, msg=msg_or_exc, trace=caller) warn msg.to_s exit! end end class Object include RaiseExit end
  • 54. Exceptions (dynamic rescue clauses) Code: ignore_exceptions(IOError, SystemCallError) do open("NONEXISTENT_FILE") end def ignore_exceptions(*exceptions) yield rescue *exceptions => e puts "IGNORED: ’#{e}’" end
  • 56. (Meta)Programming Class Macros Example Code: Class Customer def name @name end def name=(n) @name = n end ... def age @age end def age=(a) @age = a end end
  • 57. (Meta)Programming Class Macros Example Code: Class Customer class Customer def name attr_accessor :name, :surname, :age @name end end def name=(n) @name = n end ... def age @age end def age=(a) @age = a end end
  • 58. (Meta)Programming Class Macros Example Code: Class Customer class Customer def name attr_accessor :name, :surname, :age @name end end def name=(n) class Customer @name = n def self.attr_accessor(*accessors) end accessors.each do |accessor| ... define_method(accessor) do instance_variable_get("@#{accessor}") def age end @age end define_method("#{accessor}=") do |accessor_value| instance_variable_set("@#{accessor}", accessor_value) def age=(a) end @age = a end end end end end
  • 59. Hook Methods (a.k.a. callbacks) Method related hooks Class and module related hooks • method_missing • method_added • append_features • method_removed • const_missing • method_undefined • extend_object • singleton_method_added • extended • • included singleton_method_removed • • inherited singleton_method_undefined • initialize_copy Object marshaling Coercion hooks hooks • marshal_dump • coerce • marshal_load • induced_from • to_xxx
  • 60. Method Missing Code: config = { :host => 'ws.contactlab.it', :path => '/RPC2', :use_ssl => true } class ContactLab def initialize(c) @ws_client = XMLRPC::Client.new(c) end def method_missing(rpc_method_name, *params) @ws_client.call("contactlab.#{rpc_method_name}", params) end end ContactLab.new(config).addNewRecipient(recipient)
  • 62. Expressions Code: song_type = if song.mp3Type == MP3::Jazz if song.written < Date.new(1935, 1, 1) Song::TradJazz else Song::Jazz end else Song::Other end
  • 63. Infrastructure as code Code: package "rabbimq-server" do action :install end service "rabbitmq-server" do supports :status => true, :restart => true, :reload => true action[:enable, :start] end
  • 65. Code: describe Stack do RSpec before(:each) do @stack = Stack.new @stack.push :item end describe "#peek" do it "returns the top element" do @stack.peek.should == :item end it "doesn’t remove the top" do @stack.peek @stack.size.should == 1 end end describe "#pop" do it "returns the top element" do @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 66. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do @stack.peek.should == :item end it "doesn’t remove the top" do @stack.peek @stack.size.should == 1 end end describe "#pop" do it "returns the top element" do @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 67. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do @stack.peek @stack.size.should == 1 end end describe "#pop" do it "returns the top element" do @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 68. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do expect{do_something_risky}.to raise_error /too risky/ @stack.peek @stack.size.should == 1 end end describe "#pop" do it "returns the top element" do @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 69. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do expect{do_something_risky}.to raise_error /too risky/ @stack.peek @stack.size.should == 1 end array.empty?.should == true <--> array.should be_empty end describe "#pop" do it "returns the top element" do @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 70. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do expect{do_something_risky}.to raise_error /too risky/ @stack.peek @stack.size.should == 1 end array.empty?.should == true <--> array.should be_empty end describe "#pop" do field.players.select{|p| p.team == home_team} it "returns the top element" do .length.should == 9 @stack.pop.should == :item end it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 71. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do expect{do_something_risky}.to raise_error /too risky/ @stack.peek @stack.size.should == 1 end array.empty?.should == true <--> array.should be_empty end describe "#pop" do field.players.select{|p| p.team == home_team} it "returns the top element" do .length.should == 9 @stack.pop.should == :item end home_team.should have(9).players_on(field) it "removes the top element" do @stack.pop @stack.size.should == 0 end end end
  • 72. Code: describe Stack do RSpec before(:each) do @stack = Stack.new expect { @stack.push :item User.create!(:role => "admin") end }.to change{ User.admins.count }.by(1) describe "#peek" do it "returns the top element" do result.should be_close(5.25, 0.005) @stack.peek.should == :item end it "doesn’t remove the top" do expect{do_something_risky}.to raise_error /too risky/ @stack.peek @stack.size.should == 1 end array.empty?.should == true <--> array.should be_empty end describe "#pop" do field.players.select{|p| p.team == home_team} it "returns the top element" do .length.should == 9 @stack.pop.should == :item end home_team.should have(9).players_on(field) it "removes the top element" do @stack.pop a_politician.should have_at_least(3).escorts @stack.size.should == 0 end end end
  • 73. Code: Cucumber Feature: Google Search In order to learn something As an internet user I want to search for information on Google Scenario: Learn about Scrat Given I am on google.com When I search for "Scrat" Then I should see search results about Scrat When /^I search for ['"](.*)['"]$/ do |query| fill_in('q', :with => query) click_button('Google Search') end Then /^I should see search results about (.*)$/ do |term| response_body.should include(term) end
  • 74. The Object Model Revisited
  • 75. Splash "motherboard" =~ /board/ class String in_place! %w(a b c).freeze alias :real_length :length empty? :symbol def length a ||= [] real_length > 5 ? 'long' : 'short' end raise InvalidFormat unless Formats.include?(format) end [1,2,3].map{ |e| e * e } #=> [1,4,9] [1,2,3].inject{|sum, e| s + e} #=> 6 [1,2,3].select{|e| e % 2 != 0} #=> [1, 3] class Singleton RSpec spec = Gem::Specification.new do |s| s.name = “My Gem name” class << self s.version = “0.0.1” def instance File.instance_methods.grep(/.*each.*/) # ... @instance ||= new end end chars = "hello world".tap {|x| puts "original object: #{x.inspect}"} .each_char .tap {|x| puts "each_char returns: #{x.inspect}"} private :new .to_a .tap {|x| puts "to_a returns: #{x.inspect}"} end .map {|c| c.succ } .tap {|x| puts "map returns: #{x.inspect}" } end .sort .tap {|x| puts "sort returns: #{x.inspect}"}
  • 77. Why Ruby? Your own choice!!!
  • 78. ns? stio ue Q
  • 80. Than k you :) !

Hinweis der Redaktion

  1. Disclaimer: I&amp;#x2019;ll not teach Ruby.\n\nRuby follows: http://en.wikipedia.org/wiki/Principle_of_least_surprise.\n\nIn computer science the term refers to runtime resolution of what names mean and includes the concept of dynamic loading.\n\nLate binding is a computer programming mechanism in which the method being called upon an object is looked up by name at runtime. This is informally known as duck typing or name binding.\n
  2. \n
  3. An internal DSL, again according to Fowler, is one in which you start with some implementation language, perhaps Ruby, and you simply bend that one language into being your domain specific language. If you are using Ruby to implement your internal DSL, then anyone who writes a program in your little language is actually, and perhaps unknowingly, writing a Ruby program.\n
  4. An internal DSL, again according to Fowler, is one in which you start with some implementation language, perhaps Ruby, and you simply bend that one language into being your domain specific language. If you are using Ruby to implement your internal DSL, then anyone who writes a program in your little language is actually, and perhaps unknowingly, writing a Ruby program.\n
  5. Object has object_id method that return a fixnum identifier.\n\nThe methods of an object are the instance methods of its class.\n\n\nnil, true, false, self --&gt; keyword literals\n\nUnlike in Java or other static languages, in Ruby there is no connection between an object&amp;#x2019;s class and its instance variables. Instance variables just spring into existence when you assign them a value, so you can have objects of the same class that carry different sets of instance variables. You can think of the names and values of instance variables as keys and values in a hash. Both the keys and the values can be different for each object.\n\n\nOn the inside, an object simply contains its instance variables and a reference to its class. To be precise, it also contains a unique identifier (the one returned by Object#object_id( )) and a set of flags that mark special states such as &amp;#x201C;tainted&amp;#x201D; or &amp;#x201C;frozen.&amp;#x201D; To remove the ambiguity, you should say that my_method() is an instance method (not just &amp;#x201C;a method&amp;#x201D;) of MyClass, meaning that it&amp;#x2019;s defined in MyClass, and you actually need an instance of MyClass to call it.\n\nAn object&amp;#x2019;s instance variable live in the object itself and an object&amp;#x2019;s methods live in the object&amp;#x2019;s class. That&amp;#x2019;s why objects of the same class share methods but don&amp;#x2019;t share instance variables.\n\n \n
  6. \n
  7. inject { |sum, element| sum + element }\n
  8. inject { |sum, element| sum + element }\n
  9. inject { |sum, element| sum + element }\n
  10. inject { |sum, element| sum + element }\n
  11. \n
  12. \n
  13. \n
  14. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  15. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  16. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  17. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  18. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  19. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  20. FixNum and Symbol are immediate values and can&amp;#x2019;t be extended.\n
  21. \n
  22. Contants name convention (all upper case) \n\ninclude is a keyword...no! It is a private instance method of Module. It&amp;#x2019;s arguments are only modules, not sublcasses (classes).\n\nObject#extend --&gt; This method makes the instance methods of the specified module or modules into singleton methods of the receiver object. \nObject#extend() is simply a shortcut that includes a module in the receiver&amp;#x2019;s eigenclass.\n\nIt is just a shortcut for this:\n\nclass &lt;&lt; obj\n include Module \nend\n\n
  23. Contants name convention (all upper case) \n\ninclude is a keyword...no! It is a private instance method of Module. It&amp;#x2019;s arguments are only modules, not sublcasses (classes).\n\nObject#extend --&gt; This method makes the instance methods of the specified module or modules into singleton methods of the receiver object. \nObject#extend() is simply a shortcut that includes a module in the receiver&amp;#x2019;s eigenclass.\n\nIt is just a shortcut for this:\n\nclass &lt;&lt; obj\n include Module \nend\n\n
  24. Contants name convention (all upper case) \n\ninclude is a keyword...no! It is a private instance method of Module. It&amp;#x2019;s arguments are only modules, not sublcasses (classes).\n\nObject#extend --&gt; This method makes the instance methods of the specified module or modules into singleton methods of the receiver object. \nObject#extend() is simply a shortcut that includes a module in the receiver&amp;#x2019;s eigenclass.\n\nIt is just a shortcut for this:\n\nclass &lt;&lt; obj\n include Module \nend\n\n
  25. Contants name convention (all upper case) \n\ninclude is a keyword...no! It is a private instance method of Module. It&amp;#x2019;s arguments are only modules, not sublcasses (classes).\n\nObject#extend --&gt; This method makes the instance methods of the specified module or modules into singleton methods of the receiver object. \nObject#extend() is simply a shortcut that includes a module in the receiver&amp;#x2019;s eigenclass.\n\nIt is just a shortcut for this:\n\nclass &lt;&lt; obj\n include Module \nend\n\n
  26. Contants name convention (all upper case) \n\ninclude is a keyword...no! It is a private instance method of Module. It&amp;#x2019;s arguments are only modules, not sublcasses (classes).\n\nObject#extend --&gt; This method makes the instance methods of the specified module or modules into singleton methods of the receiver object. \nObject#extend() is simply a shortcut that includes a module in the receiver&amp;#x2019;s eigenclass.\n\nIt is just a shortcut for this:\n\nclass &lt;&lt; obj\n include Module \nend\n\n
  27. \n
  28. First, a block may appear only in the source adjacent to a method call; the block is written starting on the same line as the method call&amp;#x2019;s last parameter (or the closing parenthesis of the parameter list).\nSecond, the code in the block is not executed at the time it is encountered. Instead, Ruby remembers the context in which the block appears (the local variables, the current object, and so on) and then enters the method.\n\nWhat makes blocks interesting, however, is that you can pass parameters to them and receive values from them.\nThe yield statement is like a method invocation; it is followed by zero or more expressions whose values are assigned to the block parameters.\n\n
  29. \n
  30. \n
  31. \n
  32. Instance variables are variables that belong to a particular object instance. Each object has its own object variables.\n\n4 types of variables (plus constant). Please note that Cls is constant, therefore global.\n\n
  33. Blocks, Procs and Lambdas are closures.\n\nYou can define a block only when you call a method. Optionally, a block can have arguments, like x and y in Bill&amp;#x2019;s example. When you call back to the block, you can provide values for its argu- ments, just like you do when you call a method. Also, like a method, a block returns the result of the last line of code it evaluates.\n\nA block captures the bindings that are around when you first define the block. \nYou can also define additional bindings inside the block, but they disappear after the block ends.\n\nThere are exactly three places where a program leaves the previous scope behind and opens a new one:\n&amp;#x2022; Class definitions\n&amp;#x2022; Module definitions\n &amp;#x2022; Methods\nclass, module, and def\n\nThere is a subtle difference between class and module on one side and def on the other. The code in a class or module definition is executed immediately. Conversely, the code in a method definition is executed later, when you eventually call the method. However, as you write your program, you usually don&amp;#x2019;t care when it changes scope&amp;#x2014;you only care that it does.\nScope Wrap-Up\nEach Ruby scope contains a bunch of bindings, and the scopes are separated by Scope Gates (100): class, module, and def. If you want to sneak a binding or two through a Scope Gate, you can replace the Scope Gate with a method call: you capture the current bindings in a closure and pass the closure to the method. You can replace class with Class.new( ), module with Module.new, and def with Module#define_method( ). This is a\nSpell: Shared Scope\n\n\n\nINSTANCE_EVAL() 105\nFlat Scope (103), the basic closure-related spell. If you define multiple methods in the same Flat Scope, maybe protected by a Scope Gate, all those methods can share bindings. That&amp;#x2019;s called a Shared Scope (104).\n\n
  34. A block is like an additional, anonymous argument to a method.\n\nProcs have block-like behavior and lambdas have method-like behavior. Both, however, are instances of class Proc.\n\nIn most cases, you execute the block right there in the method, using yield. There are two cases where yield is not enough:\n&amp;#x2022; You want to pass the block to another method.\n&amp;#x2022; You want to convert the block to a Proc.\nProc vs Lambdas --&gt; Return and Arity check\nHowever, if the last parameter in a method definition is prefixed with an ampersand, any associated block is converted to a Proc object, and that object is assigned to the parameter.\nclass Symbol\n def to_proc\n proc { |obj, *args| obj.send(self, *args) }\n end\nend\n\nTalk about coercion protocols.\n\nA Method object is similar to a lambda, with an important difference: a lambda is evaluated in the scope it&amp;#x2019;s defined in (it&amp;#x2019;s a closure, remember?), while a Method is evaluated in the scope of its object.\nWhen you redefine a method you don&amp;#x2019;t really change the method. Instead you define a new method and attach an existing name to that new method.\n\nCallable Objects Wrap-Up\nCallable objects are snippets of code that you can evaluate, and they carry their own scope along with them. They can be the following:\n&amp;#x2022; Blocks (they aren&amp;#x2019;t really &amp;#x201C;objects,&amp;#x201D; but they are still &amp;#x201C;callable&amp;#x201D;): Evaluated in the scope in which they&amp;#x2019;re defined.\n&amp;#x2022; Procs: Objects of class Proc. Like blocks, they are evaluated in the scope where they&amp;#x2019;re defined.\n&amp;#x2022; Lambdas: Also objects of class Proc but subtly different from reg- ular procs. They&amp;#x2019;re closures like blocks and procs, and as such they&amp;#x2019;re evaluated in the scope where they&amp;#x2019;re defined.\n&amp;#x2022; Methods: Bound to an object, they are evaluated in that object&amp;#x2019;s scope. They can also be unbound from their scope and rebound to the scope of another object.\nDifferent callable objects exhibit subtly different behaviors. In methods and lambdas, return returns from the callable object, while in procs and blocks, return returns from the callable object&amp;#x2019;s original context. Different callable objects also react differently to calls with the wrong arity. Methods are stricter, lambdas are almost as strict (save for some corner cases), and procs and blocks are more tolerant.\nThese differences notwithstanding, you can still convert from one call- able object to another, such as by using Proc.new(), Method#to_proc(), or the &amp; operator.\n\n\n\n\n
  35. \n
  36. \n
  37. \n
  38. \n
  39. Public, Private, Protected are instance methods of Module class.\n\nPublic as default except: \n - methods outside of class def are private instance methods of Object. \n - initialize is implicitly private. \n\nPrivate\n - called within class or its subclasses. called in functional style m\n\nProtected\n - same as private --&gt; within class or subclasses\n - no condition on implicit object\n\nMethods: pass by value.\nsymbol --&gt; :&amp;#x2018;string&amp;#x2019; and FixNum are immediate values (immutable)\nThe existance of the immediate values should be considered an implementation detail. The immediate values could not have singleton values defined on them; different from reference values.\n\nMethod &amp;#x2018;send&amp;#x2019; helps in testing private methods, mention the Sandi Matz problem with testing private methods.\n\nNote that you can have different visibilities for different aliases. It&amp;#x2019;s the method name, not the method itself, that is either public or private. See Around Aliases.\n
  40. Public, Private, Protected are instance methods of Module class.\n\nPublic as default except: \n - methods outside of class def are private instance methods of Object. \n - initialize is implicitly private. \n\nPrivate\n - called within class or its subclasses. called in functional style m\n\nProtected\n - same as private --&gt; within class or subclasses\n - no condition on implicit object\n\nMethods: pass by value.\nsymbol --&gt; :&amp;#x2018;string&amp;#x2019; and FixNum are immediate values (immutable)\nThe existance of the immediate values should be considered an implementation detail. The immediate values could not have singleton values defined on them; different from reference values.\n\nMethod &amp;#x2018;send&amp;#x2019; helps in testing private methods, mention the Sandi Matz problem with testing private methods.\n\nNote that you can have different visibilities for different aliases. It&amp;#x2019;s the method name, not the method itself, that is either public or private. See Around Aliases.\n
  41. Public, Private, Protected are instance methods of Module class.\n\nPublic as default except: \n - methods outside of class def are private instance methods of Object. \n - initialize is implicitly private. \n\nPrivate\n - called within class or its subclasses. called in functional style m\n\nProtected\n - same as private --&gt; within class or subclasses\n - no condition on implicit object\n\nMethods: pass by value.\nsymbol --&gt; :&amp;#x2018;string&amp;#x2019; and FixNum are immediate values (immutable)\nThe existance of the immediate values should be considered an implementation detail. The immediate values could not have singleton values defined on them; different from reference values.\n\nMethod &amp;#x2018;send&amp;#x2019; helps in testing private methods, mention the Sandi Matz problem with testing private methods.\n\nNote that you can have different visibilities for different aliases. It&amp;#x2019;s the method name, not the method itself, that is either public or private. See Around Aliases.\n
  42. The rescue clauses in Ruby behave like a case statement.\n\nraise is a method.\n\nraise() equivalent of raise $! or raise RuntimeError if $!is nil.\n\nIn Ruby exception behaves like strings --&gt; &amp;#x201C;Failed&amp;#x201D;+ex call ex.to_str\nException#exception behaves like an explicit coercion method like to_s or to_a. \n\nraise via aliasing becomes fail. Aliasing permits, other then advices,to correctly name the same methods between different abstraction levels. \n
  43. The rescue clauses in Ruby behave like a case statement.\n\nraise is a method.\n\nraise() equivalent of raise $! or raise RuntimeError if $!is nil.\n\nIn Ruby exception behaves like strings --&gt; &amp;#x201C;Failed&amp;#x201D;+ex call ex.to_str\nException#exception behaves like an explicit coercion method like to_s or to_a. \n\nraise via aliasing becomes fail. Aliasing permits, other then advices,to correctly name the same methods between different abstraction levels. \n
  44. The rescue clauses in Ruby behave like a case statement.\n\nraise is a method.\n\nraise() equivalent of raise $! or raise RuntimeError if $!is nil.\n\nIn Ruby exception behaves like strings --&gt; &amp;#x201C;Failed&amp;#x201D;+ex call ex.to_str\nException#exception behaves like an explicit coercion method like to_s or to_a. \n\nraise via aliasing becomes fail. Aliasing permits, other then advices,to correctly name the same methods between different abstraction levels. \n
  45. \n
  46. \n
  47. \n
  48. Metaprogramming: writing code that writes code!\nRuby is a reflective language.\n\nThe language in which the metaprogram is written is called the metalanguage. The language of the programs that are manipulated is called the object language. The ability of a programming language to be its own metalanguage is called reflection or reflexivity.\n
  49. Metaprogramming: writing code that writes code!\nRuby is a reflective language.\n\nThe language in which the metaprogram is written is called the metalanguage. The language of the programs that are manipulated is called the object language. The ability of a programming language to be its own metalanguage is called reflection or reflexivity.\n
  50. a.k.a. --&gt; also known as\n
  51. example = OpenStruct.new\nexample.empty = true\nBuilders.\n
  52. \n
  53. Many programming languages distinguish between low-leve expressions and higher-level statements, such as conditionals and loop. In these languages, statements control the\nflow but they do not have values. They are executed rather the evaluated.\nIn Ruby there is no clear distinction between statements and expressions; everything in Ruby, including class and method definitions, can be evaluated as an expresion and will return a value.\nOne of the first differences with Ruby is that anything that can reasonably return a value does: just about everything is an expression.\n\nFor example, the if and case statements both return the value of the last expression executed.\n\n\n\n
  54. Continuous Integration.\n\nChecf has a client-server architecture.\n
  55. \n
  56. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  57. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  58. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  59. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  60. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  61. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  62. Predicate matchers (be, be_a, etc): a ruby predicate method is one whose name ends with &amp;#x201C;?&amp;#x201D; and returns a Boolean value. home_team.should have(9).players_on(field)\n
  63. Cucumber is an interpreter.The Cucumber executable interprets Gherkin code in .feature files.\nLike Python and YAML, Gherkin is a line-oriented language that uses indentation to define structure.\nCucumber scenarios consist of steps, also known as Givens, Whens and Thens.\n\nThe Given/When/Then convention is central to the notion of BDD. It connects the human concept of cause and effect, to the software concept of input/process/output.\n\n
  64. The superclass of the eigenclass is the eigenclass of the superclass. It&amp;#x2019;s easy!\n
  65. Around Aliases: Note that you can have different visibilities for different aliases. It&amp;#x2019;s the method name, not the method itself, that is either public or private.\n\nWhen you redefine a method you don&amp;#x2019;t really change the method. Instead you define a new method and attach an existing name to that new method.\n\nYou can explicitly prevent an object from being extended it by &amp;#x201C;freezing&amp;#x201D; it using the freeze method.\n
  66. \n
  67. \n
  68. \n
  69. \n