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. 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
  2. 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
  3. 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
  4. Routing Conclusions •Create a Route object to represent routes in

    the system •Build routes like ARel builds queries Monday, March 26, 12
  5. 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
  6. “I thought we used rake for manipulating the app?” Ummm...we

    use both rake and rails, I guess. “???” Monday, March 26, 12
  7. [: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
  8. 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
  9. 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
  10. 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
  11. “So the model is just a Ruby object?” Yep! “But

    I thought Ruby prefers composition over inheritance?” Uhh... Monday, March 26, 12
  12. 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
  13. class Article include ActiveRecord::Record # Enable mass-assignment for ... #

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

    and business logic “Did you just say and?” Monday, March 26, 12
  15. 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
  16. Model Layer Conclusions •Add attr_accessible to generated models •Utilize ActiveRecord

    via module inclusion •Break persistence/logic into two components Monday, March 26, 12
  17. 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
  18. 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
  19. Status Quo <h1>Articles</h1> <% @articles.each do |article| %> <li><%= link_to

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

    article.title, Route.article(article) %> <% end %> Monday, March 26, 12
  21. 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
  22. Controller/View Conclusions •Instance variables are a code smell •Use helper

    methods to expose data to the view template Monday, March 26, 12
  23. • 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