Brian Hogan discusses the Ruby standard library, highlighting its valuable features and the pitfalls of reinventing existing solutions due to ignorance or ego. He explores various libraries such as FileUtils, Forwardable, and OpenURI while emphasizing the importance of leveraging existing tools to improve efficiency in software development. Ultimately, he encourages developers to extend and enhance the standard library instead of creating new alternatives.
Download as KEY, PPTX
- 1 / 95

- 2 / 95

- 3 / 95

- 4 / 95

- 5 / 95

- 6 / 95

- 7 / 95

- 8 / 95

- 9 / 95

- 10 / 95

- 11 / 95

- 12 / 95

- 13 / 95

- 14 / 95

- 15 / 95

- 16 / 95

- 17 / 95

- 18 / 95

- 19 / 95

- 20 / 95

- 21 / 95

- 22 / 95

- 23 / 95

- 24 / 95

- 25 / 95

- 26 / 95

- 27 / 95

- 28 / 95

- 29 / 95

- 30 / 95

- 31 / 95

- 32 / 95

- 33 / 95

- 34 / 95

- 35 / 95

- 36 / 95

- 37 / 95

- 38 / 95

- 39 / 95

- 40 / 95

- 41 / 95

- 42 / 95

- 43 / 95

- 44 / 95

- 45 / 95

- 46 / 95

- 47 / 95

- 48 / 95

- 49 / 95

- 50 / 95

- 51 / 95

- 52 / 95

- 53 / 95

- 54 / 95

- 55 / 95

- 56 / 95

- 57 / 95

- 58 / 95

- 59 / 95

- 60 / 95

- 61 / 95

- 62 / 95

- 63 / 95

- 64 / 95

- 65 / 95

- 66 / 95

- 67 / 95

- 68 / 95

- 69 / 95

- 70 / 95

- 71 / 95

- 72 / 95

- 73 / 95

- 74 / 95

- 75 / 95

- 76 / 95

- 77 / 95

- 78 / 95

- 79 / 95

- 80 / 95

- 81 / 95

- 82 / 95

- 83 / 95

- 84 / 95

- 85 / 95

- 86 / 95

- 87 / 95

- 88 / 95

- 89 / 95

- 90 / 95

- 91 / 95

- 92 / 95

- 93 / 95

- 94 / 95

- 95 / 95


Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now
![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: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-18-320.jpg)
Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now
![Neat stuff
require 'pathname'
p = Pathname.new("/usr/bin/ruby")
size = p.size # 27662
isdir = p.directory? # false
dir = p.dirname # Pathname:/usr/bin
base = p.basename # Pathname:ruby
dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby]
Twitter: @bphogan
Web: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-28-320.jpg)
Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now
![YAML loads to hashes
require 'YAML'
config = YAML.load(Pathname.new("config.yml").read)
puts config["company_name"]
puts config["banner_image_url"]
puts config["custom_css_url"]
Twitter: @bphogan
Web: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-42-320.jpg)
Download now

Download now

Download now

Download now

Download now

Download now

Download now
![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 = klass.instance_methods.map { |m| m.to_sym }
observer = self
observer_name = observer.class.name.underscore.gsub('/', '__')
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: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-49-320.jpg)
Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now
![We can store stuff...
require 'pstore'
store = PStore.new('links')
links = %W{http://www.github.com
http://heroku.com
http://ruby-lang.org}
store.transaction do
store[:links] ||= []
links.each{|link| store[:links] << link}
store[:last_modified] = Time.now
end
Twitter: @bphogan
Web: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-65-320.jpg)
Download now
![and we can get it
back.
store = PStore.new("links")
store.transaction do
links = store[:links]
end
puts links.join("n")
Twitter: @bphogan
Web: http://www.napcs.com/](https://image.slidesharecdn.com/hoedown2010-100905091711-phpapp02/85/Stop-Reinventing-The-Wheel-The-Ruby-Standard-Library-66-320.jpg)
Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now

Download now
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: http://www.napcs.com/
- 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: http://www.napcs.com/
- 4.Sometimes ideas evolve for the better. Twitter: @bphogan Web: http://www.napcs.com/
- 5.Other times not so much. Twitter: @bphogan Web: http://www.napcs.com/
- 6.In software we reinvent Twitter: @bphogan Web: http://www.napcs.com/
- 7.How often is “better” really just opinion? Twitter: @bphogan Web: http://www.napcs.com/
- 8.So, we’re not talking about always using what exists... Twitter: @bphogan Web: http://www.napcs.com/
- 9.We’re talking about reinventing because of ignorance, hubris, or ego. Twitter: @bphogan Web: http://www.napcs.com/
- 10.Ruby Standard Library http://ruby-doc.org/stdlib/ Twitter: @bphogan Web: http://www.napcs.com/
- 11.•FileUtils •Forwardable •Pathname •open-uri •TempFile •WEBrick Twitter: @bphogan Web: http://www.napcs.com/
- 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: http://www.napcs.com/
- 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: http://www.napcs.com/
- 14.FileUtils Namespace for several file utility methods for copying, moving, removing, etc. Twitter: @bphogan Web: http://www.napcs.com/
- 15.Where it’s used •Rake •Capistrano stuff •Sinatra Reloader gem •Compass Twitter: @bphogan Web: http://www.napcs.com/
- 16.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 17.Delegating Methods Calling methods on one class through another. User Profile name name Twitter: @bphogan Web: http://www.napcs.com/
- 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: http://www.napcs.com/
- 19.Here’s how Rails does it class User < ActiveRecord::Base has_one :profile delegate :name, :to => :profile end Twitter: @bphogan Web: http://www.napcs.com/
- 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: http://www.napcs.com/
- 21.Forwardable This library allows you delegate method calls to an object, on a method by method basis. Twitter: @bphogan Web: http://www.napcs.com/
- 22.Where it’s used •MongoMapper •Rack::Client Twitter: @bphogan Web: http://www.napcs.com/
- 23.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 24.Working with Paths Twitter: @bphogan Web: http://www.napcs.com/
- 25.Seen in tons of Rails apps... file = File.join(RAILS_ROOT, "config", "database.yml") config = YAML.load(File.read(file)) Twitter: @bphogan Web: http://www.napcs.com/
- 26.A better way file = Rails.root.join("config", "database.yml") config = YAML.load(file.read) Rails.root.class => Pathname http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/ Twitter: @bphogan Web: http://www.napcs.com/
- 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: http://www.napcs.com/
- 28.Neat stuff require 'pathname' p = Pathname.new("/usr/bin/ruby") size = p.size # 27662 isdir = p.directory? # false dir = p.dirname # Pathname:/usr/bin base = p.basename # Pathname:ruby dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby] Twitter: @bphogan Web: http://www.napcs.com/
- 29.Where it’s used •Rails •DataMapper •Warehouse •Webistrano •many many more Twitter: @bphogan Web: http://www.napcs.com/
- 30.Grabbing Files Twitter: @bphogan Web: http://www.napcs.com/
- 31.cURL? puts `curl http://pastie.org/1131498.txt? key=zst64zkddsxafra0jz678g` Twitter: @bphogan Web: http://www.napcs.com/
- 32.Not available everywhere, must handle redirects. Twitter: @bphogan Web: http://www.napcs.com/
- 33.Treat URLs as files! require 'open-uri' url = "http://pastie.org/1131498.txt?key=zst64zkddsxafra0jz678g" puts open(url).read Twitter: @bphogan Web: http://www.napcs.com/
- 34.open-uri Wraps net/http, net/https, and net/ftp. Twitter: @bphogan Web: http://www.napcs.com/
- 35.Where it’s used •Everywhere. Twitter: @bphogan Web: http://www.napcs.com/
- 36.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 37.Temporary files Twitter: @bphogan Web: http://www.napcs.com/
- 38.The hard way path = "http://pastie.org/1131498.txt?key=zst64zkddsxafra0jz678g" `curl #{path} > /tmp/template.html` s = File.read("/tmp/template.html") puts s Twitter: @bphogan Web: http://www.napcs.com/
- 39.Use TempFile require 'open-uri' require 'tempfile' url = "http://pastie.org/1131498.txt?key=zst64zkddsxafra0jz678g" tempfile = Tempfile.new("template.html") tempfile.write open(url).read puts tempfile.open.read Twitter: @bphogan Web: http://www.napcs.com/
- 40.Where it’s used •File uploading •Caching Twitter: @bphogan Web: http://www.napcs.com/
- 41.Data structures Twitter: @bphogan Web: http://www.napcs.com/
- 42.YAML loads to hashes require 'YAML' config = YAML.load(Pathname.new("config.yml").read) puts config["company_name"] puts config["banner_image_url"] puts config["custom_css_url"] Twitter: @bphogan Web: http://www.napcs.com/
- 43.Use OpenStruct! require 'ostruct' require 'YAML' config = YAML.load(Pathname.new("config.yml").read) config = OpenStruct.new(config) puts config.company_name puts config.banner_image_url puts config.custom_css_url Twitter: @bphogan Web: http://www.napcs.com/
- 44.Don’t write your own “YAML-to-Object” thing (like I once did!) Twitter: @bphogan Web: http://www.napcs.com/
- 45.Where it’s used •Fat Free CMS •ActiveMessaging •Adhearsion •AASM Twitter: @bphogan Web: http://www.napcs.com/
- 46.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 47.Watching Stuff Twitter: @bphogan Web: http://www.napcs.com/
- 48.Rails? Twitter: @bphogan Web: http://www.napcs.com/
- 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 = klass.instance_methods.map { |m| m.to_sym } observer = self observer_name = observer.class.name.underscore.gsub('/', '__') 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: http://www.napcs.com/
- 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: http://www.napcs.com/
- 51.How we do it require 'observer' class ConfirmationEmailer def update(account) puts "Sending confirmation mail to: '#{account.email}'" # send the email mechanism end end Twitter: @bphogan Web: http://www.napcs.com/
- 52.class Account include Observable attr_accessor :email, :active def initialize(email) self.email = email self.active = false add_observer ConfirmationEmailer.new end def activate_account! self.active = true changed # <- This is important notify_observers self end end Twitter: @bphogan Web: http://www.napcs.com/
- 53.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 54.Serving Web Pages Twitter: @bphogan Web: http://www.napcs.com/
- 55.Sinatra? require 'sinatra' set :public, "~/Sites" Twitter: @bphogan Web: http://www.napcs.com/
- 56.How about this? s = WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => "~/Sites") trap('INT') { s.shutdown }; s.start Twitter: @bphogan Web: http://www.napcs.com/
- 57.How about an alias? alias serve="ruby -rwebrick -e"s = WEBrick::HTTPServer.new(:Port => 3000, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; s.start"" $ cd ~/Sites $ serve Twitter: @bphogan Web: http://www.napcs.com/
- 58.Twitter: @bphogan Web: http://www.napcs.com/
- 59.It also serves web apps Twitter: @bphogan Web: http://www.napcs.com/
- 60.Your dev machine really needs Passenger running? Twitter: @bphogan Web: http://www.napcs.com/
- 61.Where it’s used •Rails •Other frameworks Twitter: @bphogan Web: http://www.napcs.com/
- 62.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 63.Storing Data Twitter: @bphogan Web: http://www.napcs.com/
- 64.PStore Persistent, transactional storage. Baked right in to Ruby’s standard library. Twitter: @bphogan Web: http://www.napcs.com/
- 65.We can store stuff... require 'pstore' store = PStore.new('links') links = %W{http://www.github.com http://heroku.com http://ruby-lang.org} store.transaction do store[:links] ||= [] links.each{|link| store[:links] << link} store[:last_modified] = Time.now end Twitter: @bphogan Web: http://www.napcs.com/
- 66.and we can get it back. store = PStore.new("links") store.transaction do links = store[:links] end puts links.join("n") Twitter: @bphogan Web: http://www.napcs.com/
- 67.Where it’s used •Rails 1.x Twitter: @bphogan Web: http://www.napcs.com/
- 68.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 69.Better Wheels Twitter: @bphogan Web: http://www.napcs.com/
- 70.Importing CSV files require 'csv' CSV.open('data.csv', 'r', ';') do |row| p row end Twitter: @bphogan Web: http://www.napcs.com/
- 71.CSV is slow. “Use FasterCSV” Twitter: @bphogan Web: http://www.napcs.com/
- 72.In Ruby 1.9, FasterCSV is the new CSV! Twitter: @bphogan Web: http://www.napcs.com/
- 73.Working with Dates Twitter: @bphogan Web: http://www.napcs.com/
- 74.How we do it today = DateTime.now birthday = Date.new(2010, 10, 5) days_to_go = birthday - today time_until = birthday - today hours,minutes,seconds,frac = Date.day_fraction_to_time(time_until) http://www.techotopia.com/index.php/Working_with_Dates_and_Times_in_Ruby Twitter: @bphogan Web: http://www.napcs.com/
- 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. http://github.com/jeremyevans/home_run Twitter: @bphogan Web: http://www.napcs.com/
- 76.REXML Built-in library for parsing and creating XML. Twitter: @bphogan Web: http://www.napcs.com/
- 77.How about HPricot, libxml- ruby, or Nokogiri. http://www.rubyinside.com/ruby-xml-performance-benchmarks-1641.html Twitter: @bphogan Web: http://www.napcs.com/
- 78.ERb Templating language as part of the Standard Library. Twitter: @bphogan Web: http://www.napcs.com/
- 79.require 'erb' template = ERB.new <<-EOF <h1><%=@name %></h1> EOF @name = "AwesomeCo" puts template.result Twitter: @bphogan Web: http://www.napcs.com/
- 80.Templating language != View language!!! Twitter: @bphogan Web: http://www.napcs.com/
- 81.What can it do? •Generate JavaScript •Generate YAML •Generate ERb •Any type of proprietary data export Twitter: @bphogan Web: http://www.napcs.com/
- 82.Where does it fall short? Twitter: @bphogan Web: http://www.napcs.com/
- 83.Alternatives? •HAML •Liquid •ERubis •Tons of others Twitter: @bphogan Web: http://www.napcs.com/
- 84.Test::Unit We have an awesome testing library as part of our standard library. Twitter: @bphogan Web: http://www.napcs.com/
- 85.It’s pretty good. Anyone know of any alternatives? Twitter: @bphogan Web: http://www.napcs.com/
- 86.Only a few. •RSpec •Bacon •Context / Contest / Shoulda / Matchy •Testy •Micronaut •Whatever someone writes next week Twitter: @bphogan Web: http://www.napcs.com/
- 87.I use RSpec * * And I still use Test::Unit. Twitter: @bphogan Web: http://www.napcs.com/
- 88.“Minitest is a minitest/unit is a small and fast replacement for ruby's huge and slow test/unit”. Twitter: @bphogan Web: http://www.napcs.com/
- 89.If X sucks so bad, why do we write something else instead of fixing it? Twitter: @bphogan Web: http://www.napcs.com/
- 90.We think we can do it better. Twitter: @bphogan Web: http://www.napcs.com/
- 91.The original developer doesn’t want our help. Twitter: @bphogan Web: http://www.napcs.com/
- 92.There’s a language barrier. Twitter: @bphogan Web: http://www.napcs.com/
- 93.Challenge: Extend the Standard Library. Twitter: @bphogan Web: http://www.napcs.com/
- 94.Make the wheels we have better. Twitter: @bphogan Web: http://www.napcs.com/
- 95.That’s it. •Twitter: @bphogan •email: bphogan@gmail.com •web: http://www.napcs.com/ •blog: http://bphogan.com •github: http://github.com/napcs/ Twitter: @bphogan Web: http://www.napcs.com/