TDC 2012 - Patterns e Anti-Patterns em Ruby
-
Upload
fabio-akita -
Category
Technology
-
view
2.502 -
download
5
description
Transcript of TDC 2012 - Patterns e Anti-Patterns em Ruby
![Page 1: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/1.jpg)
Donets BasinMina de carvão-Ucrânia
Genius is the gold in the mine; talent is the miner who works and brings it out.Lady Marguerite Blessington
“”
![Page 2: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/2.jpg)
![Page 3: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/3.jpg)
@akitaonrails
Ruby e Ruby on Rails - 2006
Rails Summit Latin America - 2008
RubyConf Brasil - 2010
![Page 4: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/4.jpg)
![Page 5: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/5.jpg)
![Page 6: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/6.jpg)
![Page 7: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/7.jpg)
Patterns e Anti-Patternsem Ruby
Fabio Akita (@akitaonrails)
![Page 8: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/8.jpg)
![Page 9: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/9.jpg)
Pattern PADRÃO
![Page 10: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/10.jpg)
Pattern PADRÃO
Default
STANDARD
![Page 11: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/11.jpg)
“Pattern”
![Page 12: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/12.jpg)
![Page 13: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/13.jpg)
![Page 14: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/14.jpg)
“Standard”
![Page 15: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/15.jpg)
Christopher Alexander
![Page 16: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/16.jpg)
"...each pattern represents our current best guess ... to solve the problem presented. ..., the patterns are still hypotheses, all ... of them -and are therefore all tentative, all free to evolve under the impact of new experience and observation"
—Christopher Alexander, A Pattern Language, p. xv
![Page 17: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/17.jpg)
ERB
require 'erubis'
def render_erb(filepath) content = File.read(filepath) template = Erubis::Eruby.new(content) context = { title: "Hello World", paragraph: "This is an ERB template." } output = template.evaluate(context)end
puts render_erb("sample.erb")
![Page 18: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/18.jpg)
ERB
<html> <head><title><%= @title %></title></head> <body> <p><%= @paragraph %></p> </body></html>
<html> <head><title>Hello World</title></head> <body> <p>This is an ERB template.</p> </body></html>
![Page 19: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/19.jpg)
Markdown
require 'rdiscount'
def render_markdown(filepath) content = File.read(filepath) template = RDiscount.new(content) output = template.to_htmlend
puts render_markdown("sample.md")
![Page 20: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/20.jpg)
Markdown
# Hello World
This is a Markdown example
* [Markdown](http://daringfireball.net/projects/markdown/syntax/)
<h1>Hello World</h1>
<p>This is a Markdown example</p>
<ul><li><a href="http://daringfireball.net/projects/markdown/syntax/">Markdown</a></li></ul>
![Page 21: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/21.jpg)
def render(filepath) case filepath when /erb$/ then render_erb(filepath) when /md$/ then render_markdown(filepath) when /sass$/ then render_sass(filepath) ... endend
puts render("sample.erb")
![Page 22: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/22.jpg)
Strategy
![Page 23: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/23.jpg)
![Page 24: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/24.jpg)
Template Engines supported by Tilt
ENGINE FILE EXTENSIONS REQUIRED LIBRARIES-------------------------- ----------------------- ----------------------------ERB .erb, .rhtml none (included ruby stdlib)Interpolated String .str none (included ruby core)Erubis .erb, .rhtml, .erubis erubisHaml .haml hamlSass .sass haml (< 3.1) or sass (>= 3.1)Scss .scss haml (< 3.1) or sass (>= 3.1)Less CSS .less lessBuilder .builder builderLiquid .liquid liquidRDiscount .markdown, .mkd, .md rdiscountRedcarpet .markdown, .mkd, .md redcarpetBlueCloth .markdown, .mkd, .md blueclothKramdown .markdown, .mkd, .md kramdownMaruku .markdown, .mkd, .md marukuRedCloth .textile redclothRDoc .rdoc rdocRadius .radius radiusMarkaby .mab markabyNokogiri .nokogiri nokogiriCoffeeScript .coffee coffee-script (+ javascript)Creole (Wiki markup) .wiki, .creole creoleWikiCloth (Wiki markup) .wiki, .mediawiki, .mw wikiclothYajl .yajl yajl-ruby
![Page 25: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/25.jpg)
ERB and Markdown through Tilt
require 'tilt'
template = Tilt.new("sample.erb")context = { title: "Hello World", paragraph: "This is an ERB template." }output = template.render(context)
puts output
template = Tilt.new("sample.md")output = template.render
puts output
![Page 26: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/26.jpg)
Same example as previously
require 'tilt'
template = Tilt::ErubisTemplate.new("sample.erb")context = { title: "Hello World", paragraph: "This is an ERB template." }output = template.render(context)
puts output
template = Tilt::RDiscountTemplate.new("sample.md")output = template.render
puts output
![Page 27: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/27.jpg)
tilt.rb
module Tilt ... @preferred_mappings = Hash.new @template_mappings = Hash.new { |h, k| h[k] = [] }
# Hash of template path pattern => template implementation class mappings. def self.mappings @template_mappings end ... # Register a template implementation by file extension. def self.register(template_class, *extensions) if template_class.respond_to?(:to_str) # Support register(ext, template_class) too extensions, template_class = [template_class], extensions[0] end
extensions.each do |ext| ext = normalize(ext) mappings[ext].unshift(template_class).uniq! end end ...
![Page 28: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/28.jpg)
Tilt#register
require 'tilt/string'register StringTemplate, 'str'
require 'tilt/erb'register ERBTemplate, 'erb', 'rhtml'register ErubisTemplate, 'erb', 'rhtml', 'erubis'
require 'tilt/haml'register HamlTemplate, 'haml'
require 'tilt/css'register SassTemplate, 'sass'register ScssTemplate, 'scss'register LessTemplate, 'less'
...
![Page 29: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/29.jpg)
Tilt#[]
> Tilt["erb"]=> Tilt::ErubisTemplate
> Tilt["md"]=> Tilt::RDiscountTemplate
> Tilt["haml"]=> Tilt::HamlTemplate
> Tilt['coffee']=> Tilt::CoffeeScriptTemplate
![Page 30: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/30.jpg)
Tilt overrided #new
module Tilt ... # Create a new template for the given # file using the file's extension # to determine the the template mapping. def self.new(file, line=nil, options={}, &block) if template_class = self[file] template_class.new(file, line, options, &block) else fail "No template engine registered for #{File.basename(file)}" end end
![Page 31: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/31.jpg)
Factory
![Page 32: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/32.jpg)
Tilt::Template Lint
module Tilt # Base class for template implementations. # Subclasses must implement the #prepare method and one # of the #evaluate or #precompiled_template methods. class Template ... def render(scope=Object.new, locals={}, &block) evaluate scope, locals || {}, &block end
protected def prepare; ... end def evaluate(scope, locals, &block); ... end def precompiled(locals); ... end def precompiled_template(locals); ... end def precompiled_preamble(locals); ... end def precompiled_postamble(locals); ''; end def compiled_method(locals_keys); ... end endend
![Page 33: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/33.jpg)
Tilt::RedClothTemplate Implementation
module Tilt # RedCloth implementation. See: # http://redcloth.org/ class RedClothTemplate < Template def self.engine_initialized? defined? ::RedCloth end
def initialize_engine require_template_library 'redcloth' end
def prepare @engine = RedCloth.new(data) @output = nil end
def evaluate(scope, locals, &block) @output ||= @engine.to_html end endend
![Page 34: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/34.jpg)
Adapter
![Page 35: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/35.jpg)
Simple Web
Mongrel
Thin
Webrick
Rails
Sinatra
Ramaze
CGI
![Page 36: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/36.jpg)
Simple Web
Mongrel
Thin
Webrick
Rails
Sinatra
Ramaze
CGI
![Page 37: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/37.jpg)
Simple Web
Mongrel
Thin
Webrick
Rails
Sinatra
Ramaze
CGIRack
![Page 38: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/38.jpg)
Minimal Rack Compliant
class HelloWorld def call(env) [200, {"Content-Type" => "text/plain"}, ["Hello world!"]] endend
hello_world = ->(env) { [200, {"Content-Type" => "text/plain"}, ["Hello world!"]] }
![Page 39: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/39.jpg)
rackup app.ru
hello_world = ->(env) { [200, {"Content-Type" => "text/html"}, ["<h1>Hello world!</h1>"]] }
use Rack::ContentType, "text/html"use Rack::ShowExceptionsuse Rack::Auth::Basic, "Rack Demo" do |username, password| 'secret' == passwordend
# Setup Rackrun Rack::URLMap.new( { "/hello" => hello_world, "/" => Rack::File.new( "index.html" )} )
![Page 40: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/40.jpg)
rackup app.ru
module Rack class ContentType include Rack::Utils
def initialize(app, content_type = "text/html") @app, @content_type = app, content_type end
def call(env) status, headers, body = @app.call(env) headers = Utils::HeaderHash.new(headers)
unless STATUS_WITH_NO_ENTITY_BODY.include?(status) headers['Content-Type'] ||= @content_type end
[status, headers, body] end endend
![Page 41: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/41.jpg)
rake middleware (Rails)
use ActionDispatch::Staticuse Rack::Lock...use Rack::Runtimeuse Rack::MethodOverrideuse ActionDispatch::RequestIduse Rails::Rack::Loggeruse ActionDispatch::ShowExceptionsuse ActionDispatch::DebugExceptionsuse ActionDispatch::RemoteIpuse ActionDispatch::Reloaderuse ActionDispatch::Callbacksuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacheuse ActionDispatch::Cookiesuse ActionDispatch::Session::CookieStoreuse ActionDispatch::Flashuse ActionDispatch::ParamsParseruse ActionDispatch::Headuse Rack::ConditionalGetuse Rack::ETaguse ActionDispatch::BestStandardsSupportuse Warden::Manageruse OmniAuth::Strategies::Twitteruse OmniAuth::Strategies::Facebookrun Rubyconf2012::Application.routes
![Page 42: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/42.jpg)
Chain of Responsibility
![Page 43: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/43.jpg)
class Relationship attr_accessor :state def initialize @state = :dating end def get_married make_vows @state = :married eat_wedding_cake end def get_divorced @state = :divorced end
def make_vows; "I do"; end def eat_wedding_cake; "Yummy"; endend
![Page 44: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/44.jpg)
class Relationship attr_accessor :state def initialize @state = :dating end def get_married raise "Must date before marry" unless @state == :dating make_vows @state = :married eat_wedding_cake end def get_divorced raise "Must be married before divorce" unless @state == :married @state = :divorced end
def make_vows; "I do"; end def eat_wedding_cake; "Yummy"; endend
![Page 45: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/45.jpg)
![Page 46: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/46.jpg)
class Relationship include AASM
aasm do state :dating, initial: true state :married state :divorced
event :get_married, :before => :make_vows, :after => :eat_wedding_cake do transitions from: [:dating], to: :married end event :get_divorced do transitions from: [:married], to: :divorced end end def make_vows; "I do"; end def eat_wedding_cake; "Yummy"; endend
![Page 47: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/47.jpg)
class Relationship attr_accessor :dating, :married, :divorced def initialize @dating, @married, @divorced = true, false, false end def get_married raise "Must date before marry" unless dating make_vows @dating, @married = false, true eat_wedding_cake end def get_divorced raise "Must be married before divorce" unless married @married, @divorced = false, true end
def make_vows; "I do"; end def eat_wedding_cake; "Yummy"; endend
![Page 48: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/48.jpg)
State
![Page 49: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/49.jpg)
class SaleOrder attr_accessor :items, :value, :checkout_date def initialize(*args) @items, @value, @checkout_date = args endend
sale = SaleOrder.new( ['Biscuit', 'Cheese'], 15.0, "2012-07-07")
![Page 50: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/50.jpg)
require 'money'require 'time'class SaleOrder attr_reader :value, :checkout_date def initialize(options = {}) @items, @value, @checkout_date = [], Money.new(0.0, "USD"), nil self.items = options[:items] || [] self.value = options[:value] || 0.0 self.checkout_date = options[:checkout_date] end def items=(items); @items += items.dup; end def items(index); @items[index]; end def value=(value); @value = Money.new(value.to_f, "USD"); end def checkout_date=(date) @checkout_date = Date.parse(date) if date endend
sale = SaleOrder.new(items: ['Biscuit', 'Cheese'], value: 15.0, checkout_date: "2012-07-07")
![Page 51: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/51.jpg)
Primitive Obsession
![Page 52: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/52.jpg)
http://u.akita.ws/avdi-null
def slug(title) # 1 if title.nil? title.strip.downcase.tr_s('^[a-z0-9]', '-') end
# 2 title.strip.downcase.tr_s('^[a-z0-9]', '-') if title
# 3 (title || "").strip.downcase.tr_s('^[a-z0-9]', '-')
# 4 title.strip.downcase.tr_s('^[a-z0-9]', '-') rescue nilend
![Page 53: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/53.jpg)
ActiveSupport - Try
class Object def try(*a, &b) if a.empty? && block_given? yield self else public_send(*a, &b) end endend
class NilClass def try(*args) nil endend
![Page 54: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/54.jpg)
http://u.akita.ws/avdi-null
require 'active_support/core_ext/object/try'
def slug(title) title.try(:strip).try(:downcase). try(:tr_s, '^[a-z0-9]', '-')end
<%= title ? title.downcase : "" %>
<%= title.try(:downcase) %>
![Page 55: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/55.jpg)
http://u.akita.ws/avdi-null
class NullObject def method_missing(*args, &block) self end def to_a; []; end def to_s; ""; end def to_f; 0.0; end def to_i; 0; end def tap; self; end def to_value; nil; endend
def Maybe(value) value.nil? ? NullObject.new : valueend
class Object def to_value self endend
![Page 56: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/56.jpg)
http://u.akita.ws/avdi-null
def slug(title) Maybe(title).strip.downcase.tr_s('^[a-z0-9]', '-')end
def slug(title) title = Maybe(title) if title.to_value # do something useful end title.strip.downcase.tr_s('^[a-z0-9]', '-')end
![Page 57: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/57.jpg)
http://u.akita.ws/avdi-null
git clone git://github.com/akitaonrails/null.gitcd nullgem build null.gemspecgem install null-0.1.gem
> require 'null'> Maybe(someobj).foo.bar.something#=> null
> (100.0 / (NULL * 15.5) - 150)#=> null
object = Maybe(someobj)if object.truthy? # something usefulend
![Page 58: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/58.jpg)
Null Object
![Page 59: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/59.jpg)
class SalesOrder < Struct.new(:products, :total, :buyer_name) def html_receipt html_items = products.inject("") do |html, item| html += "<li>#{item}</li>" end
html = %{<h1>Thanks for the Purchase #{buyer_name}!</h1> <p>You purchased:</p> <ul> #{html_items} </ul> <p>Total: $#{total}</p>} end end
order = SalesOrder.new(["Bacon", "Cheese"], 10.0, "John Doe" )
![Page 60: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/60.jpg)
> order.html_receipt
=> "<h1>Thanks for the Purchase John Doe!</h1> <p>You purchased:</p> <ul> <li>Bacon</li><li>Cheese</li> </ul> <p>Total: $10.0</p>"
![Page 61: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/61.jpg)
class SalesOrder < Struct.new(:products, :total, :buyer_name) def html_receipt html_items = products.inject("") do |html, item| html += "<li>#{item}</li>" end
html = %{<h1>Thanks for the Purchase #{buyer_name}!</h1> <p>You purchased:</p> <ul> #{html_items} </ul> <p>Total: $#{total}</p>} end end
order = SalesOrder.new(["Bacon", "Cheese"], 10.0, "John Doe" )
![Page 62: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/62.jpg)
class SalesOrder < Struct.new(:products, :total, :buyer_name)end
class SalesOrderDecorator < SimpleDelegator def html_receipt html_items = products.inject("") do |html, item| html += "<li>#{item}</li>" end
html = %{<h1>Thanks for the Purchase #{buyer_name}!</h1> <p>You purchased:</p> <ul> #{html_items} </ul> <p>Total: $#{total}</p>} end end
order = SalesOrder.new(["Bacon", "Cheese"], 10.0, "John Doe" )decorated_order = SalesOrderDecorator.new(order)
![Page 63: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/63.jpg)
> decorated_order.html_receipt
=> "<h1>Thanks for the Purchase John Doe!</h1> <p>You purchased:</p> <ul> <li>Bacon</li><li>Cheese</li> </ul> <p>Total: $10.0</p>" > decorated_order.total
=> 10.0
> decorated_order.products
=> ["Bacon", "Cheese"]
![Page 64: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/64.jpg)
# originalorder = SalesOrder.new(["Bacon", "Cheese"], 10.0, "John Doe" )decorated_order = SalesOrderDecorator.new(order)
# newclass SalesOrderDecorator < SimpleDelegator def initialize(*args) if args.first.is_a?(SalesOrder) super(args.first) else order = SalesOrder.new(*args) super(order) end end ... end
decorated_order = SalesOrderDecorator.new(["Bacon", "Cheese"], 10.0, "John Doe" )decorated_order.html_receipt
![Page 65: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/65.jpg)
Decorator/Presenter
![Page 66: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/66.jpg)
Strategy
Factory
Adapter (Proxy, Bridge)
Chain of Responsibility
State
Primitive Obsession
Null Object
Decorator (Presenter)
![Page 67: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/67.jpg)
![Page 68: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/68.jpg)
![Page 69: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/69.jpg)
![Page 70: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/70.jpg)
![Page 71: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/71.jpg)
![Page 72: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/72.jpg)
![Page 73: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/73.jpg)
![Page 74: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/74.jpg)
![Page 75: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/75.jpg)
![Page 76: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/76.jpg)
![Page 78: TDC 2012 - Patterns e Anti-Patterns em Ruby](https://reader036.fdocuments.us/reader036/viewer/2022062513/55593064d8b42a543d8b48e5/html5/thumbnails/78.jpg)
www.codeminer42.com.br+55 11 3729 14 22
slideshare.net/akitaonrails
MUITO OBRIGADO