Slide 1

Slide 1 text

Adventures Golden Path Jeff Casimir / Jumpstart Lab / @j3 on the Monday, March 26, 12

Slide 2

Slide 2 text

Jumpstart Lab & LivingSocial Monday, March 26, 12

Slide 3

Slide 3 text

2005 Back in the year Monday, March 26, 12

Slide 4

Slide 4 text

This is no JSP Monday, March 26, 12

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

“Beta” Books Monday, March 26, 12

Slide 9

Slide 9 text

Rails 1 We can do what you can do. Monday, March 26, 12

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

The Router Part 1 Monday, March 26, 12

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Route Helpers But wait, there’s more: Monday, March 26, 12

Slide 20

Slide 20 text

“I want to link to an article” No problem! Monday, March 26, 12

Slide 21

Slide 21 text

Monday, March 26, 12

Slide 22

Slide 22 text

Monday, March 26, 12

Slide 23

Slide 23 text

Monday, March 26, 12

Slide 24

Slide 24 text

Monday, March 26, 12

Slide 25

Slide 25 text

articles_path Adding path or url Monday, March 26, 12

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

This is not OOP Functional View Helpers Monday, March 26, 12

Slide 29

Slide 29 text

Route As a singleton class Monday, March 26, 12

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

“It’s an object system, I know this!” Monday, March 26, 12

Slide 35

Slide 35 text

Routing Conclusions •Create a Route object to represent routes in the system •Build routes like ARel builds queries Monday, March 26, 12

Slide 36

Slide 36 text

System Level Part 2 Monday, March 26, 12

Slide 37

Slide 37 text

“What’s Rake?” It’s “ruby-make,” it’s for doing things with your app from the command line. Monday, March 26, 12

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

“I thought we used rake for manipulating the app?” Ummm...we use both rake and rails, I guess. “???” Monday, March 26, 12

Slide 40

Slide 40 text

[: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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

System-Level Conclusions •Generate apps using rails •Then everything else happens through rake Monday, March 26, 12

Slide 43

Slide 43 text

Models Part 3 Monday, March 26, 12

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

“Is the model important?” The most important! “So why is it blank?” ... Monday, March 26, 12

Slide 47

Slide 47 text

Mass-Assignment Monday, March 26, 12

Slide 48

Slide 48 text

Remember the h helper? Monday, March 26, 12

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

“So the model is just a Ruby object?” Yep! “But I thought Ruby prefers composition over inheritance?” Uhh... Monday, March 26, 12

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

class Article include ActiveRecord::Record # Enable mass-assignment for ... # attr_accesible :title, :body end “Oh, it’s a Record!” Monday, March 26, 12

Slide 54

Slide 54 text

“What does a model do, anyway?” It’s responsible for persistence and business logic “Did you just say and?” Monday, March 26, 12

Slide 55

Slide 55 text

Persistence Monday, March 26, 12

Slide 56

Slide 56 text

Single Responsibility module ArticlePersistence include ActiveRecord::Record has_many :comments belongs_to :author end class Article include ArticlePersistence end Monday, March 26, 12

Slide 57

Slide 57 text

“Why doesn’t Rails do that by default?” It should! Monday, March 26, 12

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

Model Layer Conclusions •Add attr_accessible to generated models •Utilize ActiveRecord via module inclusion •Break persistence/logic into two components Monday, March 26, 12

Slide 60

Slide 60 text

Controllers & Views Part 4 Monday, March 26, 12

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Status Quo

Articles

<% @articles.each do |article| %>
  • <%= link_to article.title, article_path(article) %> <% end %> Monday, March 26, 12
  • Slide 64

    Slide 64 text

    Accessor Method

    Articles

    <% articles.each do |article| %>
  • <%= link_to article.title, Route.article(article) %> <% end %> Monday, March 26, 12
  • Slide 65

    Slide 65 text

    class ArticlesController < ApplicationController attr_viewable :articles def index self.articles = Article.all end In the Controller Monday, March 26, 12

    Slide 66

    Slide 66 text

    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

    Slide 67

    Slide 67 text

    Controller/View Conclusions •Instance variables are a code smell •Use helper methods to expose data to the view template Monday, March 26, 12

    Slide 68

    Slide 68 text

    • 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