Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Adventures on the Golden Path

j3
March 26, 2012

Adventures on the Golden Path

Version 1.0 as delivered at RubyNation 2012 on 3/24/12.

j3

March 26, 2012
Tweet

More Decks by j3

Other Decks in Technology

Transcript

  1. Adventures Golden Path Jeff Casimir / Jumpstart Lab / @j3

    on the Monday, March 26, 12
  2. Jumpstart Lab & LivingSocial Monday, March 26, 12

  3. 2005 Back in the year Monday, March 26, 12

  4. This is no JSP Monday, March 26, 12

  5. Love? How do you fall in Monday, March 26, 12

  6. 10X Productivity This new world promised Monday, March 26, 12

  7. “Joy” This new world promised Monday, March 26, 12

  8. “Beta” Books Monday, March 26, 12

  9. Rails 1 We can do what you can do. Monday,

    March 26, 12
  10. Rails 2 Pushing the state of the art Monday, March

    26, 12
  11. Rails 3 Foundation for the future Monday, March 26, 12

  12. Rails 4 Back to happiness? Monday, March 26, 12

  13. Why Rails Works The Golden Path Monday, March 26, 12

  14. Rounding the Wheel We know better Monday, March 26, 12

  15. The Router Part 1 Monday, March 26, 12

  16. “YARR!” That’s not it Monday, March 26, 12

  17. routes.rb Blog::Application.routes.draw do # The priority is based upon order

    of creation: # first created -> highest priority. # Sample of regular route: # match 'products/:id' => 'catalog#view' # Keep in mind you can assign values other than :controller and :action # Sample of named route: # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase # This route can be invoked with purchase_url(:id => product.id) # Sample resource route (maps HTTP verbs to controller actions automatically): # resources :products # Sample resource route with options: # resources :products do # member do # get 'short' Monday, March 26, 12
  18. Simple routes.rb Blog::Application.routes.draw do # EXAMPLES # resources :products #

    root :to => 'welcome#index' # MORE INFORMATION # Run "rake routes" to see the routes available # http://guides.rubyonrails.org/routing.html end Monday, March 26, 12
  19. Route Helpers But wait, there’s more: Monday, March 26, 12

  20. “I want to link to an article” No problem! Monday,

    March 26, 12
  21. Monday, March 26, 12

  22. Monday, March 26, 12

  23. Monday, March 26, 12

  24. Monday, March 26, 12

  25. articles_path Adding path or url Monday, March 26, 12

  26. “Where does that method come from?” Uhh...don’t worry about it.

    Monday, March 26, 12
  27. “Can I play with routes from the console?” I think

    so, kinda. Monday, March 26, 12
  28. This is not OOP Functional View Helpers Monday, March 26,

    12
  29. Route As a singleton class Monday, March 26, 12

  30. Route.articles Generates the index path Monday, March 26, 12

  31. Route.article(1) Generates the show path Monday, March 26, 12

  32. Route.article(1).edit Generates the edit path Monday, March 26, 12

  33. Route Experiments blog$ rails console Loading development environment 001 >

    Route.methods(false) => [:articles, :article] 002 > Route.articles => /articles/ 003 > Route.article(1) => /articles/1 004 > Route.article(1).edit => /articles/1/edit <%= link_to "Articles", Route.articles %> Monday, March 26, 12
  34. “It’s an object system, I know this!” Monday, March 26,

    12
  35. Routing Conclusions •Create a Route object to represent routes in

    the system •Build routes like ARel builds queries Monday, March 26, 12
  36. System Level Part 2 Monday, March 26, 12

  37. “What’s Rake?” It’s “ruby-make,” it’s for doing things with your

    app from the command line. Monday, March 26, 12
  38. Let’s generate our first model... “Ok, cool.” Here’s how we

    do it at the terminal: rails generate model Article Monday, March 26, 12
  39. “I thought we used rake for manipulating the app?” Ummm...we

    use both rake and rails, I guess. “???” Monday, March 26, 12
  40. [:generate, :destroy, :server, :console].each do | command| desc "Proof-of-concept rails

    CLI proxy for #{command}" task command do system("rails #{command} #{ARGV[1..-1].join(' ')}") exit end end Proof of Concept Monday, March 26, 12
  41. Rake Everything blog$ rake generate model Article title:string body:string invoke

    active_record create db/migrate/20120322132256_create_articles.rb create app/models/article.rb ... blog$ rake db:migrate == CreateArticles: migrating ================================================= -- create_table(:articles) ... blog$ rake console Loading development environment 001 > Monday, March 26, 12
  42. System-Level Conclusions •Generate apps using rails •Then everything else happens

    through rake Monday, March 26, 12
  43. Models Part 3 Monday, March 26, 12

  44. Let’s check out the model we generated... Monday, March 26,

    12
  45. class Article < ActiveRecord::Base end article.rb Monday, March 26, 12

  46. “Is the model important?” The most important! “So why is

    it blank?” ... Monday, March 26, 12
  47. Mass-Assignment Monday, March 26, 12

  48. Remember the h helper? Monday, March 26, 12

  49. Safe by Default class Article < ActiveRecord::Base # Enable mass-assignment

    for attributes with # attr_accessible :title, :body end module Blog class Application < Rails::Application # Block all model attributes from mass assignment # unless attr_accessible is used config.attributes_protected_by_default = true #... end end Monday, March 26, 12
  50. Proof of Concept ActiveRecord::Base.class_eval if Application.config.attributes_protected_by_default attr_accessible end end blog$

    rake console Loading development environment 001 > Article.create(:title => "Hello, world") ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: title Monday, March 26, 12
  51. “So the model is just a Ruby object?” Yep! “But

    I thought Ruby prefers composition over inheritance?” Uhh... Monday, March 26, 12
  52. class Article include ActiveRecord::Base # Enable mass-assignment for ... #

    attr_accessible :title, :body end “That makes more sense, but what is a ‘Base’?” Monday, March 26, 12
  53. class Article include ActiveRecord::Record # Enable mass-assignment for ... #

    attr_accesible :title, :body end “Oh, it’s a Record!” Monday, March 26, 12
  54. “What does a model do, anyway?” It’s responsible for persistence

    and business logic “Did you just say and?” Monday, March 26, 12
  55. Persistence Monday, March 26, 12

  56. Single Responsibility module ArticlePersistence include ActiveRecord::Record has_many :comments belongs_to :author

    end class Article include ArticlePersistence end Monday, March 26, 12
  57. “Why doesn’t Rails do that by default?” It should! Monday,

    March 26, 12
  58. blog$ rake generate model Comment body:text article_id:integer invoke active_record create

    db/migrate/20120322142641_create_com... create app/models/comment.rb create app/persistence/comment_persistence.rb invoke test_unit create test/unit/comment_test.rb create test/unit/comment_persistence_test.rb create test/fixtures/comments.yml blog$ In the Generators Monday, March 26, 12
  59. Model Layer Conclusions •Add attr_accessible to generated models •Utilize ActiveRecord

    via module inclusion •Break persistence/logic into two components Monday, March 26, 12
  60. Controllers & Views Part 4 Monday, March 26, 12

  61. Let’s check out the controller action to list articles: class

    ArticlesController < ApplicationController def index @articles = Article.all end end “Why is that an instance variable?” Monday, March 26, 12
  62. That’s how we get it over to the view template.

    “So they share state? I thought MVC was three components?” ...it’s complicated. Monday, March 26, 12
  63. Status Quo <h1>Articles</h1> <% @articles.each do |article| %> <li><%= link_to

    article.title, article_path(article) %> <% end %> Monday, March 26, 12
  64. Accessor Method <h1>Articles</h1> <% articles.each do |article| %> <li><%= link_to

    article.title, Route.article(article) %> <% end %> Monday, March 26, 12
  65. class ArticlesController < ApplicationController attr_viewable :articles def index self.articles =

    Article.all end In the Controller Monday, March 26, 12
  66. Proof of Concept module AttributeViewer def attr_viewable(*names) names.each do |name|

    attr_accessor name helper_method name private "#{name}=".to_sym end end end class ApplicationController < ActionController::Base protect_from_forgery include AttributeViewable end Monday, March 26, 12
  67. Controller/View Conclusions •Instance variables are a code smell •Use helper

    methods to expose data to the view template Monday, March 26, 12
  68. • Wrap the router into an object • Unify the

    system-level with rake • attr_accessible by default • Break logic from persistence • Eliminate instance vars from views Adventures on the Golden Path Jeff Casimir / Jumpstart Lab / @j3 Monday, March 26, 12