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

Stop Reinventing The Wheel - The Ruby Standard Library


Published on

My talk from Ruby Hoedown MMX. We talked about the Ruby standard library and how sometimes we reinvent things when we have perfectly good tools waiting for us to use them.

Published in: Technology
  • Yes you are right. There are many research paper writing services available now. But almost services are fake and illegal. Only a genuine service will treat their customer with quality research papers. ⇒ ⇐
    Are you sure you want to  Yes  No
    Your message goes here
  • I'd advise you to use this service: ⇒ ⇐ The price of your order will depend on the deadline and type of paper (e.g. bachelor, undergraduate etc). The more time you have before the deadline - the less price of the order you will have. Thus, this service offers high-quality essays at the optimal price.
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ♥♥♥ ♥♥♥
    Are you sure you want to  Yes  No
    Your message goes here
  • Sex in your area is here: ❤❤❤ ❤❤❤
    Are you sure you want to  Yes  No
    Your message goes here

Stop Reinventing The Wheel - The Ruby Standard Library

  1. stop reinventing the wheel hidden gems in the ruby standard library brian hogan - @bphogan
  2. Twitter: @bphogan Web:
  3. What about this design? describe "the user" do it "gets an email when their account is activated" do # some stuff end end Twitter: @bphogan Web:
  4. Sometimes ideas evolve for the better. Twitter: @bphogan Web:
  5. Other times not so much. Twitter: @bphogan Web:
  6. In software we reinvent Twitter: @bphogan Web:
  7. How often is “better” really just opinion? Twitter: @bphogan Web:
  8. So, we’re not talking about always using what exists... Twitter: @bphogan Web:
  9. We’re talking about reinventing because of ignorance, hubris, or ego. Twitter: @bphogan Web:
  10. Ruby Standard Library Twitter: @bphogan Web:
  11. •FileUtils •Forwardable •Pathname •open-uri •TempFile •WEBrick Twitter: @bphogan Web:
  12. Working With The File System system("mkdir -p tmp/files") system("touch tmp/files/lockfile.lock") system("rm -rf tmp/files") Twitter: @bphogan Web:
  13. Make it platform- independent! require 'fileutils' FileUtils.mkdir_p("tmp/files") FileUtils.touch("tmp/files/lockfile.lock") FileUtils.rm_rf("tmp/files") Twitter: @bphogan Web:
  14. FileUtils Namespace for several file utility methods for copying, moving, removing, etc. Twitter: @bphogan Web:
  15. Where it’s used •Rake •Capistrano stuff •Sinatra Reloader gem •Compass Twitter: @bphogan Web:
  16. Where does it fall short? Twitter: @bphogan Web:
  17. Delegating Methods Calling methods on one class through another. User Profile name name Twitter: @bphogan Web:
  18. Here’s how Rails does it def delegate(*methods) options = methods.pop unless options.is_a?(Hash) && to = options[:to] raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)." end methods.each do |method| module_eval("def #{method}(*args, &block) n#{to}.__send__(#{method.inspect}, *args, &block)nendn", "(__DELEGATION__)", 1) end end Twitter: @bphogan Web:
  19. Here’s how Rails does it class User < ActiveRecord::Base has_one :profile delegate :name, :to => :profile end Twitter: @bphogan Web:
  20. Here’s how we could do it. require 'forwardable' class User < ActiveRecord::Base has_one :profile extend Forwardable def_delegator :profile, :bio, :bio end Twitter: @bphogan Web:
  21. Forwardable This library allows you delegate method calls to an object, on a method by method basis. Twitter: @bphogan Web:
  22. Where it’s used •MongoMapper •Rack::Client Twitter: @bphogan Web:
  23. Where does it fall short? Twitter: @bphogan Web:
  24. Working with Paths Twitter: @bphogan Web:
  25. Seen in tons of Rails apps... file = File.join(RAILS_ROOT, "config", "database.yml") config = YAML.load( Twitter: @bphogan Web:
  26. A better way file = Rails.root.join("config", "database.yml") config = YAML.load( Rails.root.class => Pathname Twitter: @bphogan Web:
  27. Pathname Library to simplify working with files and paths. Represents a pathname which locates a file in a filesystem. The pathname depends on OS: Unix, Windows, etc. Twitter: @bphogan Web:
  28. Neat stuff require 'pathname' p ="/usr/bin/ruby") size = p.size # 27662 isdir = # false dir = p.dirname # Pathname:/usr/bin base = p.basename # Pathname:ruby dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby] Twitter: @bphogan Web:
  29. Where it’s used •Rails •DataMapper •Warehouse •Webistrano •many many more Twitter: @bphogan Web:
  30. Grabbing Files Twitter: @bphogan Web:
  31. cURL? puts `curl key=zst64zkddsxafra0jz678g` Twitter: @bphogan Web:
  32. Not available everywhere, must handle redirects. Twitter: @bphogan Web:
  33. Treat URLs as files! require 'open-uri' url = "" puts open(url).read Twitter: @bphogan Web:
  34. open-uri Wraps net/http, net/https, and net/ftp. Twitter: @bphogan Web:
  35. Where it’s used •Everywhere. Twitter: @bphogan Web:
  36. Where does it fall short? Twitter: @bphogan Web:
  37. Temporary files Twitter: @bphogan Web:
  38. The hard way path = "" `curl #{path} > /tmp/template.html` s ="/tmp/template.html") puts s Twitter: @bphogan Web:
  39. Use TempFile require 'open-uri' require 'tempfile' url = "" tempfile ="template.html") tempfile.write open(url).read puts Twitter: @bphogan Web:
  40. Where it’s used •File uploading •Caching Twitter: @bphogan Web:
  41. Data structures Twitter: @bphogan Web:
  42. YAML loads to hashes require 'YAML' config = YAML.load("config.yml").read) puts config["company_name"] puts config["banner_image_url"] puts config["custom_css_url"] Twitter: @bphogan Web:
  43. Use OpenStruct! require 'ostruct' require 'YAML' config = YAML.load("config.yml").read) config = puts config.company_name puts config.banner_image_url puts config.custom_css_url Twitter: @bphogan Web:
  44. Don’t write your own “YAML-to-Object” thing (like I once did!) Twitter: @bphogan Web:
  45. Where it’s used •Fat Free CMS •ActiveMessaging •Adhearsion •AASM Twitter: @bphogan Web:
  46. Where does it fall short? Twitter: @bphogan Web:
  47. Watching Stuff Twitter: @bphogan Web:
  48. Rails? Twitter: @bphogan Web:
  49. def initialize super observed_descendants.each { |klass| add_observer!(klass) } end def self.method_added(method) method = method.to_sym if ActiveRecord::Callbacks::CALLBACKS.include?(method) self.observed_methods += [method] self.observed_methods.freeze end end protected def observed_descendants observed_classes.sum([]) { |klass| klass.descendants } end def observe_callbacks? self.class.observed_methods.any? end def add_observer!(klass) super define_callbacks klass if observe_callbacks? end def define_callbacks(klass) existing_methods = { |m| m.to_sym } observer = self observer_name ='/', '__') self.class.observed_methods.each do |method| callback = :"_notify_#{observer_name}_for_#{method}" unless existing_methods.include? callback klass.send(:define_method, callback) do # def _notify_user_observer_for_before_save observer.update(method, self) # observer.update(:before_save, self) end # end klass.send(method, callback) # before_save :_notify_user_observer_for_before_save end end end end end Twitter: @bphogan Web:
  50. Observer Provides a simple mechanism for one object to inform a set of interested third-party objects when its state changes. Twitter: @bphogan Web:
  51. How we do it require 'observer' class ConfirmationEmailer def update(account) puts "Sending confirmation mail to: '#{}'" # send the email mechanism end end Twitter: @bphogan Web:
  52. class Account include Observable attr_accessor :email, :active def initialize(email) = email = false add_observer end def activate_account! = true changed # <- This is important notify_observers self end end Twitter: @bphogan Web:
  53. Where does it fall short? Twitter: @bphogan Web:
  54. Serving Web Pages Twitter: @bphogan Web:
  55. Sinatra? require 'sinatra' set :public, "~/Sites" Twitter: @bphogan Web:
  56. How about this? s = => 3000, :DocumentRoot => "~/Sites") trap('INT') { s.shutdown }; s.start Twitter: @bphogan Web:
  57. How about an alias? alias serve="ruby -rwebrick -e"s = => 3000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start"" $ cd ~/Sites $ serve Twitter: @bphogan Web:
  58. Twitter: @bphogan Web:
  59. It also serves web apps Twitter: @bphogan Web:
  60. Your dev machine really needs Passenger running? Twitter: @bphogan Web:
  61. Where it’s used •Rails •Other frameworks Twitter: @bphogan Web:
  62. Where does it fall short? Twitter: @bphogan Web:
  63. Storing Data Twitter: @bphogan Web:
  64. PStore Persistent, transactional storage. Baked right in to Ruby’s standard library. Twitter: @bphogan Web:
  65. We can store stuff... require 'pstore' store ='links') links = %W{} store.transaction do store[:links] ||= [] links.each{|link| store[:links] << link} store[:last_modified] = end Twitter: @bphogan Web:
  66. and we can get it back. store ="links") store.transaction do links = store[:links] end puts links.join("n") Twitter: @bphogan Web:
  67. Where it’s used •Rails 1.x Twitter: @bphogan Web:
  68. Where does it fall short? Twitter: @bphogan Web:
  69. Better Wheels Twitter: @bphogan Web:
  70. Importing CSV files require 'csv''data.csv', 'r', ';') do |row| p row end Twitter: @bphogan Web:
  71. CSV is slow. “Use FasterCSV” Twitter: @bphogan Web:
  72. In Ruby 1.9, FasterCSV is the new CSV! Twitter: @bphogan Web:
  73. Working with Dates Twitter: @bphogan Web:
  74. How we do it today = birthday =, 10, 5) days_to_go = birthday - today time_until = birthday - today hours,minutes,seconds,frac = Date.day_fraction_to_time(time_until) Twitter: @bphogan Web:
  75. home_run home_run is an implementation of rubyʼs Date/ DateTime classes in C, with much better performance (20-200x) than the version in the standard library, while being almost completely compatible. Twitter: @bphogan Web:
  76. REXML Built-in library for parsing and creating XML. Twitter: @bphogan Web:
  77. How about HPricot, libxml- ruby, or Nokogiri. Twitter: @bphogan Web:
  78. ERb Templating language as part of the Standard Library. Twitter: @bphogan Web:
  79. require 'erb' template = <<-EOF <h1><%=@name %></h1> EOF @name = "AwesomeCo" puts template.result Twitter: @bphogan Web:
  80. Templating language != View language!!! Twitter: @bphogan Web:
  81. What can it do? •Generate JavaScript •Generate YAML •Generate ERb •Any type of proprietary data export Twitter: @bphogan Web:
  82. Where does it fall short? Twitter: @bphogan Web:
  83. Alternatives? •HAML •Liquid •ERubis •Tons of others Twitter: @bphogan Web:
  84. Test::Unit We have an awesome testing library as part of our standard library. Twitter: @bphogan Web:
  85. It’s pretty good. Anyone know of any alternatives? Twitter: @bphogan Web:
  86. Only a few. •RSpec •Bacon •Context / Contest / Shoulda / Matchy •Testy •Micronaut •Whatever someone writes next week Twitter: @bphogan Web:
  87. I use RSpec * * And I still use Test::Unit. Twitter: @bphogan Web:
  88. “Minitest is a minitest/unit is a small and fast replacement for ruby's huge and slow test/unit”. Twitter: @bphogan Web:
  89. If X sucks so bad, why do we write something else instead of fixing it? Twitter: @bphogan Web:
  90. We think we can do it better. Twitter: @bphogan Web:
  91. The original developer doesn’t want our help. Twitter: @bphogan Web:
  92. There’s a language barrier. Twitter: @bphogan Web:
  93. Challenge: Extend the Standard Library. Twitter: @bphogan Web:
  94. Make the wheels we have better. Twitter: @bphogan Web:
  95. That’s it. •Twitter: @bphogan •email: •web: •blog: •github: Twitter: @bphogan Web: