• Ruby on RailsPresentation to Agile Atlanta GroupOriginally presented May 10 05Obie FernandezAgile Atlanta Founder /ThoughtWorks Technologist

  • IntroductionWhy present Ruby on Rails to Agile Atlanta?Ruby is an agile languageRuby on Rails is Rubys Killer AppRuby on Rails promotes agile practices

  • Presentation AgendaBrief overview of RubyRails DemonstrationDescription of Rails frameworkQuestions and Answers

  • Why Ruby?Write more understandable code in less linesFree (Very open license)Extensible

  • Principles of RubyJapanese Design Aesthetics Shine ThroughFocus on human factorsPrinciple of Least SurprisePrinciple of SuccinctnessRelevant because these principles were followed closely by the designer of Rails, David H. Hansson Scandinavian Design Aesthetic

  • The Principle of Least SurpriseThis principle is the supreme design goal of RubyMakes programmers happy and makes Ruby easy to learnExamplesWhat class is an object? o.classIs it Array#size or Array#length? same method theyre aliasedWhat are the differences between arrays? diff = ary1 ary2 union = ary1 + ary2

  • Principle of SuccinctnessA.K.A. Principle of Least EffortWe dont like to waste timeEspecially on XML config files, getters, setters, etc The quicker we program, the more we accomplishSounds reasonable enough, right?Less code means less bugs

  • Ruby is Truly Object-OrientedAll classes derived from Object including Class (like Java) but there are no primitives (not like Java at all)Ruby uses single-inheritanceMixins give you the power of multiple inheritance without the headachesModules allow addition of behaviors to a classReflection is built in along with lots of other highly dynamic metadata featuresThings like = and + that you might think are operators are actually methods (like Smalltalk)

  • Some Coding ConventionsMethod Chaining print array.uniq.sort.reverseMethod Names include ! and ? ary.sort! (discuss bang if there is time)Iterators and Blocks vs. Loops files.each { |file| process(file) }Case usage: Class names begin with a Capital letterConstants are ALL_CAPSEverything else - method call or a local variableUnder_score instead of camelCase

  • Dynamic ProgrammingDuck Typing Based on signatures, not class inheritanceDynamic Dispatch A key concept of OOP: methods are actually messages that are sent to an object instanceDynamic BehaviorReflectionScope Reopening (Kind of like AOP)EvalBreakpoint debugger

  • Enough About Ruby!What about Ruby on Rails?

  • Rails in a Nutshell Includes everything needed to create database-driven web applications according to the Model-View-Control pattern of separation.Mostly written by David H. HannsonTalented designerDream is to change the worldA principal World class designersOver 100 additional contributors to the Rails codebase in 9 months!

  • The Obligatory Architecture Slide

  • DemoTodo List Tutorial Projectby Vincent Foley

  • Model View Controller Model classes are the "smart" domain objects (such as Account, Product, Person, Post) that hold business logic and know how to persist themselves to a databaseViews are HTML templatesControllers handle incoming requests (such as Save New Account, Update Product, Show Post) by manipulating the model and directing data to the view

  • Model ClassesBased on Martin Fowlers ActiveRecord patternFrom Patterns of Enterprise Architecture

    An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.

  • ActiveRecordConvention over Configuration (Applies to all of Rails)No XML files! Lots of reflection and run-time extension Magic is not inherently a bad word Admit the DatabaseLets you drop down to SQL for odd cases and performance Doesnt attempt to duplicate or replace data definitions

  • ActiveRecord APIObject/Relational Mapping FrameworkAutomatic mapping between columns and class attributesDeclarative configuration via macrosDynamic findersAssociations, Aggregations, Tree and List BehaviorsLockingLifecycle CallbacksSingle-table inheritance supportedEager fetching supportedValidation rulesMore

  • ActiveRecord AggregationsAggregation expresses a composed of relationshipDefine value objects by using composed_of methodTells Rails how value objects are created from the attributes of the entity object when the entity is initialized andhow it can be turned back into attributes when the entity is saved to the databaseAdds a reader and writer method for manipulating a value objectValue objects should be immutable and that requirement is enforced by Active Record by freezing any object assigned as a value object.Attempting to change value objects result in a TypeError

  • ActiveRecord Models are Multi-talented actorsThe ActiveRecord::Acts module has super cool features that enhance your models behavioracts_as_listProvides the capabilities for sorting and reordering a number of objects in listacts_as_treeModel a tree structure by providing a parent association and a children associationacts_as_nested_setSimiliar to Tree, but with the added feature that you can select the children and all of its descendants with a single query!

  • ActiveRecord AssociationsMacro-like class methods for tying objects together through foreign keysEach adds a number of methods to the class Works much the same way as Rubys own attr* methods

  • ActiveRecord TimestampsMagic timestamps!ActiveRecord objects will automatically record creation and/or update timestamps of database objects if columns with the names created_at / created_on or updated_at / updated_on are present in your db table

  • ActiveRecord TransactionsSimple declarative transaction support on both object and database level

    # Just database transaction Account.transaction do david.withdrawal(100) mary.deposit(100) end

    # Object transactionAccount.transaction(david, mary) do david.withdrawal(100) mary.deposit(100) end

  • ActiveRecord vs HibernateInstead of

    ActiveRecord lets you do

  • Rails Logging

  • ActionController APIControllers defined as classes that execute and then either render a template or redirectsAn action is a public method on the controllerGetting data in and out of controllersRequest parameters available in the @params hash (and can be multidimensional)Web session exposed as @session hashCookies exposed as @cookies hashRedirect scope provided by @flash hash (unique to Rails)

  • Filters and Request InterceptionThe simple way to add Pre and Post processing to actions Access to the request, response, and instance variables set by other filters or the actionController inheritance hierarchies share filters downwards, but subclasses can also add new filtersTarget specific actions with :only and :except optionsFlexible Filter definitionmethod reference (by symbol)external classinline method (proc)

  • From Controller to ViewRails gives you many rendering optionsDefault template rendering follow naming conventions and magic happensExplicitly render to particular actionRedirect to another actionRender a string response (or no response)

  • View Template ApproachesERB Embedded RubySimilar to JSPs
  • ERB Example

  • XmlMarkup Example

  • Similar to JSP is a Good Thing?Arent Rails programmers going to be tempted to put a bunch of application logic in the templates?

    The short answer is no.

    JSPs are a less painful way to add logic to a screen. Due to the lower pain associated with their use, it is very tempting to add inappropriate code to them

    Thats simply not the case with Rails!Ruby is an excellent language for view logic (succinct, readable) and Rails is also made out of all Ruby. So there's no longing for a better suited template language and there's no pain relief in misappropriating business logic into the view.- David H. Hansson

  • Layouts and PartialsTemplates in app/views/layouts/ with the same name as a controller will be automatically set as that controllers layout unless explicitly told otherwisePartials are sub-templates that render a single objectPartial template files follow conventionEasy API support for rendering collections of partials.

  • Built-in CachingEnhance performance by keeping the result of calculations, renderings, and database calls around for subsequent requestsAction Controller offers 3 levels of granularityPageActionFragmentSweepers are responsible for expiring caches when model objects change

  • Page CachingEntire action output of is stored as a HTML file that the web server can serve As much as 100 times faster than going the process of dynamically generating the contentOnly available to stateless pages where all visitors are treated the sameEasy to implement

  • Action CachingEntire output of the response is cachedEvery request still goes to the controllerfilters are run before the cache is servedallows for authentication and other restrictions on whether someone are supposed to see the cache

  • Fragment CachingCaches parts of templates without caching the entire actionUse when elements of an action change frequently and other parts rarely change or are okay to share among requestsFour options for storageFileStore Fragments shared on file system by all processesMemoryStore Caches fragments in memory per processDrbStore Fragments cached on a separate, shared processMemCachedStore Uses Dangas MemCached open source caching server

  • PaginationMacro-style automatic fetching of your model for multiple views, or explicit fetching for single actionsIncluded for all controllersConfigure as much or as little as desiredPaginationHelper module has methods for generating pagination links in your template

  • Helper ModulesHelp you spend time writing meaningful codeActiveRecordHelperAssetTagHelperDateHelperDebugHelperFormHelper(s)JavascriptHelperNumberHelperPaginationHelperTagHelperTextHelperUrlHelper

  • Helper Methods ExamplesDateHelper::distance_of_time_in_wordsReports the approximate distance in time between to Time objects. For example, if the distance is 47 minutes, it'll return "about 1 hourJavascriptHelper::link_to_remoteAJAX in one line! Creates link to a remote action thats called in the background using XMLHttpRequest. The result of that request can then be inserted into the browsers DOM JavascriptHelper::periodically_call_remoteMore AJAX! Links page to a remote action thats called in the background using XMLHttpRequest. The result of that request can be inserted into the browsers DOMNumberHelper::human_size, number_to_currency, number_to_phone, etcYou get the picture!

  • The Quest for Pretty URLsThe responsibility of URL parsing is handled by Rails itself. Why?Not all webservers support rewritingAllows Rails to function out of the box on almost all webserversFacilitates definition of custom URLsLinked to URL helper methods such as url_for, link_to, and redirect_toRouting rules defined in config/routes.rb

  • routes.rbActionController::Routing::Routes.draw do |map|

    # Priority based on creation: first created -> highest priority # Keep in mind you can assign values other than :controller and :action

    # You can have the root of your site routed by hooking up '' # just remember to delete public/index.html. map.connect '', :controller => "bakery"

    map.connect 'query/:guid', :controller => global", :action=>"query"

    # Allow downloading Web Service WSDL as a file with an extension map.connect ':controller/service.wsdl', :action => 'wsdl'

    map.connect ':controller/:action/:id # Default


  • Rails to the RescueActions that fail to perform as expected throw exceptionsExceptions can either be rescuedfor public view (with a nice user-friendly explanation)for developers view (with tons of debugging information)By default, requests from localhost get developers view

  • ActiveSupport APIRails utility methodsDate conversionNumber handlingString conversions and inflectionTime calculations

  • ActionMailer APIRails built-in email serviceWrite email controllers in same way as web controllersIntegrated with templating system

  • ActionWebService APIIts easy to do web services in RailsRails has built-in support for SOAP and XML-RPCStruct base class can be used to represent structured types that dont have ActiveRecord implementations or to avoid exposing an entire model to callersExamplesDefine a web services client in one lineAdd a web service to a controller (next slide)

  • Defining a WebService

  • FixturesUse YAML sample data for testingEach YAML fixture (ie. record) is given a name and is followed by an indented list of key/value pairs in the "key: value" format. Records are separated by a blank line

  • Unit TestingRails includes Rubys test/unitRake pre-configured to run test suite or individual testsEasy to load fixtures into a test case

  • RakeRubys Build SystemFamiliar to Ant usersYour build file is a written in RubyBasic build script provided with Rails project

  • Rails Success StoryBasecamp (info as of late April 05)Average lines of code for an action in Basecamp is 5Written in 9 monthsTens of thousands of users300k dynamic page renders/dayHosted on two app servers with 15 fastcgi processes each + one MySQL server

  • The Rails CommunityThe developer community around Rails is very helpful and excitedRails Wiki - Mailing List very activeIRC Get instant answers to most questions. David and other Rails commiters are all regularly present

    Ruby on Rails 2005 Powerpoint Presentation: Introduction to Ruby and Ruby on Rails given to the Agile Atlanta user group on 5/10/2005

    Obed Fernandez Obed Fernandez