Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
Intro to Advanced Rubytwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
What makes Ruby                       special?twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Its expressive                                 5.times do                                   puts "Hello World"            ...
Its dynamic       class Person          [:first_name, :last_name, :gender].each do |method|            attr_accessor metho...
Its extendable         module KeywordSearch           def find_all_by_keywords(keywords)             self.where(["name lik...
Its flexible        def add(*args)          args.reduce(0){ |result, item| result + item}        end        add 1,1,1,1twit...
Its dangerous!                                  class String                                    def nil?                  ...
Our roadmap for today         • Requiring files         • Testing         • Message passing         • Classes vs Instances ...
requiretwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
require more functionality       Date.today.to_s       NoMethodError: undefined method today for       Date:Class       re...
Testingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
A simple Unit test          require test/unit          class PersonTest < Test::Unit::TestCase              def test_perso...
Make it fail first...          Loaded suite untitled          Started          E          Finished in 0.000325 seconds.    ...
Now write the code                                 class Person                                   attr_accessor :age      ...
And pass the test!               Loaded suite untitled               Started               .               Finished in 0.0...
Classes and Objects                 • A Ruby Class is an object of type Class                 • An Object is an instance o...
Instance vs class methods      class Person               class Person        def sleep                  def self.sleep   ...
Message passingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
.send     class Person                  p = Person.new       def name         @name                     p.send(:name)     ...
We reduce complexity with this.      class Sorter                         class Sorter        def move_higher             ...
Then we can add more methods.                                 class Sorter                                   def move_high...
Send and respond_to                class Person                  attr_accessor(:name)                end                p ...
Blocks and Lambdastwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Blockstwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Iteration                   people.each do |person|                     puts person.name                   end            ...
Encapsulation                             result = wrap(:p) do                                        "Hello world"       ...
yield can bind objects!                    navbar = Navbar.create do |menu|                      menu.add "Google", "http:...
Procs and Lambdastwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Delayed Execution      a = lambda{|phrase| puts "#{phrase} at #{Time.now}" }      puts a.call("Hello")      sleep 1      p...
Monkeypatchingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Reopen a class!         class Object           def blank?             self.nil? || self.to_s == ""           end          ...
Monkeypatching is an                 evil process!twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Instead, we use Modulestwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Modules             module OrElseMethods                 def blank?                   self.nil? || self.to_s == ""        ...
In Ruby, we don’t care              about the type... we              care about how the                 object works.twit...
Including modules on objects                      module NinjaBehaviors                        def attack                 ...
Extending classes with modules       module NinjaCreator          def new_ninja            puts "Ive created a new Ninja" ...
Person              vs   PersonNinjaRockStarAdmintwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Extending objects with modules      module NinjaBehaviors        def attack          puts "Youve been killed silently!"   ...
Extending objects with modules        ninja = Person.new        ninja.extend NinjaBehaviors        ninja.attack        roc...
Inject code without reopening!      module OrElseMethods         def blank?           self.nil? || self.to_s == ""        ...
self.included class access         module UserValidations           def self.included(base)             base.validates_pre...
Modules can’t contain          methods that overwrite            existing methods!twitter: bphoganemail: brianhogan at nap...
self.included + class_eval      class Person               module NoSave        def save          puts "Original save"    ...
Yes, that’s weird.twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Putting it all together            • Implement “before save” behavior - when we                 call “save” on our object,...
Demo        https://github.com/napcs/intro_to_advanced_rubytwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/...
Questions?twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
Próxima SlideShare
Cargando en…5
×

Intro To Advanced Ruby

3.743 visualizaciones

Publicado el

Intro talks never let you learn about the things that make a language truly cool. In this talk we'll discover how advanced features of Ruby help us write cleaner more modular code.

Publicado en: Tecnología
  • Sé el primero en comentar

Intro To Advanced Ruby

  1. 1. Intro to Advanced Rubytwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  2. 2. What makes Ruby special?twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  3. 3. Its expressive 5.times do puts "Hello World" endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  4. 4. Its dynamic class Person [:first_name, :last_name, :gender].each do |method| attr_accessor method end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  5. 5. Its extendable module KeywordSearch def find_all_by_keywords(keywords) self.where(["name like ?", "%" + keywords + "%"]) end end class Project < ActiveRecord::Base extend KeywordSearch end class Task < ActiveRecord::Base extend KeywordSearch endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  6. 6. Its flexible def add(*args) args.reduce(0){ |result, item| result + item} end add 1,1,1,1twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  7. 7. Its dangerous! class String def nil? self == "" end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  8. 8. Our roadmap for today • Requiring files • Testing • Message passing • Classes vs Instances • Blocks and Lambdas • Monkeypatching • Modulestwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  9. 9. requiretwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  10. 10. require more functionality Date.today.to_s NoMethodError: undefined method today for Date:Class require date => true Date.today.to_s => "2011-04-09"twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  11. 11. Testingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  12. 12. A simple Unit test require test/unit class PersonTest < Test::Unit::TestCase def test_person_under_16_cant_drive p = Person.new p.age = 15 assert !p.can_drive? end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  13. 13. Make it fail first... Loaded suite untitled Started E Finished in 0.000325 seconds.   1) Error: test_person_under_16_cannot_drive(PersonTest): NameError: uninitialized constant PersonTest::Person method test_person_under_16_cannot_drive in untitled document at line 6 1 tests, 0 assertions, 0 failures, 1 errorstwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  14. 14. Now write the code class Person attr_accessor :age def can_drive? self.age >= 16 end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  15. 15. And pass the test! Loaded suite untitled Started . Finished in 0.00028 seconds. 1 tests, 1 assertions, 0 failures, 0 errorstwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  16. 16. Classes and Objects • A Ruby Class is an object of type Class • An Object is an instance of a Class • Classes can have methods just like objects • These are often used as static methods.twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  17. 17. Instance vs class methods class Person class Person def sleep def self.sleep puts "ZZZZZZ" puts "ZZZZZZ" end end end end p = Person.new Person.sleep p.sleep "ZZZZZZ" "ZZZZZZ" => nil => niltwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  18. 18. Message passingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  19. 19. .send class Person p = Person.new def name @name p.send(:name) end def name=(input) p.send(:name=, "Homer") @name = input end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  20. 20. We reduce complexity with this. class Sorter class Sorter def move_higher def move_higher puts "moved one higher" puts "moved one higher" end end def move_lower def move_lower puts "moved lower" puts "moved lower" end end def move(type) def move(type) case type self.send "move_" + type when "higher" then move_higher end when "lower" then move_lower end end end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  21. 21. Then we can add more methods. class Sorter def move_higher puts "moved one higher" end def move_lower puts "moved lower" end def move_top puts "moved to the top" end def move_bottom puts "moved to the bottom" end def move(type) self.send "move_" + type end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  22. 22. Send and respond_to class Person attr_accessor(:name) end p = Person.new p.send(:name) if p.respond_to?(:name) p.send(:age) if p.respond_to?(:age)twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  23. 23. Blocks and Lambdastwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  24. 24. Blockstwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  25. 25. Iteration people.each do |person| puts person.name end people.select do |person| person.last_name == "Hogan" end adults = people.reject do |person| person.age <= 18 endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  26. 26. Encapsulation result = wrap(:p) do "Hello world" end puts result => "<p>Hello world</p>” def wrap(tag, &block) output = "<#{tag}>#{yield}</#{tag}>" endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  27. 27. yield can bind objects! navbar = Navbar.create do |menu| menu.add "Google", "http://www.google.com" menu.add "Amazon", "http://www.amazon.com" end class Menu class Navbar def self.create(&block) def add(name, link) menu = Menu.new @items ||= [] yield menu @items << "<li><a href=#{link}>#{name}</a></li>" menu.to_s(options) end end end def to_s(options) menu = @items.join("n") "<ul>n#{menu}n</ul>" end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  28. 28. Procs and Lambdastwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  29. 29. Delayed Execution a = lambda{|phrase| puts "#{phrase} at #{Time.now}" } puts a.call("Hello") sleep 1 puts a.call("Goodbye") Hello at Sat Apr 09 13:34:07 -0500 2011 Goodbye at Sat Apr 09 13:34:08 -0500 2011twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  30. 30. Monkeypatchingtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  31. 31. Reopen a class! class Object def blank? self.nil? || self.to_s == "" end def orelse(other) self.blank? ? other : self end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  32. 32. Monkeypatching is an evil process!twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  33. 33. Instead, we use Modulestwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  34. 34. Modules module OrElseMethods def blank? self.nil? || self.to_s == "" end def orelse(other) self.blank? ? other : self end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  35. 35. In Ruby, we don’t care about the type... we care about how the object works.twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  36. 36. Including modules on objects module NinjaBehaviors def attack puts "Youve been killed silently!" end end class Person include NinjaBehaviors end p = Person.new p.attacktwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  37. 37. Extending classes with modules module NinjaCreator def new_ninja puts "Ive created a new Ninja" end end class Person extend NinjaCreator end Person.new_ninjatwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  38. 38. Person vs PersonNinjaRockStarAdmintwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  39. 39. Extending objects with modules module NinjaBehaviors def attack puts "Youve been killed silently!" end end module RockStarBehaviors def trash_hotel_room puts "What a mess!" end endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  40. 40. Extending objects with modules ninja = Person.new ninja.extend NinjaBehaviors ninja.attack rockstar = Person.new rockstar.extend RockStarBehaviors rockstar.trash_hotel_room rockstar.extend NinjaBehaviors rockstar.attacktwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  41. 41. Inject code without reopening! module OrElseMethods def blank? self.nil? || self.to_s == "" end def orelse(other) self.blank? ? other : self end end Object.send :include, OrElseMethodstwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  42. 42. self.included class access module UserValidations def self.included(base) base.validates_presence_of :email, :login base.valudates_uniqueness_of :email, :login base.validates_confirmation_of :password end end class User < ActiveRecord::Base include UserValidations endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  43. 43. Modules can’t contain methods that overwrite existing methods!twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  44. 44. self.included + class_eval class Person module NoSave def save puts "Original save" def self.included(base) true base.class_eval do end def save end puts "New save" false end end end end Person.send :include, NoSavetwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  45. 45. Yes, that’s weird.twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  46. 46. Putting it all together • Implement “before save” behavior - when we call “save” on our object, we want to declare other methods we want to hook in. class Person before_save, :foo, lambda{|p| p.name = "test"}, SuperFilter endtwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  47. 47. Demo https://github.com/napcs/intro_to_advanced_rubytwitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114
  48. 48. Questions?twitter: bphoganemail: brianhogan at napcs.comhttp://spkr8.com/t/7114

×