SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Our Presentation Will Begin Shortly

Rails AntiPatterns
Workshop
May 12, 2011


          Matt Reider, Director of Training
          Engine Yard


          Chad Pytel, Founder & CEO
          thoughtbot Inc.
Rake Tasks
Are you testing them?
What makes them hard to test?

   • Scripts that live outside app
   • Often have network and file access
   • Often have output
Example Task

namespace :twitter do
  task :search => :environment do
    puts "Searching twitter."
    Twitter.search("@cpytel").each do |result|
      puts "Processing #{result.inspect}."
      alert = Alert.create(:body => result)
      alert.save_cache_file!
    end
  end
  puts "All done!"
end
One possible way to test
context "rake twitter:search" do
  setup do
    # How slow is this going to be? Very.
    @out = `cd #{Rails.root} &&
           rake twitter:search 2>&1`
  end
should "print a message at the beginning" do
  assert_match /Searching/i, @out
end
should "find all tweets containing @cpytel" do
  # this one would be based entirely on luck.
end
This Has Problems

• Slow
• No mocking or stubbing available
• Task isn’t in a transaction
Basically, no sandboxing
How do we fix this?
Rake tasks are just Ruby
Move it all into the Model
class Alert < ActiveRecord::Base
  def self.create_all_from_twitter_search(output = $stdout)
    output.puts "Searching twitter."
    Twitter.search("@cpytel").each do |result|
      output.puts "Processing #{result.inspect}."
      alert = create(:body => result)
      alert.save_cache_file!
    end
    output.puts "All done!"
  end

  def save_cache_file!
    # Removes a file from the filesystem.
  end
end
The Task is Nice and Skinny

namespace :twitter do
  task :search => :environment do
    Alert.create_all_from_twitter_search
  end
end
Testing is Pretty Normal

# test/unit/alert_test.rb
class AlertTest < ActiveSupport::TestCase
  context "create_all_from_twitter_search" do
    setup do
      # Make sure none of the tests below hit the
      # network or touch the filesystem.
      Alert.any_instance.stubs(:save_cache_file!)
      Twitter.stubs(:search).returns([])
      @output = StringIO.new
    end
should "print a message at the beginning" do
  Alert.create_all_from_twitter_search(@output)
  assert_match /Searching/i, @output.string
end
should "save some cache files" do
  Twitter.stubs(:search).returns(["one"])
  alert = mock("alert")
  alert.expects(:save_cache_file!)
  Alert.stubs(:create).returns(alert)
  Alert.create_all_from_twitter_search(@output)
end
should "find all tweets containing @cpytel" do
  Twitter.expects(:search).
          with("@cpytel").
          returns(["body"])
  Alert.create_all_from_twitter_search(@output)
end
We can mock and stub!
We can use normal tools!


• FakeWeb/WebMock
• FileUtils::NoWrite
In Summary

• You can test drive development of
  your rake tasks
• Rake tasks should live inside a
  model (or class)
Views
Know Your Helpers
Know How They Change
# Edit form
<%= form_for :user,
             :url => user_path(@user),
             :html => {:method => :put} do |form| %>
<%= form_for @user do |form| %>
<!-- posts/index.html.erb -->
<% @posts.each do |post| -%>
  <h2><%= post.title %></h2>
  <%= format_content post.body %>
  <p>
    <%= link_to 'Email author',
                mail_to(post.user.email) %>
  </p>
<% end -%>
Move the post content
    into a partial
<!-- posts/index.html.erb -->
<% @posts.each do |post| -%>
  <%= render :partial => 'post', :object => :post %>
<% end -%>

<!-- posts/_post.erb -->
<h2><%= post.title %></h2>
<%= format_content post.body %>
<p><%= link_to 'Email author',
mail_to(post.user.email) %></p>
Looping was built
  into render
<!-- posts/index.html.erb -->
<%= render :partial => 'post', :collection => @posts %>

<!-- posts/_post.erb -->
<h2><%= post.title %></h2>
<%= format_content post.body %>
<p>
  <%= link_to 'Email author',
              mail_to(post.user.email) %>
</p>
<!-- posts/index.html.erb -->
<%= render :partial => 'post', :collection => @posts %>

<!-- posts/_post.erb -->
<h2><%= post.title %></h2>
<%= format_content post.body %>
<p>
  <%= link_to 'Email author',
              mail_to(post.user.email) %>
</p>
<%= render :partial => @posts %>
<%= render @posts %>
Dynamic Page Titles
<!-- layouts/application.html.erb -->
<head>
  <title>
    Acme Widgets : TX-300 Utility Widget
  </title>
</head>
class PagesController < ApplicationController
  def show
    @widget = Widgets.find(params[:id])
    @title = @widget.name
  end
end

<!-- layouts/application.html.erb -->
<head>
  <title>Acme Widgets : <%= @title %></title>
</head>
This is all View
There is a Helper
<!-- layouts/application.html.erb -->
<head>
  <title>
    Acme Widgets : <%= yield(:title) %>
  </title>
</head>

<!-- widgets/show.html.erb -->
<% content_for :title, @widget.title %>
Default Title
<!-- layouts/application.html.erb -->
<head>
  <title>
    Acme Widgets : <%= yield(:title) || "Home" %>
  </title>
</head>
What else can we use
      this for?
<!-- layouts/application.html.erb -->
<div class="sidebar">
  This is content for the sidebar.
  <%= link_to "Your Account", account_url %>
</div>

<div class="main">
  The main content of the page
</div>
<!-- layouts/application.html.erb -->
<%= yield(:sidebar) %>

<div class="main">
  The main content of the page
</div>

<!-- layouts/application.html.erb -->
<% content_for :sidebar do %>
  <div class="sidebar">
    This is content for the sidebar.
    <%= link_to "Your Account", account_url %>
  </div>
<% end %>
Avoid Duplication
<!-- layouts/application.html.erb -->
<div class="sidebar">
  <%= yield(:sidebar) %>
</div>

<div class="main">
  The main content of the page
</div>

<!-- layouts/application.html.erb -->
<% content_for :sidebar do %>
  This is content for the sidebar.
  <%= link_to "Your Account", account_url %>
<% end %>
Conditional Sidebar
<!-- layouts/application.html.erb -->
<% if content_for?(:sidebar) -%>
  <div class="sidebar">
    <%= yield(:sidebar) %>
  </div>
<% end -%>

<div class="main">
  The main content of the page
</div>

<!-- app/views/products/show.html.erb -->
<% content_for :sidebar do %>
  This is content for the sidebar.
  <%= link_to "Your Account", account_url %>
<% end %>
Upcoming Classes


Zero to Rails 3 in four days
•May 23-26
•Virtual

Rails AntiPatterns
•Best Practices
•Boston – June 6 & 7
•San Francisco – June 13 & 14




   Learn more at: Engineyard.com/university

Weitere ähnliche Inhalte

Was ist angesagt?

Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à RubyMicrosoft
 
SproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFestSproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFesttomdale
 
Introduccion app engine con python
Introduccion app engine con pythonIntroduccion app engine con python
Introduccion app engine con pythonsserrano44
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creationbenalman
 
Plugin jQuery, Design Patterns
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design PatternsRobert Casanova
 
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)andrewnacin
 
Hooked on WordPress: WordCamp Columbus
Hooked on WordPress: WordCamp ColumbusHooked on WordPress: WordCamp Columbus
Hooked on WordPress: WordCamp ColumbusShawn Hooper
 
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 2RORLAB
 
Denver emberjs-sept-2015
Denver emberjs-sept-2015Denver emberjs-sept-2015
Denver emberjs-sept-2015Ron White
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with CucumberBen Mabey
 
Powershell to the People #suguk
Powershell to the People #sugukPowershell to the People #suguk
Powershell to the People #sugukChris McKinley
 
16.mysql stored procedures in laravel
16.mysql stored procedures in laravel16.mysql stored procedures in laravel
16.mysql stored procedures in laravelRazvan Raducanu, PhD
 
Creating Themes
Creating ThemesCreating Themes
Creating ThemesDaisyOlsen
 
Build a bot workshop async primer - php[tek]
Build a bot workshop  async primer - php[tek]Build a bot workshop  async primer - php[tek]
Build a bot workshop async primer - php[tek]Adam Englander
 
Web development with django - Basics Presentation
Web development with django - Basics PresentationWeb development with django - Basics Presentation
Web development with django - Basics PresentationShrinath Shenoy
 
PowerShell with SharePoint 2013 and Office 365 - EPC Group
PowerShell with SharePoint 2013 and Office 365 - EPC GroupPowerShell with SharePoint 2013 and Office 365 - EPC Group
PowerShell with SharePoint 2013 and Office 365 - EPC GroupEPC Group
 
How To Write a WordPress Plugin
How To Write a WordPress PluginHow To Write a WordPress Plugin
How To Write a WordPress PluginAndy Stratton
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le WagonAlex Benoit
 
The effective use of Django ORM
The effective use of Django ORMThe effective use of Django ORM
The effective use of Django ORMYaroslav Muravskyi
 

Was ist angesagt? (20)

Introduction à Ruby
Introduction à RubyIntroduction à Ruby
Introduction à Ruby
 
SproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFestSproutCore is Awesome - HTML5 Summer DevFest
SproutCore is Awesome - HTML5 Summer DevFest
 
Introduccion app engine con python
Introduccion app engine con pythonIntroduccion app engine con python
Introduccion app engine con python
 
jQuery Plugin Creation
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
 
Plugin jQuery, Design Patterns
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design Patterns
 
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)
 
Hooked on WordPress: WordCamp Columbus
Hooked on WordPress: WordCamp ColumbusHooked on WordPress: WordCamp Columbus
Hooked on WordPress: WordCamp Columbus
 
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
 
Denver emberjs-sept-2015
Denver emberjs-sept-2015Denver emberjs-sept-2015
Denver emberjs-sept-2015
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
 
Powershell to the People #suguk
Powershell to the People #sugukPowershell to the People #suguk
Powershell to the People #suguk
 
16.mysql stored procedures in laravel
16.mysql stored procedures in laravel16.mysql stored procedures in laravel
16.mysql stored procedures in laravel
 
Creating Themes
Creating ThemesCreating Themes
Creating Themes
 
Django
DjangoDjango
Django
 
Build a bot workshop async primer - php[tek]
Build a bot workshop  async primer - php[tek]Build a bot workshop  async primer - php[tek]
Build a bot workshop async primer - php[tek]
 
Web development with django - Basics Presentation
Web development with django - Basics PresentationWeb development with django - Basics Presentation
Web development with django - Basics Presentation
 
PowerShell with SharePoint 2013 and Office 365 - EPC Group
PowerShell with SharePoint 2013 and Office 365 - EPC GroupPowerShell with SharePoint 2013 and Office 365 - EPC Group
PowerShell with SharePoint 2013 and Office 365 - EPC Group
 
How To Write a WordPress Plugin
How To Write a WordPress PluginHow To Write a WordPress Plugin
How To Write a WordPress Plugin
 
Rails for Beginners - Le Wagon
Rails for Beginners - Le WagonRails for Beginners - Le Wagon
Rails for Beginners - Le Wagon
 
The effective use of Django ORM
The effective use of Django ORMThe effective use of Django ORM
The effective use of Django ORM
 

Ähnlich wie Rails Antipatterns | Open Session with Chad Pytel

You're Doing It Wrong
You're Doing It WrongYou're Doing It Wrong
You're Doing It Wrongbostonrb
 
Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)Joao Lucas Santana
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Turbogears Presentation
Turbogears PresentationTurbogears Presentation
Turbogears Presentationdidip
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsAlessandro Molina
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?brynary
 
Implement rich snippets in your webshop
Implement rich snippets in your webshopImplement rich snippets in your webshop
Implement rich snippets in your webshopArjen Miedema
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в MagentoMagecom Ukraine
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalystdwm042
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Ted Kulp
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
DRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersDRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersJames Gray
 
Resource and view
Resource and viewResource and view
Resource and viewPapp Laszlo
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 

Ähnlich wie Rails Antipatterns | Open Session with Chad Pytel (20)

You're Doing It Wrong
You're Doing It WrongYou're Doing It Wrong
You're Doing It Wrong
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)Desenvolvimento web com Ruby on Rails (parte 2)
Desenvolvimento web com Ruby on Rails (parte 2)
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Turbogears Presentation
Turbogears PresentationTurbogears Presentation
Turbogears Presentation
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Django crush course
Django crush course Django crush course
Django crush course
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 
Implement rich snippets in your webshop
Implement rich snippets in your webshopImplement rich snippets in your webshop
Implement rich snippets in your webshop
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
 
Practical catalyst
Practical catalystPractical catalyst
Practical catalyst
 
Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101Geek Moot '09 -- Smarty 101
Geek Moot '09 -- Smarty 101
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
DRYing Up Rails Views and Controllers
DRYing Up Rails Views and ControllersDRYing Up Rails Views and Controllers
DRYing Up Rails Views and Controllers
 
Resource and view
Resource and viewResource and view
Resource and view
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 

Mehr von Engine Yard

Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard
 
Getting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudGetting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudEngine Yard
 
Engine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performanceEngine Yard
 
Simplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentSimplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentEngine Yard
 
The Tao of Documentation
The Tao of DocumentationThe Tao of Documentation
The Tao of DocumentationEngine Yard
 
Innovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceInnovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceEngine Yard
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to RubyEngine Yard
 
JRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesJRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesEngine Yard
 
High Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedHigh Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedEngine Yard
 
Release Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionRelease Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionEngine Yard
 
JRuby Jam Session
JRuby Jam Session JRuby Jam Session
JRuby Jam Session Engine Yard
 
Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Engine Yard
 
JRuby: Apples and Oranges
JRuby: Apples and OrangesJRuby: Apples and Oranges
JRuby: Apples and OrangesEngine Yard
 
Developing a Language
Developing a LanguageDeveloping a Language
Developing a LanguageEngine Yard
 
Debugging Ruby Systems
Debugging Ruby SystemsDebugging Ruby Systems
Debugging Ruby SystemsEngine Yard
 
Everything Rubinius
Everything RubiniusEverything Rubinius
Everything RubiniusEngine Yard
 
Rails Hosting and the Woes
Rails Hosting and the WoesRails Hosting and the Woes
Rails Hosting and the WoesEngine Yard
 

Mehr von Engine Yard (19)

Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard Partner Program 2014
Engine Yard Partner Program 2014
 
Getting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudGetting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard Cloud
 
Engine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture Enhancements
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
 
Simplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentSimplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS Environment
 
The Tao of Documentation
The Tao of DocumentationThe Tao of Documentation
The Tao of Documentation
 
Innovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceInnovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a Service
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
JRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesJRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers Lives
 
High Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedHigh Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. Threaded
 
Release Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionRelease Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment Friction
 
JRuby Jam Session
JRuby Jam Session JRuby Jam Session
JRuby Jam Session
 
Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story
 
JRuby: Apples and Oranges
JRuby: Apples and OrangesJRuby: Apples and Oranges
JRuby: Apples and Oranges
 
Developing a Language
Developing a LanguageDeveloping a Language
Developing a Language
 
Debugging Ruby Systems
Debugging Ruby SystemsDebugging Ruby Systems
Debugging Ruby Systems
 
Geemus
GeemusGeemus
Geemus
 
Everything Rubinius
Everything RubiniusEverything Rubinius
Everything Rubinius
 
Rails Hosting and the Woes
Rails Hosting and the WoesRails Hosting and the Woes
Rails Hosting and the Woes
 

Kürzlich hochgeladen

Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 

Kürzlich hochgeladen (20)

Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 

Rails Antipatterns | Open Session with Chad Pytel

  • 1. Our Presentation Will Begin Shortly Rails AntiPatterns Workshop May 12, 2011 Matt Reider, Director of Training Engine Yard Chad Pytel, Founder & CEO thoughtbot Inc.
  • 4. What makes them hard to test? • Scripts that live outside app • Often have network and file access • Often have output
  • 5. Example Task namespace :twitter do task :search => :environment do puts "Searching twitter." Twitter.search("@cpytel").each do |result| puts "Processing #{result.inspect}." alert = Alert.create(:body => result) alert.save_cache_file! end end puts "All done!" end
  • 7. context "rake twitter:search" do setup do # How slow is this going to be? Very. @out = `cd #{Rails.root} && rake twitter:search 2>&1` end
  • 8. should "print a message at the beginning" do assert_match /Searching/i, @out end
  • 9. should "find all tweets containing @cpytel" do # this one would be based entirely on luck. end
  • 10. This Has Problems • Slow • No mocking or stubbing available • Task isn’t in a transaction
  • 12. How do we fix this?
  • 13. Rake tasks are just Ruby
  • 14. Move it all into the Model
  • 15. class Alert < ActiveRecord::Base def self.create_all_from_twitter_search(output = $stdout) output.puts "Searching twitter." Twitter.search("@cpytel").each do |result| output.puts "Processing #{result.inspect}." alert = create(:body => result) alert.save_cache_file! end output.puts "All done!" end def save_cache_file! # Removes a file from the filesystem. end end
  • 16. The Task is Nice and Skinny namespace :twitter do task :search => :environment do Alert.create_all_from_twitter_search end end
  • 17. Testing is Pretty Normal # test/unit/alert_test.rb class AlertTest < ActiveSupport::TestCase context "create_all_from_twitter_search" do setup do # Make sure none of the tests below hit the # network or touch the filesystem. Alert.any_instance.stubs(:save_cache_file!) Twitter.stubs(:search).returns([]) @output = StringIO.new end
  • 18. should "print a message at the beginning" do Alert.create_all_from_twitter_search(@output) assert_match /Searching/i, @output.string end
  • 19. should "save some cache files" do Twitter.stubs(:search).returns(["one"]) alert = mock("alert") alert.expects(:save_cache_file!) Alert.stubs(:create).returns(alert) Alert.create_all_from_twitter_search(@output) end
  • 20. should "find all tweets containing @cpytel" do Twitter.expects(:search). with("@cpytel"). returns(["body"]) Alert.create_all_from_twitter_search(@output) end
  • 21. We can mock and stub!
  • 22. We can use normal tools! • FakeWeb/WebMock • FileUtils::NoWrite
  • 23. In Summary • You can test drive development of your rake tasks • Rake tasks should live inside a model (or class)
  • 24. Views
  • 26. Know How They Change
  • 27. # Edit form <%= form_for :user, :url => user_path(@user), :html => {:method => :put} do |form| %>
  • 28. <%= form_for @user do |form| %>
  • 29. <!-- posts/index.html.erb --> <% @posts.each do |post| -%> <h2><%= post.title %></h2> <%= format_content post.body %> <p> <%= link_to 'Email author', mail_to(post.user.email) %> </p> <% end -%>
  • 30. Move the post content into a partial
  • 31. <!-- posts/index.html.erb --> <% @posts.each do |post| -%> <%= render :partial => 'post', :object => :post %> <% end -%> <!-- posts/_post.erb --> <h2><%= post.title %></h2> <%= format_content post.body %> <p><%= link_to 'Email author', mail_to(post.user.email) %></p>
  • 32. Looping was built into render
  • 33. <!-- posts/index.html.erb --> <%= render :partial => 'post', :collection => @posts %> <!-- posts/_post.erb --> <h2><%= post.title %></h2> <%= format_content post.body %> <p> <%= link_to 'Email author', mail_to(post.user.email) %> </p>
  • 34. <!-- posts/index.html.erb --> <%= render :partial => 'post', :collection => @posts %> <!-- posts/_post.erb --> <h2><%= post.title %></h2> <%= format_content post.body %> <p> <%= link_to 'Email author', mail_to(post.user.email) %> </p>
  • 35. <%= render :partial => @posts %>
  • 38. <!-- layouts/application.html.erb --> <head> <title> Acme Widgets : TX-300 Utility Widget </title> </head>
  • 39. class PagesController < ApplicationController def show @widget = Widgets.find(params[:id]) @title = @widget.name end end <!-- layouts/application.html.erb --> <head> <title>Acme Widgets : <%= @title %></title> </head>
  • 40. This is all View
  • 41. There is a Helper
  • 42. <!-- layouts/application.html.erb --> <head> <title> Acme Widgets : <%= yield(:title) %> </title> </head> <!-- widgets/show.html.erb --> <% content_for :title, @widget.title %>
  • 44. <!-- layouts/application.html.erb --> <head> <title> Acme Widgets : <%= yield(:title) || "Home" %> </title> </head>
  • 45. What else can we use this for?
  • 46. <!-- layouts/application.html.erb --> <div class="sidebar"> This is content for the sidebar. <%= link_to "Your Account", account_url %> </div> <div class="main"> The main content of the page </div>
  • 47. <!-- layouts/application.html.erb --> <%= yield(:sidebar) %> <div class="main"> The main content of the page </div> <!-- layouts/application.html.erb --> <% content_for :sidebar do %> <div class="sidebar"> This is content for the sidebar. <%= link_to "Your Account", account_url %> </div> <% end %>
  • 49. <!-- layouts/application.html.erb --> <div class="sidebar"> <%= yield(:sidebar) %> </div> <div class="main"> The main content of the page </div> <!-- layouts/application.html.erb --> <% content_for :sidebar do %> This is content for the sidebar. <%= link_to "Your Account", account_url %> <% end %>
  • 50. Conditional Sidebar <!-- layouts/application.html.erb --> <% if content_for?(:sidebar) -%> <div class="sidebar"> <%= yield(:sidebar) %> </div> <% end -%> <div class="main"> The main content of the page </div> <!-- app/views/products/show.html.erb --> <% content_for :sidebar do %> This is content for the sidebar. <%= link_to "Your Account", account_url %> <% end %>
  • 51. Upcoming Classes Zero to Rails 3 in four days •May 23-26 •Virtual Rails AntiPatterns •Best Practices •Boston – June 6 & 7 •San Francisco – June 13 & 14 Learn more at: Engineyard.com/university

Hinweis der Redaktion

  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