Agile and rails

340 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
340
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Agile and rails

  1. 1. Agile Rails Gregory McIntyre, March 2012
  2. 2. My Creds • University • Ruby, TDD • Tilefile Pty Ltd • Python, ActionScript, Rails • realestate.com.au • Agile (ThoughtWorks)
  3. 3. Waterfall
  4. 4. #fail • Impenetrable requirements documents • Scary contracts • Early is when you know the least • Requirements tend to change
  5. 5. Agile Manifest’O • Face time > processes and tools • Working software > documentation • Customer collaboration > contracts • Embracing change > sticking to the plan
  6. 6. You Say Scrum, I Say... • XP • Scrum • Crystal • Lean • Roll your own, just follow the ’festo
  7. 7. Turn, Turn, Turn •Strategy Release • Iteration • Daily •
  8. 8. Strategy
  9. 9. Strategy • Mission statements • Scope • Risk • Team building • Priorities • Finance
  10. 10. Project Inception • Agile “strategy” process (1-5 days) • Share vision • Align goals • Set realistic expectations • Swap phone numbers
  11. 11. Strategy Constraints
  12. 12. Risk Chart
  13. 13. Release Planning
  14. 14. Build a Story Backlog • Do some UX • Write “stories” • T-shirt sizing
  15. 15. Burn Down Chart
  16. 16. Kanban • Toyota invented it to manage car production efficiently • Not waterfall, not iterative • • Continuous, like a pipe Deliver something of value every day
  17. 17. Lumpy Bad
  18. 18. Smooth Good
  19. 19. Iterations
  20. 20. Feedback Loops • • • • 2-4 weeks is common Involve the customer Revise estimates Assess and improve
  21. 21. Planning Poker
  22. 22. Card Wall
  23. 23. Stand Ups
  24. 24. Pair Programming
  25. 25. Conversations
  26. 26. Noise
  27. 27. Mess
  28. 28. Paper and Pens
  29. 29. Test Driven Dev
  30. 30. Behaviour Driven Dev
  31. 31. Continuous Integration
  32. 32. Agile is... • Technically “backward” (ahem, pragmatic) • “Last minute” • Noisy, demanding and confronting • Practice practice practice • About visibility, not due dates
  33. 33. Agile is... Deliver something of value every day
  34. 34. Ruby on Rails
  35. 35. exit unless "restaurant".include? "aura" 5.times { print "Odelay!" } ['toast', 'cheese', 'wine'].each {|food| print food.capitalize } class Blog has_many :posts end Ruby: Expressive and Flexible
  36. 36. Ruby DSLs class Blog has_many :posts end def has_many(things)
  37. 37. “LADIES, let’s make web apps with Ruby”
  38. 38. Rails is a Web Application Framework • Handles an HTTP request • • • Common practices Sensible defaults Keeps things orderly
  39. 39. Rapid Prototyping $ rails generate scaffold Post name:string title:string content:text invoke create create invoke create route invoke create invoke create create create create create create invoke create create create create create invoke create create invoke create invoke create invoke invoke create active_record db/migrate/20120316050430_create_posts.rb app/models/post.rb rspec spec/models/post_spec.rb resources :posts inherited_resources_controller app/controllers/posts_controller.rb erb app/views/posts app/views/posts/index.html.erb app/views/posts/edit.html.erb app/views/posts/show.html.erb app/views/posts/new.html.erb app/views/posts/_form.html.erb rspec spec/controllers/posts_controller_spec.rb spec/views/posts/edit.html.erb_spec.rb spec/views/posts/index.html.erb_spec.rb spec/views/posts/new.html.erb_spec.rb spec/views/posts/show.html.erb_spec.rb helper spec/helpers/posts_helper_spec.rb spec/routing/posts_routing_spec.rb rspec spec/requests/posts_spec.rb helper app/helpers/posts_helper.rb rspec stylesheets public/stylesheets/scaffold.css
  40. 40. Sensible Defaults Davidson::Application.routes.draw do resource 'shared_cookie' end <struts> <package name = "MyPackage"> <interceptors> <!--Some set particular action--> <interceptor <interceptor <interceptor <interceptor of common interceptors for a name name name name = = = = "A_I1" "A_I2" "A_I3" "A_I4" class class class class = = = = "MyA_I1"> "MyA_I2"> "MyA_I3"> "MyA_I4"> <!--Another set of common interceptors --> <interceptor name = "B_I1" class = "MyB_I1"> <interceptor name = "B_I2" class = "MyB_I2"> <interceptor name = "B_I3" class = "MyB_I3"> <interceptor name = "B_I4" class = "MyB_I4"> </interceptors> <interceptor-stack name = <interceptor-ref name <interceptor-ref name <interceptor-ref name <interceptor-ref name </interceptor-stack> "A"> = "A_I1"> = "A_I2"> = "A_I3"> = "A_I4"> <interceptor-stack name = <interceptor-ref name <interceptor-ref name <interceptor-ref name <interceptor-ref name </interceptor-stack> "B"> = "B_I1"> = "B_I2"> = "B_I3"> = "B_I4"> <action name = "MyAction1"> <interceptor-ref name = "A"/> </action> shared_cookie POST new_shared_cookie GET edit_shared_cookie GET GET PUT DELETE /shared_cookie /shared_cookie/new /shared_cookie/edit /shared_cookie /shared_cookie /shared_cookie
  41. 41. ERB versus HAML = form_for(@post) do |f| <%= form_for(@post) do |f| %> - if @post.errors.any? <% if @post.errors.any? %> #errorExplanation <div id="errorExplanation"> %h2 <h2><%= pluralize(@post.errors.count, "error") %> = pluralize(@post.errors.count, "error") prohibited this post from being saved:</h2> prohibited this post from being saved: <ul> %ul <% @post.errors.full_messages.each do |msg| %> - @post.errors.full_messages.each do |msg| <li><%= msg %></li> %li= msg <% end %> .field </ul> = f.label :name </div> = f.text_field :name <% end %> .field <div class="field"> = f.label :title <%= f.label :name %> = f.text_field :title <%= f.text_field :name %> .field </div> = f.label :content <div class="field"> = f.text_area :content <%= f.label :title %> .actions <%= f.text_field :title %> = f.submit </div> <div class="field"> <%= f.label :content %> <%= f.text_area :content %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>
  42. 42. CSS versus SASS html.rgba header#global nav .user-nav { background-color: rgba(0, 0, 0, 0.05); } html.rgba header#global nav .user-nav .signin:active, html.rgba header#global nav .user-nav .signin:hover, html.rgba header#global nav .user-nav .signin:focus, html.rgba header#global nav .user-nav .signout:active, html.rgba header#global nav .user-nav .signout:hover, html.rgba header#global nav .user-nav .signout:focus { background-color: rgba(255, 255, 255, 0.5); } html.no-rgba header#global nav .user-nav { background: url("/images/design/black-5.png"); } html.no-rgba header#global nav .user-nav .signin:active, html.no-rgba header#global nav .user-nav .signin:hover, html.no-rgba header#global nav .user-nav .signin:focus, html.no-rgba header#global nav .user-nav .signout:active, html.no-rgba header#global nav .usernav .signout:hover, html.no-rgba header#global nav .user-nav .signout:focus { background-color: #edebe9; } html &.rgba header#global nav .user-nav background-color: rgba(0, 0, 0, 0.05) .signin, .signout &:active, &:hover, &:focus background-color: rgba(255, 255, 255, 0.5) &.no-rgba header#global nav .user-nav background: url("/images/design/black-5.png" .signin, .signout &:active, &:hover, &:focus background-color: #edebe9
  43. 43. SASS + Compass <3 .box -ms-filter: "progid:DXImageTransform.Microsoft.A lpha(Opacity=50)" filter: alpha(opacity=50) opacity: .5 .box +opacity(.5)
  44. 44. Advanced Compass @import "my-icons/*.png" .actions .new @include my-icons-sprite(new) .edit @include my-icons-sprite(edit) .save @include my-icons-sprite(save) .delete @include my-icons-sprite(delete) .my-icons-sprite, .actions .new, .actions .edit, .actions .save, .actions .delete { background: url('/images/my-icons-s34fe0604ab.png') no-repeat; } .actions .actions .actions .actions .new .edit .save .delete { { { { background-position: background-position: background-position: background-position: 0 0 0 0 -64px; -32px; -96px; 0; } } } }
  45. 45. CoffeeScript (function() { DI.Home = { onload: function() { return this.setupScrollable(); }, setupScrollable: function() { return $('.scrollable').scrollable({ circular: true, speed: 800 }).autoscroll({ autoplay: true, interval: 10000 }).navigator(); } }; $(function() { return DI.Home.onload(); }); }).call(this); DI.Home = onload: -> @setupScrollable() setupScrollable: -> $(".scrollable").scrollable( circular: true speed: 800 ).autoscroll( autoplay: true interval: 10000 ).navigator() $ -> DI.Home.onload()
  46. 46. Asset Management <%= javascript_include_tag "application" %> <script src="/assets/core.js?body=1" type="text/javascript"></script> <script src="/assets/projects.js?body=1" type="text/javascript"></script> <script src="/assets/tickets.js?body=1" type="text/javascript"></script> <script src="/assets/application908e25f4bf641868d8683022a5b62f54.js" type="text/javascript"></script>
  47. 47. Rails Plugins
  48. 48. Rails Plugins • Authentication (Devise, OmniAuth, Facebook, Twitter) • Storage (MySQL, PostgreSQL, MongoDB) • Search (ElasticSearch, Sphinx) • HTML (HAML, SASS, Less, Compass, Slim) • Deployment (Capistrano, Heroku) • Monitoring (Airbrake, NewRelic) • Testing (RSpec, Cucumber, Capybara) • JavaScript (jQuery, MooTools) • ...
  49. 49. Plugins I used to write functionality Now I integrate functionality into solutions
  50. 50. RSpec for TDD require 'spec_helper' describe Region do context 'with regions Sydney, North Sydney and Melbourne' do before do @sydney = Region.make(:sydney) @north_sydney = Region.make(:north_sydney) @melbourne = Region.make(:melbourne) end describe '.find_by_postcode' do it 'should be Sydney for 2000' do gpo = Region.find_by_postcode('2000') gpo.should == @sydney end end end end
  51. 51. Cucumber for BDD Feature: Manage Articles In order to make a blog As an author I want to create and manage articles Scenario: List articles Given I have articles titled Pizza, Breadsticks When I go to the list of article Then I should see "Pizza" And I should see "Breadsticks" Scenario: Create an article Given I have no articles And I am on the list of articles When I follow "New Article" And I fill in "Title" with "Spuds" And I fill in "Content" with "Delicious potato wedges!" And I press "Create" Then I should see "New article created." And I should see "Spuds" And I should see "Delicious potato wedges!" And I should have 1 article
  52. 52. Steak for BDD require 'spec_helper' feature 'Admin Sign In and Out', %q{ As an admin user I want to sign in and out So that I can access the admin section } do background do AdminUser.make(:email => 'jdoe@protein-one.com', :password => 'password') end scenario 'Valid admin login' do visit admin_path fill_in 'Email', :with => 'jdoe@protein-one.com' fill_in 'Password', :with => 'password' click_link 'Sign in' page.should have_content('Signed in successfully.') page.should have_css('a', :text => 'Sign out') end scenario 'Invalid admin login' do visit admin_path fill_in 'Email', :with => 'jdoe@protein-one.com' fill_in 'Password', :with => 'wrong password' click_link 'Sign in' page.should have_content('Invalid email or password.') page.should_not have_content('Sign out') end end
  53. 53. Selenium Webdriver
  54. 54. Deployment # config/deploy.rb set :application, 'davidson' set :repository, 'git@git.protein-one.com' set :deploy_to, '/home/davidson/deployment' set :scm, :git role :app, '192.168.1.1', '192.168.1.2' role :web, '192.168.1.101', '192.168.1.102' role :db, '192.168.1.229', :primary => true $ cap staging deploy ... $ cap production deploy ...
  55. 55. Can I Learn All This? • Come pair program with me • Ask me for my collection of Rails ebooks • Pick an app to write • Ask (shyness is niiiice but...) • Nettuts+, Lynda.com, Treehouse
  56. 56. Rails at Protein One • Let’s rapidly prototype our ideas • Let’s focus on solutions, not code • Let’s test and monitor so we can be suave and confident
  57. 57. Designers and Me • If you give me Photoshop files • I will use Compass (and spriting) • If you give me HTML5 • I will convert it to HAML, SASS and CoffeeScript • (so if you wanna save me time...)
  58. 58. Ta greg@gregorymcintyre.com 2013

×