SlideShare a Scribd company logo
1 of 45
Download to read offline
Making and Breaking
  Web Services
   (with Ruby)
      Chris Wanstrath
          Err Free
     http://errfree.com
ttp://farm1.static.flickr.com/138/320699460_b8e7c1e7e6_o.jpg
SOAP
• Simple Object Access Protocol?
• Lies.
• Service Oriented Architecture Protocol
• wtf.
Newsletters!
“Outbound”

• Slow response time
• Duplication of data
• Hard to debug
• require ‘soap/wsdlDriver’
Ruby SOAP Library:
      Your Friend

• Creates methods on the fly
• Seems to work pretty well
• Transparently converts Ruby types to SOAP
  definitions
Ruby SOAP Library:
      Your Enemy

• Hard to debug (dump req/res to file)
• No one has ever used it
• There are not any alternatives
• The code is a jungle
Why use SOAP?


• One reason: legacy.
Wrapping SOAP
def update_user(email, subs = [], unsubs = [])
  client.updateUser(brand, email, email, demo, subs, unsubs)
end
Wrapping SOAP
def update_user(email, subs = [], unsubs = [])
  client.updateUser(brand, email, email, demo, subs, unsubs)
end




def get_user(email)
  client.getUser(email, brand)
end
Wrapping SOAP
def update_user(email, subs = [], unsubs = [])
  client.updateUser(brand, email, email, demo, subs, unsubs)
end




def get_user(email)
  client.getUser(email, brand)
end
Wrapping SOAP
def update_user(email, subs = [], unsubs = [])
  client.updateUser(brand, email, email, demo, subs, unsubs)
end




def get_user(email)
  client.getUser(email, brand)
end
Testing SOAP


• Use mocks
• Mocha: http://mocha.rubyforge.org
Testing SOAP

def test_get_user_should_hit_client
  email = 'chrisw@nstrath.com'
  Outbound.client.expects(:getUser).with(email, Outbound.brand)
  Outbound.get_user(email)
end
Testing SOAP

soap_methods = {
  :getUser    => true,
  :updateUser => true
}

Outbound.stubs(:client).returns(mock('SOAP Service', soap_methods))
Running a SOAP Server
       in Ruby
Just Kidding
Microformats!
• Your website is your API
• Plant classes in HTML
• Tell parsers what information is important
• http://microformats.org
hReview
hReview
<div id="review_16873" class="hreview">
  <h5 class="item"><span class="fn">Beringer California Collection White Merlot 20
  <abbr class="dtreviewed" title="20070420">(1 day ago)</abbr>
  <span class="reviewer vcard">
     <img class="photo" src="/assets/avatars/c19d1b2080f73765d420b461d3133ffa.jpg"
     <a class="url fn" href="/people/garyvaynerchuk">garyvaynerchuk</a>
  </span>
  <abbr class="rating" title="50.0">50.0<em>/100</em></abbr>
  <blockquote class="description">Had this in an industry event the other day, man
  <p class="tags">Tasting Tags:
  <a href="/tags/pink" rel="tag" class="rel-tag" title="view all wines with this t
  <a href="/tags/sugar" rel="tag" class="rel-tag" title="view all wines with this
</p>
</div>
hReview
<div id="review_16873" class="hreview">
  <h5 class="item"><span class="fn">Beringer California Collection White Merlot 20
  <abbr class="dtreviewed" title="20070420">(1 day ago)</abbr>
  <span class="reviewer vcard">
     <img class="photo" src="/assets/avatars/c19d1b2080f73765d420b461d3133ffa.jpg"
     <a class="url fn" href="/people/garyvaynerchuk">garyvaynerchuk</a>
  </span>
  <abbr class="rating" title="50.0">50.0<em>/100</em></abbr>
  <blockquote class="description">Had this in an industry event the other day, man
  <p class="tags">Tasting Tags:
  <a href="/tags/pink" rel="tag" class="rel-tag" title="view all wines with this t
  <a href="/tags/sugar" rel="tag" class="rel-tag" title="view all wines with this
</p>
</div>
mofo
$ sudo gem install mofo
Successfully installed mofo-0.2.2
$ irb -rubygems
>> require 'mofo/hreview'
=> true
>> review = HReview.find :first => 'http://corkd.com/wine/view/21670'
=> #<HReview:0x1598d04 ...>
>> review.properties
=> ["description", "item", "dtreviewed", "tags", "rating", "reviewer"]
>> review.rating
=> 50.0
>> review.item.fn
=> "Beringer California Collection White Merlot 2005"
>> review.reviewer.fn
=> "garyvaynerchuk"
mofo/hreview.rb
class HReview < Microformat
  one :version, :summary, :type, :dtreviewed,
      :rating, :description

 one :reviewer => HCard

  one :item! do
    one :fn
  end
end
microformat.rb
def collector
  collector = Hash.new([])
  def collector.method_missing(method, *classes)
    super unless %w(one many).include? method.to_s
    self[method] += Microformat.send(:break_out_hashes, classes)
  end
  collector
end
mofo supports...

              • xoxo
• hCard
              • geo
• hCalendar
              • adr
• hReview
              • xfn
• hEntry
• hResume
What else can they do?
Operator
Operator
Okay.
Hpricot




( by _why )
Hpricot
$ irb -rubygems -r'open-uri'
>> require 'hpricot'
=> true
>> page = Hpricot open('http://google.com')
=> #<Hpricot::Doc ...>
>> page.search(:a).size
=> 20
>> page.at(:a)
=> {elem <a href="/url?sa=p&pref=ig&pval=3
   &q=http://www.google.com/ig%3Fhl%3Den&usg=
   AFrqEzfPu3dYlSVsfjI7gUHePgEkcx_VXg">
   "Personalize this page" </a>}
Hpricot
Can use XPATH, CSS selectors, whatever, to search
Hpricot

>>   page = Hpricot(open('http://brainspl.at'))
=>   #<Hpricot::Doc ...>
>>   page.search('.post').size
=>   10
Hpricot
>>   corkd = 'http://corkd.com/wine/view/21670'
=>   'http://corkd.com/wine/view/21670'
>>   page = Hpricot(open(corkd))
=>   #<Hpricot::Doc ...>
>>   page.search('.hreview').size
=>   4
Hpricot/:mofo
>> page.at('.hreview').at('.item').at('.fn').inner_text
=> "Beringer California Collection White Merlot 2005"




>> review.item.fn
=> "Beringer California Collection White Merlot 2005"
Oh, you can use Hpricot
     for XML, too.
  <Export>
    <Product>
      <SKU>403276</SKU>
      <ItemName>Trivet</ItemName>
      <CollectionNo>0</CollectionNo>
      <Pages>0</Pages>
    </Product>
  </Export>
Oh, you can use Hpricot
         for XML, too.
fields = %w(SKU ItemName CollectionNo Pages)

doc = Hpricot(open("my.xml"))
(doc/:product).each do |xml_product|
  attributes = fields.inject({}) do |hash, field|
    hash.merge(field => xml_product.at(field).innerHTML)
  end
  Product.create(attributes)
end


        ( also there’s Hpricot::XML() )
But who uses XML?
Cheat!
     http://cheat.errtheblog.com


(insert short, live demo here)
Thanks
•   http://mofo.rubyforge.org

•   http://code.whytheluckystiff.net/hpricot

•   https://addons.mozilla.org/en-US/firefox/addon/4106

•   http://microformats.org

•   http://upcoming.yahoo.com/

•   http://corkd.com/

•   http://chow.com

•   http://chowhound.com
Thanks

•   http://ronrothman.com/gallery/cnet/cnet_neon

•   http://flickr.com/photos/bootbearwdc/466751240/

•   http://flickr.com/photos/segana/320699460/

•   http://flickr.com/photos/spiffariffic/456211526/

More Related Content

What's hot

Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2
RORLAB
 
Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2
RORLAB
 
Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101
Nando Vieira
 
Compatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensionsCompatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensions
Kai Cui
 
20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished
Yoichiro Sakurai
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
Mike Subelsky
 
Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2
RORLAB
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 

What's hot (20)

Excellent
ExcellentExcellent
Excellent
 
Action Controller Overview, Season 2
Action Controller Overview, Season 2Action Controller Overview, Season 2
Action Controller Overview, Season 2
 
RSpec
RSpecRSpec
RSpec
 
Even Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax ExperienceEven Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax Experience
 
RubyMotion
RubyMotionRubyMotion
RubyMotion
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2Action View Form Helpers - 1, Season 2
Action View Form Helpers - 1, Season 2
 
Damage Control
Damage ControlDamage Control
Damage Control
 
QA for PHP projects
QA for PHP projectsQA for PHP projects
QA for PHP projects
 
How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014How to test complex SaaS applications - The family july 2014
How to test complex SaaS applications - The family july 2014
 
Metaprogramming 101
Metaprogramming 101Metaprogramming 101
Metaprogramming 101
 
Compatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensionsCompatibility Detector Tool of Chrome extensions
Compatibility Detector Tool of Chrome extensions
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modules
 
20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished20111030i phonedeveloperworkshoppublished
20111030i phonedeveloperworkshoppublished
 
javascript for backend developers
javascript for backend developersjavascript for backend developers
javascript for backend developers
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2Layouts and Rendering in Rails, Season 2
Layouts and Rendering in Rails, Season 2
 
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and JasmineRails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript using CoffeeScript, Backbone.js and Jasmine
 

Similar to Making and Breaking Web Services with Ruby

Socket applications
Socket applicationsSocket applications
Socket applications
João Moura
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
New Relic
 
Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)
True-Vision
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
Integration Test Cucumber + Webrat + Selenium
Integration Test Cucumber + Webrat + SeleniumIntegration Test Cucumber + Webrat + Selenium
Integration Test Cucumber + Webrat + Selenium
tka
 

Similar to Making and Breaking Web Services with Ruby (20)

Rails Performance
Rails PerformanceRails Performance
Rails Performance
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)Rails Presentation (Anton Dmitriyev)
Rails Presentation (Anton Dmitriyev)
 
Ruby MVC from scratch with Rack
Ruby MVC from scratch with RackRuby MVC from scratch with Rack
Ruby MVC from scratch with Rack
 
When To Use Ruby On Rails
When To Use Ruby On RailsWhen To Use Ruby On Rails
When To Use Ruby On Rails
 
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com RubyConsegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
 
Building Scalable Websites with Perl
Building Scalable Websites with PerlBuilding Scalable Websites with Perl
Building Scalable Websites with Perl
 
Perl web app 테스트전략
Perl web app 테스트전략Perl web app 테스트전략
Perl web app 테스트전략
 
Ruby on Rails in UbiSunrise
Ruby on Rails in UbiSunriseRuby on Rails in UbiSunrise
Ruby on Rails in UbiSunrise
 
Server side scripting smack down - Node.js vs PHP
Server side scripting smack down - Node.js vs PHPServer side scripting smack down - Node.js vs PHP
Server side scripting smack down - Node.js vs PHP
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?
 
Rails 4.0
Rails 4.0Rails 4.0
Rails 4.0
 
Michelin Starred Cooking with Chef
Michelin Starred Cooking with ChefMichelin Starred Cooking with Chef
Michelin Starred Cooking with Chef
 
ApacheCon 2005
ApacheCon 2005ApacheCon 2005
ApacheCon 2005
 
Integration Test Cucumber + Webrat + Selenium
Integration Test Cucumber + Webrat + SeleniumIntegration Test Cucumber + Webrat + Selenium
Integration Test Cucumber + Webrat + Selenium
 

More from err (7)

Inside GitHub
Inside GitHubInside GitHub
Inside GitHub
 
The Real-Time Web (and Other Buzzwords)
The Real-Time Web (and Other Buzzwords)The Real-Time Web (and Other Buzzwords)
The Real-Time Web (and Other Buzzwords)
 
Git: The Lean, Mean, Distributed Machine
Git: The Lean, Mean, Distributed MachineGit: The Lean, Mean, Distributed Machine
Git: The Lean, Mean, Distributed Machine
 
Kings of Code 2009
Kings of Code 2009Kings of Code 2009
Kings of Code 2009
 
Forbidden Fruit: A Taste of Ruby's ParseTree
Forbidden Fruit: A Taste of Ruby's ParseTreeForbidden Fruit: A Taste of Ruby's ParseTree
Forbidden Fruit: A Taste of Ruby's ParseTree
 
Kickin' Ass with Cache-Fu (without notes)
Kickin' Ass with Cache-Fu (without notes)Kickin' Ass with Cache-Fu (without notes)
Kickin' Ass with Cache-Fu (without notes)
 
Kickin' Ass with Cache-Fu (with notes)
Kickin' Ass with Cache-Fu (with notes)Kickin' Ass with Cache-Fu (with notes)
Kickin' Ass with Cache-Fu (with notes)
 

Recently uploaded

The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai KuwaitThe Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
daisycvs
 
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabiunwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
Abortion pills in Kuwait Cytotec pills in Kuwait
 

Recently uploaded (20)

How to Get Started in Social Media for Art League City
How to Get Started in Social Media for Art League CityHow to Get Started in Social Media for Art League City
How to Get Started in Social Media for Art League City
 
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai KuwaitThe Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
The Abortion pills for sale in Qatar@Doha [+27737758557] []Deira Dubai Kuwait
 
Falcon Invoice Discounting: Aviate Your Cash Flow Challenges
Falcon Invoice Discounting: Aviate Your Cash Flow ChallengesFalcon Invoice Discounting: Aviate Your Cash Flow Challenges
Falcon Invoice Discounting: Aviate Your Cash Flow Challenges
 
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165Lucknow Housewife Escorts  by Sexy Bhabhi Service 8250092165
Lucknow Housewife Escorts by Sexy Bhabhi Service 8250092165
 
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdfTVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
 
Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1Katrina Personal Brand Project and portfolio 1
Katrina Personal Brand Project and portfolio 1
 
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAIGetting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
 
HomeRoots Pitch Deck | Investor Insights | April 2024
HomeRoots Pitch Deck | Investor Insights | April 2024HomeRoots Pitch Deck | Investor Insights | April 2024
HomeRoots Pitch Deck | Investor Insights | April 2024
 
Falcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business GrowthFalcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business Growth
 
Escorts in Nungambakkam Phone 8250092165 Enjoy 24/7 Escort Service Enjoy Your...
Escorts in Nungambakkam Phone 8250092165 Enjoy 24/7 Escort Service Enjoy Your...Escorts in Nungambakkam Phone 8250092165 Enjoy 24/7 Escort Service Enjoy Your...
Escorts in Nungambakkam Phone 8250092165 Enjoy 24/7 Escort Service Enjoy Your...
 
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
Unveiling Falcon Invoice Discounting: Leading the Way as India's Premier Bill...
 
Falcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investorsFalcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investors
 
Famous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st CenturyFamous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st Century
 
Over the Top (OTT) Market Size & Growth Outlook 2024-2030
Over the Top (OTT) Market Size & Growth Outlook 2024-2030Over the Top (OTT) Market Size & Growth Outlook 2024-2030
Over the Top (OTT) Market Size & Growth Outlook 2024-2030
 
Arti Languages Pre Seed Teaser Deck 2024.pdf
Arti Languages Pre Seed Teaser Deck 2024.pdfArti Languages Pre Seed Teaser Deck 2024.pdf
Arti Languages Pre Seed Teaser Deck 2024.pdf
 
Organizational Transformation Lead with Culture
Organizational Transformation Lead with CultureOrganizational Transformation Lead with Culture
Organizational Transformation Lead with Culture
 
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDINGParadip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
Paradip CALL GIRL❤7091819311❤CALL GIRLS IN ESCORT SERVICE WE ARE PROVIDING
 
Phases of Negotiation .pptx
 Phases of Negotiation .pptx Phases of Negotiation .pptx
Phases of Negotiation .pptx
 
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabiunwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
 
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
 

Making and Breaking Web Services with Ruby

  • 1. Making and Breaking Web Services (with Ruby) Chris Wanstrath Err Free http://errfree.com
  • 3. SOAP • Simple Object Access Protocol? • Lies. • Service Oriented Architecture Protocol • wtf.
  • 5. “Outbound” • Slow response time • Duplication of data • Hard to debug • require ‘soap/wsdlDriver’
  • 6. Ruby SOAP Library: Your Friend • Creates methods on the fly • Seems to work pretty well • Transparently converts Ruby types to SOAP definitions
  • 7. Ruby SOAP Library: Your Enemy • Hard to debug (dump req/res to file) • No one has ever used it • There are not any alternatives • The code is a jungle
  • 8. Why use SOAP? • One reason: legacy.
  • 9.
  • 10. Wrapping SOAP def update_user(email, subs = [], unsubs = []) client.updateUser(brand, email, email, demo, subs, unsubs) end
  • 11. Wrapping SOAP def update_user(email, subs = [], unsubs = []) client.updateUser(brand, email, email, demo, subs, unsubs) end def get_user(email) client.getUser(email, brand) end
  • 12. Wrapping SOAP def update_user(email, subs = [], unsubs = []) client.updateUser(brand, email, email, demo, subs, unsubs) end def get_user(email) client.getUser(email, brand) end
  • 13. Wrapping SOAP def update_user(email, subs = [], unsubs = []) client.updateUser(brand, email, email, demo, subs, unsubs) end def get_user(email) client.getUser(email, brand) end
  • 14.
  • 15. Testing SOAP • Use mocks • Mocha: http://mocha.rubyforge.org
  • 16. Testing SOAP def test_get_user_should_hit_client email = 'chrisw@nstrath.com' Outbound.client.expects(:getUser).with(email, Outbound.brand) Outbound.get_user(email) end
  • 17. Testing SOAP soap_methods = { :getUser => true, :updateUser => true } Outbound.stubs(:client).returns(mock('SOAP Service', soap_methods))
  • 18. Running a SOAP Server in Ruby
  • 20. Microformats! • Your website is your API • Plant classes in HTML • Tell parsers what information is important • http://microformats.org
  • 22. hReview <div id="review_16873" class="hreview"> <h5 class="item"><span class="fn">Beringer California Collection White Merlot 20 <abbr class="dtreviewed" title="20070420">(1 day ago)</abbr> <span class="reviewer vcard"> <img class="photo" src="/assets/avatars/c19d1b2080f73765d420b461d3133ffa.jpg" <a class="url fn" href="/people/garyvaynerchuk">garyvaynerchuk</a> </span> <abbr class="rating" title="50.0">50.0<em>/100</em></abbr> <blockquote class="description">Had this in an industry event the other day, man <p class="tags">Tasting Tags: <a href="/tags/pink" rel="tag" class="rel-tag" title="view all wines with this t <a href="/tags/sugar" rel="tag" class="rel-tag" title="view all wines with this </p> </div>
  • 23. hReview <div id="review_16873" class="hreview"> <h5 class="item"><span class="fn">Beringer California Collection White Merlot 20 <abbr class="dtreviewed" title="20070420">(1 day ago)</abbr> <span class="reviewer vcard"> <img class="photo" src="/assets/avatars/c19d1b2080f73765d420b461d3133ffa.jpg" <a class="url fn" href="/people/garyvaynerchuk">garyvaynerchuk</a> </span> <abbr class="rating" title="50.0">50.0<em>/100</em></abbr> <blockquote class="description">Had this in an industry event the other day, man <p class="tags">Tasting Tags: <a href="/tags/pink" rel="tag" class="rel-tag" title="view all wines with this t <a href="/tags/sugar" rel="tag" class="rel-tag" title="view all wines with this </p> </div>
  • 24. mofo $ sudo gem install mofo Successfully installed mofo-0.2.2 $ irb -rubygems >> require 'mofo/hreview' => true >> review = HReview.find :first => 'http://corkd.com/wine/view/21670' => #<HReview:0x1598d04 ...> >> review.properties => ["description", "item", "dtreviewed", "tags", "rating", "reviewer"] >> review.rating => 50.0 >> review.item.fn => "Beringer California Collection White Merlot 2005" >> review.reviewer.fn => "garyvaynerchuk"
  • 25. mofo/hreview.rb class HReview < Microformat one :version, :summary, :type, :dtreviewed, :rating, :description one :reviewer => HCard one :item! do one :fn end end
  • 26. microformat.rb def collector collector = Hash.new([]) def collector.method_missing(method, *classes) super unless %w(one many).include? method.to_s self[method] += Microformat.send(:break_out_hashes, classes) end collector end
  • 27. mofo supports... • xoxo • hCard • geo • hCalendar • adr • hReview • xfn • hEntry • hResume
  • 28.
  • 29.
  • 30. What else can they do?
  • 33. Okay.
  • 35. Hpricot $ irb -rubygems -r'open-uri' >> require 'hpricot' => true >> page = Hpricot open('http://google.com') => #<Hpricot::Doc ...> >> page.search(:a).size => 20 >> page.at(:a) => {elem <a href="/url?sa=p&pref=ig&pval=3 &q=http://www.google.com/ig%3Fhl%3Den&usg= AFrqEzfPu3dYlSVsfjI7gUHePgEkcx_VXg"> "Personalize this page" </a>}
  • 36. Hpricot Can use XPATH, CSS selectors, whatever, to search
  • 37. Hpricot >> page = Hpricot(open('http://brainspl.at')) => #<Hpricot::Doc ...> >> page.search('.post').size => 10
  • 38. Hpricot >> corkd = 'http://corkd.com/wine/view/21670' => 'http://corkd.com/wine/view/21670' >> page = Hpricot(open(corkd)) => #<Hpricot::Doc ...> >> page.search('.hreview').size => 4
  • 39. Hpricot/:mofo >> page.at('.hreview').at('.item').at('.fn').inner_text => "Beringer California Collection White Merlot 2005" >> review.item.fn => "Beringer California Collection White Merlot 2005"
  • 40. Oh, you can use Hpricot for XML, too. <Export> <Product> <SKU>403276</SKU> <ItemName>Trivet</ItemName> <CollectionNo>0</CollectionNo> <Pages>0</Pages> </Product> </Export>
  • 41. Oh, you can use Hpricot for XML, too. fields = %w(SKU ItemName CollectionNo Pages) doc = Hpricot(open("my.xml")) (doc/:product).each do |xml_product| attributes = fields.inject({}) do |hash, field| hash.merge(field => xml_product.at(field).innerHTML) end Product.create(attributes) end ( also there’s Hpricot::XML() )
  • 43. Cheat! http://cheat.errtheblog.com (insert short, live demo here)
  • 44. Thanks • http://mofo.rubyforge.org • http://code.whytheluckystiff.net/hpricot • https://addons.mozilla.org/en-US/firefox/addon/4106 • http://microformats.org • http://upcoming.yahoo.com/ • http://corkd.com/ • http://chow.com • http://chowhound.com
  • 45. Thanks • http://ronrothman.com/gallery/cnet/cnet_neon • http://flickr.com/photos/bootbearwdc/466751240/ • http://flickr.com/photos/segana/320699460/ • http://flickr.com/photos/spiffariffic/456211526/