SlideShare una empresa de Scribd logo
1 de 48
Elegant APIs
Why your methods
should never
go missing
Presented by Andrew Timberlake
Elegant APIs


variable arguments
method_missing
blocks
instance_eval
Elegant APIs


variable arguments
method_missing
blocks
instance_eval
variable arguments   Elegant APIs




   method_missing
   blocks
   instance_eval
variable arguments   Elegant APIs

def method(arg1)
  #...
end
variable arguments   Elegant APIs

def method(arg1 = 1)
  #...
end
variable arguments            Elegant APIs

def method(arg1 = 1, arg2 = 2)
  #...
end
variable arguments                  Elegant APIs

def method(opts = {})
  options = {:arg1 => 1,
             :arg2 => 2}.merge(opts)
  #...
end
variable arguments                  Elegant APIs

def method(opts = {})
  options = {:arg1 => 1,
             :arg2 => 2}.merge(opts)
  #...
end


method :arg2 => 3
variable arguments                     Elegant APIs

#Active Record
User.create(:first_name => 'Andrew',
            :last_name => 'Timberlake')
Elegant APIs


variable arguments
method_missing
blocks
instance_eval
method_missing     Elegant APIs


   variable arguments


   blocks
   instance_eval
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts body['background']       #=> background:#FFF




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts body['background']       #=> background:#FFF
puts body[:background]        #=> background:#FFF




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts body['background']       #=> background:#FFF
puts body[:background]        #=> background:#FFF
puts body['background-color'] #=> #FFF




                                  http://github.com/andrewtimberlake/css
method_missing                                  Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts   body['background']         #=>   background:#FFF
puts   body[:background]          #=>   background:#FFF
puts   body['background-color']   #=>   #FFF
puts   body.background            #=>   background:#FFF




                                        http://github.com/andrewtimberlake/css
method_missing                                  Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts   body['background']         #=>   background:#FFF
puts   body[:background]          #=>   background:#FFF
puts   body['background-color']   #=>   #FFF
puts   body.background            #=>   background:#FFF
puts   body.background_color      #=>   #FFF




                                        http://github.com/andrewtimberlake/css
method_missing                                  Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts   body['background']         #=>   background:#FFF
puts   body[:background]          #=>   background:#FFF
puts   body['background-color']   #=>   #FFF
puts   body.background            #=>   background:#FFF
puts   body.background_color      #=>   #FFF
puts   body.backgroundColor       #=>   #FFF




                                        http://github.com/andrewtimberlake/css
method_missing                                  Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

puts   body['background']         #=>   background:#FFF
puts   body[:background]          #=>   background:#FFF
puts   body['background-color']   #=>   #FFF
puts   body.background            #=>   background:#FFF
puts   body.background_color      #=>   #FFF
puts   body.backgroundColor       #=>   #FFF
puts   body.background.color      #=>   #FFF




                                        http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

body.background.image = 'url(image.png)'




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

css = CSS::Parser.parse("body { background: #FFF }")
body = css['body']

body.background.image = 'url(image.png)'
puts body.background #=> background:#FFF url(image.png)




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

def method_missing(method_name, *args, &block)
  get(normalize_property_name(method_name.to_s))
end




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

def respond_to?(method_name, include_private = false)
  property_name = normalize_property_name(method_name.to_s)

  default_properties.keys.include?(property_name)
end




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

def respond_to?(method_name, include_private = false)
  property_name = normalize_property_name(method_name.to_s)

  default_properties.keys.include?(property_name) || super
end




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

def method_missing(method_name, *args, &block)
  property_name = method_name.to_s

  if respond_to?(method_name)
    property_name = normalize_property_name(property_name)
    get(property_name)
  end
end




                                  http://github.com/andrewtimberlake/css
method_missing                            Elegant APIs

def method_missing(method_name, *args, &block)
  property_name = method_name.to_s

  if respond_to?(method_name)
    property_name = normalize_property_name(property_name)
    get(property_name)
  else
    super
  end
end




                                  http://github.com/andrewtimberlake/css
method_missing                             Elegant APIs

def method_missing(method_name, *args, &block)
  property_name = method_name.to_s
  setter = property_name.chomp!('=')

  if respond_to?(method_name)
    property_name = normalize_property_name(property_name)

    if setter
       @properties[property_name] = ...
    else
      get(property_name)
    end
  else
    super
  end
end
                                   http://github.com/andrewtimberlake/css
Elegant APIs


variable arguments
method_missing
blocks
instance_eval
blocks              Elegant APIs


   variable arguments
   method_missing


   instance_eval
blocks                                   Elegant APIs

ec2 = Awsum::Ec2.new('123456', '654321')
ec2.run_instances 'ami-123456'




                                     http://github.com/internuity/awsum
blocks                                   Elegant APIs

ec2 = Awsum::Ec2.new('123456', '654321')
ec2.run_instances 'ami-123456'

region = ec2.region('eu-west')
region.run_instances 'ami-123456'
region.create_volume 'eu-west-1a'
region.allocate_address




                                     http://github.com/internuity/awsum
blocks                                      Elegant APIs

region = ec2.region('eu-west')
region.run_instances 'ami-123456'
region.create_volume 'eu-west-1a'
region.allocate_address

ec2.region('eu-west').use do |region|
  region.run_instances 'ami-123456'
  region.create_volume 'eu-west-1a'
  region.allocate_address
end




                                        http://github.com/internuity/awsum
blocks                                      Elegant APIs

ec2.region('eu-west').use do |region|
  run_instances
end

class Awsum::Ec2::Region
  def use(&block)
    old_host = @ec2.host
    @ec2.host = end_point
    yield self
  ensure
    @ec2.host = old_host
  end
end




                                        http://github.com/internuity/awsum
blocks                                      Elegant APIs

ec2.region('eu-west').use do |region|
  region.run_instances 'ami-123456'
  region.create_volume 'eu-west-1a'
  region.allocate_address
end




                                        http://github.com/internuity/awsum
blocks                                      Elegant APIs

ec2.region('eu-west').use do |region|
  region.run_instances 'ami-123456'
  region.create_volume 'eu-west-1a'
  region.allocate_address
end
ec2.region('eu-west').use do
  run_instances 'ami-123456'
  create_volume 'eu-west-1a'
  allocate_address
end




                                        http://github.com/internuity/awsum
Elegant APIs


variable arguments
method_missing
blocks
instance_eval
instance_eval        Elegant APIs


    variable arguments
    method_missing
    blocks
instance_eval                      Elegant APIs

ec2.region('eu-west').use do
  run_instances
end

class Awsum::Ec2::Region
  def use(&block)
    old_host = @ec2.host
    @ec2.host = end_point
    instance_eval(&block)
  ensure
    @ec2.host = old_host
  end
end




                               http://github.com/internuity/awsum
instance_eval                             Elegant APIs

ec2.region('eu-west').use do
  run_instances
end

class Awsum::Ec2::Region
  def use(&block)
    old_host = @ec2.host
    @ec2.host = end_point
    block.arity < 1 ? instance_eval(&block) : block[self]
  ensure
    @ec2.host = old_host
  end
end




                                      http://github.com/internuity/awsum
instance_eval                             Elegant APIs

class Awsum::Ec2::Region
  def use(&block)
    if block_given?
      begin
         old_host = @ec2.host
         @ec2.host = end_point
         block.arity < 1 ? instance_eval(&block) : block[self]
      ensure
         @ec2.host = old_host
      end
    else
      @ec2.host = end_point
      self
    end
  end
end
                                      http://github.com/internuity/awsum
instance_eval                      Elegant APIs

ec2.region('eu-west').use do
  run_instances
end




                               http://github.com/internuity/awsum
instance_eval                      Elegant APIs

ec2.region('eu-west').use do
  run_instances
end

ec2.region('eu-west') do
  run_instances
end




                               http://github.com/internuity/awsum
instance_eval                            Elegant APIs

ec2.region('eu-west') do
  run_instances
end

def region(region_name)
  region = regions(region_name)[0]
end




                                     http://github.com/internuity/awsum
instance_eval                            Elegant APIs

ec2.region('eu-west') do
  run_instances
end

def region(region_name, &block)
  region = regions(region_name)[0]
  if block_given?
    region.use(&block)
  else
    region
  end
end




                                     http://github.com/internuity/awsum
instance_eval                            Elegant APIs

class Awsum::Ec2::Region
  def method_missing(method_name, *args, &block)
    use do
      @ec2.send(method_name, *args, &block)
    end
  end

  def respond_to?(method_name,
                  include_private = false)
    @ec2.respond_to?(method_name, include_private) 
                     || super
  end
end




                                     http://github.com/internuity/awsum
Elegant APIs

     Inspiration
     (recommended reading)


     Ruby Best Practices
http://ruby best practices book.com
Practicing Ruby newsletter
  http://letter.ly/practicing-ruby


   Thanks Gregory Brown
Elegant APIs


                Thank you
                  twitter:   @atimberlake
  email:   andrew@andrewtimberlake.com

        web:   http://andrewtimberlake.com
code:   http://github.com/andrewtimberlake

Más contenido relacionado

La actualidad más candente

ISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみたISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみた
memememomo
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
Luca Mearelli
 
Power Theming
Power ThemingPower Theming
Power Theming
drkdn
 

La actualidad más candente (20)

AngularJS Tips&Tricks
AngularJS Tips&TricksAngularJS Tips&Tricks
AngularJS Tips&Tricks
 
Exploiting Php With Php
Exploiting Php With PhpExploiting Php With Php
Exploiting Php With Php
 
ISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみたISUCONアプリを Pythonで書いてみた
ISUCONアプリを Pythonで書いてみた
 
To Batch Or Not To Batch
To Batch Or Not To BatchTo Batch Or Not To Batch
To Batch Or Not To Batch
 
Controlling The Cloud With Python
Controlling The Cloud With PythonControlling The Cloud With Python
Controlling The Cloud With Python
 
A Little Backbone For Your App
A Little Backbone For Your AppA Little Backbone For Your App
A Little Backbone For Your App
 
Web Scraping is BS
Web Scraping is BSWeb Scraping is BS
Web Scraping is BS
 
An introduction to Rex - FLOSS UK DevOps York 2015
An introduction to Rex - FLOSS UK DevOps York 2015An introduction to Rex - FLOSS UK DevOps York 2015
An introduction to Rex - FLOSS UK DevOps York 2015
 
Dancer's Ecosystem
Dancer's EcosystemDancer's Ecosystem
Dancer's Ecosystem
 
Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)Functional Pearls 4 (YAPC::EU::2009 remix)
Functional Pearls 4 (YAPC::EU::2009 remix)
 
What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0What’s new in ECMAScript 6.0
What’s new in ECMAScript 6.0
 
Testing Jboss Seam Bottom Up
Testing Jboss Seam Bottom UpTesting Jboss Seam Bottom Up
Testing Jboss Seam Bottom Up
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
Hack in the Box Keynote 2006
Hack in the Box Keynote 2006Hack in the Box Keynote 2006
Hack in the Box Keynote 2006
 
Power Theming
Power ThemingPower Theming
Power Theming
 
Investigating Python Wats
Investigating Python WatsInvestigating Python Wats
Investigating Python Wats
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
JSON and the APInauts
JSON and the APInautsJSON and the APInauts
JSON and the APInauts
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
 

Destacado (7)

Practica 17
Practica 17Practica 17
Practica 17
 
Tema2
Tema2Tema2
Tema2
 
Photoshop for Photographers
Photoshop for PhotographersPhotoshop for Photographers
Photoshop for Photographers
 
He was there all the time
He was there all the timeHe was there all the time
He was there all the time
 
Practica 17
Practica 17Practica 17
Practica 17
 
Why join Cpl?
Why join Cpl?Why join Cpl?
Why join Cpl?
 
Practica 17
Practica 17Practica 17
Practica 17
 

Similar a Elegant APIs

Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
Jano Suchal
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
Clinton Dreisbach
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
Edgar Suarez
 

Similar a Elegant APIs (20)

All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine YardHow I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
 
Practical Celery
Practical CeleryPractical Celery
Practical Celery
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Ruby 2.0
Ruby 2.0Ruby 2.0
Ruby 2.0
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
Blocks by Lachs Cox
Blocks by Lachs CoxBlocks by Lachs Cox
Blocks by Lachs Cox
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
Attributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active recordAttributes Unwrapped: Lessons under the surface of active record
Attributes Unwrapped: Lessons under the surface of active record
 
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
 
Desarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutosDesarrollando aplicaciones web en minutos
Desarrollando aplicaciones web en minutos
 
Ruby - Uma Introdução
Ruby - Uma IntroduçãoRuby - Uma Introdução
Ruby - Uma Introdução
 
Lettering js
Lettering jsLettering js
Lettering js
 

Último

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Último (20)

Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 

Elegant APIs

  • 1. Elegant APIs Why your methods should never go missing Presented by Andrew Timberlake
  • 4. variable arguments Elegant APIs method_missing blocks instance_eval
  • 5. variable arguments Elegant APIs def method(arg1) #... end
  • 6. variable arguments Elegant APIs def method(arg1 = 1) #... end
  • 7. variable arguments Elegant APIs def method(arg1 = 1, arg2 = 2) #... end
  • 8. variable arguments Elegant APIs def method(opts = {}) options = {:arg1 => 1, :arg2 => 2}.merge(opts) #... end
  • 9. variable arguments Elegant APIs def method(opts = {}) options = {:arg1 => 1, :arg2 => 2}.merge(opts) #... end method :arg2 => 3
  • 10. variable arguments Elegant APIs #Active Record User.create(:first_name => 'Andrew', :last_name => 'Timberlake')
  • 12. method_missing Elegant APIs variable arguments blocks instance_eval
  • 13. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] http://github.com/andrewtimberlake/css
  • 14. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF http://github.com/andrewtimberlake/css
  • 15. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF http://github.com/andrewtimberlake/css
  • 16. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF puts body['background-color'] #=> #FFF http://github.com/andrewtimberlake/css
  • 17. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF puts body['background-color'] #=> #FFF puts body.background #=> background:#FFF http://github.com/andrewtimberlake/css
  • 18. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF puts body['background-color'] #=> #FFF puts body.background #=> background:#FFF puts body.background_color #=> #FFF http://github.com/andrewtimberlake/css
  • 19. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF puts body['background-color'] #=> #FFF puts body.background #=> background:#FFF puts body.background_color #=> #FFF puts body.backgroundColor #=> #FFF http://github.com/andrewtimberlake/css
  • 20. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] puts body['background'] #=> background:#FFF puts body[:background] #=> background:#FFF puts body['background-color'] #=> #FFF puts body.background #=> background:#FFF puts body.background_color #=> #FFF puts body.backgroundColor #=> #FFF puts body.background.color #=> #FFF http://github.com/andrewtimberlake/css
  • 21. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] body.background.image = 'url(image.png)' http://github.com/andrewtimberlake/css
  • 22. method_missing Elegant APIs css = CSS::Parser.parse("body { background: #FFF }") body = css['body'] body.background.image = 'url(image.png)' puts body.background #=> background:#FFF url(image.png) http://github.com/andrewtimberlake/css
  • 23. method_missing Elegant APIs def method_missing(method_name, *args, &block) get(normalize_property_name(method_name.to_s)) end http://github.com/andrewtimberlake/css
  • 24. method_missing Elegant APIs def respond_to?(method_name, include_private = false) property_name = normalize_property_name(method_name.to_s) default_properties.keys.include?(property_name) end http://github.com/andrewtimberlake/css
  • 25. method_missing Elegant APIs def respond_to?(method_name, include_private = false) property_name = normalize_property_name(method_name.to_s) default_properties.keys.include?(property_name) || super end http://github.com/andrewtimberlake/css
  • 26. method_missing Elegant APIs def method_missing(method_name, *args, &block) property_name = method_name.to_s if respond_to?(method_name) property_name = normalize_property_name(property_name) get(property_name) end end http://github.com/andrewtimberlake/css
  • 27. method_missing Elegant APIs def method_missing(method_name, *args, &block) property_name = method_name.to_s if respond_to?(method_name) property_name = normalize_property_name(property_name) get(property_name) else super end end http://github.com/andrewtimberlake/css
  • 28. method_missing Elegant APIs def method_missing(method_name, *args, &block) property_name = method_name.to_s setter = property_name.chomp!('=') if respond_to?(method_name) property_name = normalize_property_name(property_name) if setter @properties[property_name] = ... else get(property_name) end else super end end http://github.com/andrewtimberlake/css
  • 30. blocks Elegant APIs variable arguments method_missing instance_eval
  • 31. blocks Elegant APIs ec2 = Awsum::Ec2.new('123456', '654321') ec2.run_instances 'ami-123456' http://github.com/internuity/awsum
  • 32. blocks Elegant APIs ec2 = Awsum::Ec2.new('123456', '654321') ec2.run_instances 'ami-123456' region = ec2.region('eu-west') region.run_instances 'ami-123456' region.create_volume 'eu-west-1a' region.allocate_address http://github.com/internuity/awsum
  • 33. blocks Elegant APIs region = ec2.region('eu-west') region.run_instances 'ami-123456' region.create_volume 'eu-west-1a' region.allocate_address ec2.region('eu-west').use do |region| region.run_instances 'ami-123456' region.create_volume 'eu-west-1a' region.allocate_address end http://github.com/internuity/awsum
  • 34. blocks Elegant APIs ec2.region('eu-west').use do |region| run_instances end class Awsum::Ec2::Region def use(&block) old_host = @ec2.host @ec2.host = end_point yield self ensure @ec2.host = old_host end end http://github.com/internuity/awsum
  • 35. blocks Elegant APIs ec2.region('eu-west').use do |region| region.run_instances 'ami-123456' region.create_volume 'eu-west-1a' region.allocate_address end http://github.com/internuity/awsum
  • 36. blocks Elegant APIs ec2.region('eu-west').use do |region| region.run_instances 'ami-123456' region.create_volume 'eu-west-1a' region.allocate_address end ec2.region('eu-west').use do run_instances 'ami-123456' create_volume 'eu-west-1a' allocate_address end http://github.com/internuity/awsum
  • 38. instance_eval Elegant APIs variable arguments method_missing blocks
  • 39. instance_eval Elegant APIs ec2.region('eu-west').use do run_instances end class Awsum::Ec2::Region def use(&block) old_host = @ec2.host @ec2.host = end_point instance_eval(&block) ensure @ec2.host = old_host end end http://github.com/internuity/awsum
  • 40. instance_eval Elegant APIs ec2.region('eu-west').use do run_instances end class Awsum::Ec2::Region def use(&block) old_host = @ec2.host @ec2.host = end_point block.arity < 1 ? instance_eval(&block) : block[self] ensure @ec2.host = old_host end end http://github.com/internuity/awsum
  • 41. instance_eval Elegant APIs class Awsum::Ec2::Region def use(&block) if block_given? begin old_host = @ec2.host @ec2.host = end_point block.arity < 1 ? instance_eval(&block) : block[self] ensure @ec2.host = old_host end else @ec2.host = end_point self end end end http://github.com/internuity/awsum
  • 42. instance_eval Elegant APIs ec2.region('eu-west').use do run_instances end http://github.com/internuity/awsum
  • 43. instance_eval Elegant APIs ec2.region('eu-west').use do run_instances end ec2.region('eu-west') do run_instances end http://github.com/internuity/awsum
  • 44. instance_eval Elegant APIs ec2.region('eu-west') do run_instances end def region(region_name) region = regions(region_name)[0] end http://github.com/internuity/awsum
  • 45. instance_eval Elegant APIs ec2.region('eu-west') do run_instances end def region(region_name, &block) region = regions(region_name)[0] if block_given? region.use(&block) else region end end http://github.com/internuity/awsum
  • 46. instance_eval Elegant APIs class Awsum::Ec2::Region def method_missing(method_name, *args, &block) use do @ec2.send(method_name, *args, &block) end end def respond_to?(method_name, include_private = false) @ec2.respond_to?(method_name, include_private) || super end end http://github.com/internuity/awsum
  • 47. Elegant APIs Inspiration (recommended reading) Ruby Best Practices http://ruby best practices book.com Practicing Ruby newsletter http://letter.ly/practicing-ruby Thanks Gregory Brown
  • 48. Elegant APIs Thank you twitter: @atimberlake email: andrew@andrewtimberlake.com web: http://andrewtimberlake.com code: http://github.com/andrewtimberlake

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n