ruby :: training 1
TRANSCRIPT
TRAINING 1
RUBYPavel Tsiukhtsiayeu
github.com/paveltyk
Ruby :: introduction• Ruby is a object oriented language• Truly OBJECT ORIENTED language !!!• Designed and developed by Yukihiro “Matz” Matsumoto
Ruby :: introduction• Yukihiro “Matz” Matsumoto
• まつもとゆきひろ 松本行弘• Born 14 Apr 1965• As of 2012, Matsumoto is the
Chief Architect of Ruby at Heroku• https://github.com/matz• https://twitter.com/yukihiro_matz
Ruby :: introduction• Ruby is a object oriented language• Truly OBJECT ORIENTED language !!!• Designed and developed by Yukihiro “Matz” Matsumoto• Ruby written for humans, not machines
• Often … computer engineers … focus on the machines. But in fact we need to focus on humans… We are the masters. They are the slaves.
• Rich yet Flexible Syntax• 3.downto(0) { |i| puts "Countdown: #{i}..."}• user = User.find_by_name(‘Matz’) and user.say_hi
• Ruby makes developers HAPPY
Ruby :: variables and constants• Sigils denote scopes• Sigil - symbol attached to variable name• $ - global ($global_variable)• @ - instance variable (@instance_variable)• @@ - class variable (@@class_variable)• [A-Z] - constants
• CONSTANT - all upper case• MyClass - titleized
• [_a-z] - local variables (local_variable)• You never see variable declarations• But you always know what you are dealing with• Clean and Readable code
Ruby :: methods, naming convention• object.find_by_name - preferable snake case• object.dangerous! - Bang!!! method• object.boolean_predicate? - returns true or false
def Name # do not do this “I’m a method”end
Name = “I’m a constant”
Name
#=> “I’m a constant”
Name()
#=> “I’m a method”
• Everything is an object. Everything!• 1.class => Fixnum• “hello”.class => String• [1, ‘hello’, nil].class => Array• nil.class => NilClass• true.class => TrueClass• false.class => FalseClass• (1..10).class => Range• /hello/.class => Regexp• Fixnum.class => Class• Class.class => Class %)) WHAT!!
Ruby :: truly object oriented
• nil.to_s => “”• nil.to_i => 0• nil.nil? => true• nil.blank? => true (Rails extension)• In statements (if, case, etc.) only nil and false evaluated
as FALSE
Ruby :: nil is an object
Ruby :: syntax• Almost everything can be written in different ways
• Easy things stay clean and easy• Difficult things maintain readability
• Parentheses are optional• find_by_name 'Matz'• find_by_name('Matz')
• Blocks• { |a| #do something with a }• do |a|
• #do something with a
• end
• 1..5 eq Range.new(1,5) and /^Hi/ eq Regexp.new(“^Hi”)
Ruby :: syntax sugar• Did you ever do?
• puts “Hello, World!”
• puts - is it a language construct?• It’s a method defined in Kernel :)
• public, private, protected - language constructs?• No! They are class methods!
• +, -, *, ==, etc. are methods too :)• 1 + 2 equivalent to 1.+(2) equivalent to 1.send :+, 2
• =, .., ..., !, not, &&, and, ||, or, !=, !~ What about these?• These are REAL operators
• Ready to know the truth?
Ruby :: classes
class MyClass def name “MyClass” endend
MyClass = Class.new do def name “MyClass” endend
• Classes are instances of a class Class• Class.ancestors =>
• [Class, Module, Object, Kernel, BasicObject]
• Classes in Ruby are always open• Change them any time (avoid monkey patching core
classes)
Ruby :: open classes
nil.dance #=> NoMethodError
• Rails adds many handy methods to core Ruby classes:• blank?, present?, presence, etc.
class NilClass def dance “Spin” endend
nil.dance #=> “Spin”
• Ruby has NO multiple inheritance• Ruby has single inheritance + MIXINS• By default all classes inherit from Object• Object inherit from BasicObject (ruby 1.9)• Object.instance_methods.size => 112• BasicObject.instance_methods.size => 7
Ruby :: inheritance
Ruby :: inheritance, message dispatching
BasicObject
Object
MyClassmy_object.send :dancemy_object.method_missing
• What happens if method not found?
• kate.dance• kate.send :dance
• Exception raised: NoMethodError
• self = current object• Every method has 3 parts: object.do_the_thing(10)
• object - receiver• do_the_thing - message• 10 - arguments• receiver is self, if not explicit receiver given
• What method_missing can be useful for• Person.find_by_name(‘Matz’)• Write DSL (XML generators)• Proxy pattern• Method delgation
Ruby :: self & method missing
• A namespace for constants (such as classes)• A place to define methods (can be later used by a class or
an object)• Unlike a class, can’t have instances & instance variables• Class (as a class name) inherit from class Module
• Class (as a class name) has more functionality (#new for example)
• A key element of MIXIN
Ruby :: modules
module Dance def do_the_trick “Back flip” endend
Dance = Module.new do def do_the_trick “Back flip” endend
• Mixins are used widely in Ruby• Please behave like Enumerable: include Enumerable
Ruby :: MIXINS
class Band include Enumerable attr_accessor :members def each(&block) members.each{ |member| block.call(member) } endend
find | detectfind_all | selectmap | collectinject, rejectall? any? one? none?min max
AND MORE
metallica = Band.newmetallica.members = [‘James’, ‘Lars’, ‘Kirk’, ‘Robert’]metallica.find_all { |m| m.size > 4 }#=> [‘James’, ‘Robert’]
Ruby :: MIXINS• What happens when you include a module?• class Band;end• Band.ancestors => [Band, Object, Kernel, BasicObject]
• class Band• include Enumerable• end
• Band.ancestors =>• [Band, Enumerable, Object, Kernel, BasicObject]
• Ruby creates an anonymous proxy class (“include” class) containing the module’s methods: Enumerable
• Ruby inserts this proxy class in the inheritance chain right above current class: Band < Enumerable < Object …
Ruby :: MIXIN• Try to solve this
module A def name; “I’m A”; endend
Object
Object
MyClass
module B def name; “I’m B”; endend
class MyClass include A Include Bend
MyClass.new.name => “I’m B”
A
A
Object
B
Ruby :: MIXINS & eigenclasses• You can extend individual object with module’s methodsmodule Dancer def dance “Swing” endend
class Catend
jane = Cat.newjane.extend(Dancer)jane.dance #=> “Swing”
• Ruby created eigenclass, and added proxy class• (jane eigenclass) < (Dancer) < Cat
bob = Cat.newbob.dance #=> ???NoMethodError
Ruby :: MIXINS & eigenclasses• You can define methods on individual objects
class Catend
jane = Cat.newdef jane.dance “Crawl”endjane.dance #=> “Crawl”
bob = Cat.newbob.dance #=> NoMethodError
• jane’s eigenclass now has #dance method
Ruby :: Blocks• Blocks are heavily used in Ruby• Callbacks
• after_create lambda { |u| u.send_message }• before_validate lambda { |u| u.clear_name }
• Template functions• [1,2,3].map { |a| a * 2 } #=> [2,4,6]• [1,2,3].all? { |a| a > 2 } #=> false
• Wrapping logic• File.open(‘hello.txt’, ‘w’) { |f| f.puts ‘Hello’ }
• Lazy evaluation• Rails.cache.fetch(:jobs) { heavy_task }
Ruby :: alternative syntax• Array
• [‘cat’, ‘dog’]• %w(cat dog) - parentheses may vary: %w{..} %w[..] %w!..!• %W(cat #{var} dog)
• Regexp• /^cat/• %r(^cat) - parentheses may vary
• String• ‘Hello, World’ and “Hello, Word!”• %q(Hello, World!) - single quoted string• %Q(Hello, World!) - double quoted string (interpolation occurs)• %(Hello, World!)• <<HERE_DOC• Hello, World!• HERE_DOC
Ruby :: Q&A• Q&A?
Ruby :: what do I do next?• http://tryruby.org• http://koans.heroku.com