RubyPlus RailsPlus Your ApplicationMinus RailsBrian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthrie
TheLastTenPercentBrian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthrie
How to do complex things in Ruby      (without shooting yourself in the foot)                      2010
How to do simple things in Ruby          (with care and craft)                 2011
the last10%
So what’s hard about this?(Is it time to go check out the talk in the other room? That guy seems cool.)
Nothing!
Every good talk needs a rant
not complex
There’s an army of programmers      looking for Rails bugs
Your code? Just you.
Craft is even more important.
notcookiecutter
Most Ruby programmers are Rails programmers first
Learning what Rails doesn’t dois as important as learning what it does
For those craftspeople here:        Thank you
Gaps in Rails:Where’s the problem?
“Prior to Rails 3.0, if a plugin or gemdeveloper wanted to have an objectinteract with Action Pack helpers, it wasrequired...
Rails 2Active      Active          Action          ActionRecord     Resource         Mailer           Pack      Active    ...
Presentation   Logic   Data
Presentation        Logic   Dataform_for @user do
Presentation                   Logic                 Dataform_for @user do   @user = User.find(params[:id])
Presentation                   Logic                 Dataform_for @user do   @user = User.find(params[:id])
Presentation                   Logic                 Dataform_for @user do   @user = User.find(params[:id])
Presentation                     Logic                    Dataform_for @user do     @user = User.find(params[:id])        ...
Presentation                       Logic                    Data form_for @user do       @user = User.find(params[:id])for...
• Domain models that aren’t database tables• Importing and transforming data• Web service clients• Presenter objects      ...
Rails 2Active      Active          Action          ActionRecord     Resource         Mailer           Pack      Active    ...
Rails 3         Active         ModelActive         Active          Action          ActionRecord        Resource         Ma...
Active          gem active_model Model Active   gem active_support,Support     :require => false
the principles   Simplicity   Testability   Abstractability   Community
the principlesCode      Simplicity          Testability          Abstractability          Community
S   Single responsibility principle    An object should have only a single responsibility.O   Open/closed principle    Sof...
S   Single responsibility principle    An object should have only a single responsibility.O   Open/closed principle    Sof...
SD Card Principles
S   Single responsibility principle    An object should have only a single responsibility.O   Open/closed principle    Sof...
S     Single responsibility principle     An object should have only a single responsibility.O              Open/closed pr...
the principles                  Simplicity                  TestabilityArchitecture      Abstractability                  ...
IdiomaticityIdiom (plural idioms) 1. A manner of speaking, a way of expressing oneself. 2. An artistic style (for example,...
IdiomaticityIdiom (plural idioms) 1. A manner of speaking, a way of expressing oneself. 2. An artistic style (for example,...
Some of the best Ruby programmers have  gone against commonly-accepted style
Keep it simple when you canBreak the rules when you must (or when it sounds like fun)
The best* Ruby code is clean, simple, and follows             community idioms.                  * Easiest to maintain.
the recipeBuild an objectTest that objectExpose a familiar API
Mmm... Masala Ruby
the recipeBuild an objectTest that objectExpose a familiar API
Antipattern: Bad Modeling
Dosa Tracker(I smell a startup opportunity)
CSV Filename,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala...
Columnsname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|...
Dataname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|rav...
ETLCSV      (extract, transform, load)
Hand-written SQLCSV
Slight improvement                        CSVCSV                       Mapper module ABunchOfSuperAwesomeDataTransformatio...
Active               Support                CSV                   ActiveCSV                                   Record      ...
module DosaTracker  class DosaStandMapper    def initialize(inputs={})      @inputs = inputs    end    def location      [...
require spec_helperdescribe DosaTracker::DosaStandMapper do  context "#location" do    it "should include the city and add...
context "#rating" do  [    [ "pretty good", 4 ],    [ "bad", 1 ],    [ "okay", 3 ],    [ "awesome", 5 ],    [ "meh", 2 ]  ...
def rating  case @inputs["review"]  when /bad/; 1  when /meh/; 2  when /okay/; 3  when /pretty good/; 4  when /awesome/; 5...
TipKeep objects testable by reducing internal dependencies.                     Each method tested individually.
context ".build" do    EXAMPLE_CSV = <<-CSVname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nag...
def self.build(io)  CSV.read(io, :headers => :first_row).map do |row|    self.new(row.to_hash)  endend
TipInitializers are dumb, factory methods are smart.             Follow Rails factory patterns where appropriate.
Factory method
Factory method   Initializer
context "#dosa_types" do  it "map a single dosa type to a list with a single item" do    DosaTracker::DosaStandMapper.new(...
TipDont stub in the class you’re testing.          It’s a smell. Reduce dependencies instead.
context "#to_model" do  it "should expose a model object with the newly-populated data" do    DosaTracker::DosaStandMapper...
class DosaStand < ActiveRecord::Base  # Domain logic hereendmodule DosaTracker  class DosaStandMapper    def to_attributes...
TipAbstract when youve got a pattern.              But not before.
TipWhen youve abstracted a pattern, make it a gem.           This is how good ideas are born.You don’t have to release it.
Antipattern:Too much view logic
http://www.flickr.com/photos/donpezzano/3496645152/                                                     Active             ...
http://www.flickr.com/photos/donpezzano/3496645152/                                                      Active            ...
http://www.flickr.com/photos/donpezzano/3496645152/                                                      Active            ...
http://www.flickr.com/photos/donpezzano/3496645152/                                                       Active           ...
http://www.flickr.com/photos/donpezzano/3496645152/                                                       Active           ...
autoload   :AttributeMethodsautoload   :BlockValidator, active_model/validatorautoload   :Callbacksautoload   :Conversiona...
Mix and match to suit your needs
class DosaSearchController < ApplicationController  def new    @search = DosaSearch.new  end  def show    @search = DosaSe...
describe DosaSearch do  include Test::Unit::Assertions  include ActiveModel::Lint::Tests  def model    subject  end  Activ...
class DosaSearch  include ActiveModel::Conversion  def initialize(attrs={})    @attributes = attrs  end  def persisted?   ...
TipIf you accept attributes, mass-assign.            It’s simple and straightforward.
context "attributes" do  it "should assign city" do    DosaSearch.new(:city => "Chennai").city.should == "Chennai"  endend...
class DosaSearch  include ActiveModel::Conversion  include ActiveModel::Validations  attr_reader :attributes  attr_accesso...
class DosaSearchController < ApplicationController  def new    @search = DosaSearch.new  end  def show    @search = DosaSe...
Antipattern: Slavish Adherence       (with zombies)
The Uncanny Valley
class Person  include Validatable  validates_presence_of :name  attr_accessor :nameend
class Person  include Validatable  validates_presence_of :name, :times => 1  attr_accessor :nameend
class MortgageApplication  include Validatable  validates_presence_of :ssn, :groups => [:saving, :underwriting]  validates...
class MortgageApplication  include Validatable  validates_presence_of :ssn, :groups => [:saving, :underwriting]  validates...
Validations! Everywhere!
http://www.flickr.com/photos/rodolphoreis/5253294758/          [your library here]
Validations was a great gem.    It solved a real need.
Database.establish_connection
ActiveRecordDatabase.establish_connection
ActiveRecord                        ValidatableDatabase.establish_connection
ActiveRecord                                ValidatableDatabase.establish_connection                        [your library ...
Post-Rails?http://www.flickr.com/photos/vogelium/2105821119
Rails isn’t going anywhere
What is Ruby on Rails anyway?
What is Ruby on Rails anyway?          Routing?
What is Ruby on Rails anyway?          Routing?         Requires?
What is Ruby on Rails anyway?          Routing?         Requires?   A set of conventions?
Post-Rails:use individual pieces without being tied to the whole
ActiveRecord anywhere    First-class SinatraUnintrusive ActiveSupport
More generally, code is now more portable
Rails 3         Active         ModelActive         Active          Action          ActionRecord        Resource         Ma...
Sinatra         Active         ModelActive                      ActionRecord                      Mailer      Active     S...
What happens when stuff gets modular
How to learn Ruby
How to learn Ruby    (secret)
“Dude, this is RubyConf. How many people here do you        really think don’t already know Ruby?”
1Read Ruby Code
1aRead good Ruby Code
2Write Ruby Code
2aWrite Ruby Code (without Rails)
3Structure your libraries like gems   Run an internal gem server         Release a gem!
Robots do what every other robot does
Robots do what every other robot does      Don’t be a robot!
Brian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthriequestions?                              http://www.flickr....
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Ruby Plus Rails Plus Your Application Minus Rails
Upcoming SlideShare
Loading in...5
×

Ruby Plus Rails Plus Your Application Minus Rails

3,170

Published on

Ruby on Rails is a famously opinionated framework that handles ninety percent of the problems a typical web application faces. But what about the last ten percent? Every app has to jump off the Rails eventually, whether that means integrating with an external web service, importing data from another database, or providing enhanced search functionality. In this talk I'll lead you through some patterns for handling those cases, and discuss certain features of Rails 3 that let you leverage the best pieces of the core framework without resorting to ugly hacks. Finally we'll discuss what a new, more modular core framework means for a post-Rails world.

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,170
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
34
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Hero of Rails 3\n
  • Hero of Rails 3\n
  • Hero of Rails 3\n
  • Hero of Rails 3\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Masahiro Mori - 1970\n
  • Masahiro Mori in 1970\n
  • Masahiro Mori in 1970\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Ruby Plus Rails Plus Your Application Minus Rails

    1. 1. RubyPlus RailsPlus Your ApplicationMinus RailsBrian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthrie
    2. 2. TheLastTenPercentBrian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthrie
    3. 3. How to do complex things in Ruby (without shooting yourself in the foot) 2010
    4. 4. How to do simple things in Ruby (with care and craft) 2011
    5. 5. the last10%
    6. 6. So what’s hard about this?(Is it time to go check out the talk in the other room? That guy seems cool.)
    7. 7. Nothing!
    8. 8. Every good talk needs a rant
    9. 9. not complex
    10. 10. There’s an army of programmers looking for Rails bugs
    11. 11. Your code? Just you.
    12. 12. Craft is even more important.
    13. 13. notcookiecutter
    14. 14. Most Ruby programmers are Rails programmers first
    15. 15. Learning what Rails doesn’t dois as important as learning what it does
    16. 16. For those craftspeople here: Thank you
    17. 17. Gaps in Rails:Where’s the problem?
    18. 18. “Prior to Rails 3.0, if a plugin or gemdeveloper wanted to have an objectinteract with Action Pack helpers, it wasrequired to either copy chunks of codefrom Rails, or monkey patch entirehelpers to make them handle objects thatdid not exactly conform to the ActiveRecord interface. This would result incode duplication and fragile applicationsthat broke on upgrades. - ActiveModel README
    19. 19. Rails 2Active Active Action ActionRecord Resource Mailer Pack Active Railties Support
    20. 20. Presentation Logic Data
    21. 21. Presentation Logic Dataform_for @user do
    22. 22. Presentation Logic Dataform_for @user do @user = User.find(params[:id])
    23. 23. Presentation Logic Dataform_for @user do @user = User.find(params[:id])
    24. 24. Presentation Logic Dataform_for @user do @user = User.find(params[:id])
    25. 25. Presentation Logic Dataform_for @user do @user = User.find(params[:id]) @fb_user = FbUser.find(params[:id])
    26. 26. Presentation Logic Data form_for @user do @user = User.find(params[:id])form_for @fb_user do @fb_user = FbUser.find(params[:id])
    27. 27. • Domain models that aren’t database tables• Importing and transforming data• Web service clients• Presenter objects (not a comprehensive list)
    28. 28. Rails 2Active Active Action ActionRecord Resource Mailer Pack Active Railties Support
    29. 29. Rails 3 Active ModelActive Active Action ActionRecord Resource Mailer Pack Active Railties Support
    30. 30. Active gem active_model Model Active gem active_support,Support :require => false
    31. 31. the principles Simplicity Testability Abstractability Community
    32. 32. the principlesCode Simplicity Testability Abstractability Community
    33. 33. S Single responsibility principle An object should have only a single responsibility.O Open/closed principle Software entities … should be open for extension, but closed for modification.L Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.I Dependency inversion principle Depend upon Abstractions. Do not depend upon concretions.D Interface segregation principle Many client specific interfaces are better than one general purpose interface.
    34. 34. S Single responsibility principle An object should have only a single responsibility.O Open/closed principle Software entities … should be open for extension, but closed for modification.L Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.I Dependency inversion principle Depend upon Abstractions. Do not depend upon concretions.D Interface segregation principle Many client specific interfaces are better than one general purpose interface.
    35. 35. SD Card Principles
    36. 36. S Single responsibility principle An object should have only a single responsibility.O Open/closed principle Software entities … should be open for extension, but closed for modification.L Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.I Dependency inversion principle Depend upon Abstractions. Do not depend upon concretions.D Interface segregation principle Many client specific interfaces are better than one general purpose interface.
    37. 37. S Single responsibility principle An object should have only a single responsibility.O Open/closed principle Software entities … should be open for extension, but closed for modification.L Liskov substitution principle Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. I Dependency inversion principle Depend upon Abstractions. Do not depend upon concretions.D Interface segregation principle Many client specific interfaces are better than one general purpose interface.Mini SD Card Principles
    38. 38. the principles Simplicity TestabilityArchitecture Abstractability Community
    39. 39. IdiomaticityIdiom (plural idioms) 1. A manner of speaking, a way of expressing oneself. 2. An artistic style (for example, in art, architecture, or music); an instance of such a style. 3. An expression peculiar to or characteristic of a particular language, especially when the meaning is illogical or separate from the meanings of its component words. 4. (linguistics) A communicative system under study, which could be called either a dialect or a language, when its status as a language or dialect is irrelevant. 5. (programming) A programming construct or phraseology generally held to be the most efficient, elegant or effective means to achieve a particular result or behavior. http://en.wiktionary.org/wiki/idiom
    40. 40. IdiomaticityIdiom (plural idioms) 1. A manner of speaking, a way of expressing oneself. 2. An artistic style (for example, in art, architecture, or music); an instance of such a style. 3. An expression peculiar to or characteristic of a particular language, especially when the meaning is illogical or separate from the meanings of its component words. 4. (linguistics) A communicative system under study, which could be called either a dialect or a language, when its status as a language or dialect is irrelevant. 5. (programming) A programming construct or phraseology generally held to be the most efficient, elegant or effective means to achieve a particular result or behavior. http://en.wiktionary.org/wiki/idiom
    41. 41. Some of the best Ruby programmers have gone against commonly-accepted style
    42. 42. Keep it simple when you canBreak the rules when you must (or when it sounds like fun)
    43. 43. The best* Ruby code is clean, simple, and follows community idioms. * Easiest to maintain.
    44. 44. the recipeBuild an objectTest that objectExpose a familiar API
    45. 45. Mmm... Masala Ruby
    46. 46. the recipeBuild an objectTest that objectExpose a familiar API
    47. 47. Antipattern: Bad Modeling
    48. 48. Dosa Tracker(I smell a startup opportunity)
    49. 49. CSV Filename,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|ravaSri Sai Sagar,Bangalore,"5th Cross, 18th Main Road, HAL 2ndStage",Indiranagar,plain|paper|masala|rava masala|mysore masala|coconut
    50. 50. Columnsname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|ravaSri Sai Sagar,Bangalore,"5th Cross, 18th Main Road, HAL 2ndStage",Indiranagar,plain|paper|masala|rava masala|mysore masala|coconut
    51. 51. Dataname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|ravaSri Sai Sagar,Bangalore,"5th Cross, 18th Main Road, HAL 2ndStage",Indiranagar,plain|paper|masala|rava masala|mysore masala|coconut
    52. 52. ETLCSV (extract, transform, load)
    53. 53. Hand-written SQLCSV
    54. 54. Slight improvement CSVCSV Mapper module ABunchOfSuperAwesomeDataTransformationMethods def some_conversion_that_wont_make_sense_six_months_from_now(inputs) end end
    55. 55. Active Support CSV ActiveCSV Record Mapper module DosaTracker class DosaStandMapper def initialize(inputs={}) end def to_model # Output end end end
    56. 56. module DosaTracker class DosaStandMapper def initialize(inputs={}) @inputs = inputs end def location [ @inputs["city"], @inputs["address"], @inputs["landmark"] ].join(", ") end endend
    57. 57. require spec_helperdescribe DosaTracker::DosaStandMapper do context "#location" do it "should include the city and address" do DosaTracker::DosaStandMapper.new( city => Chennai, address => 2nd Avenue, Anna Nagar ).location.should match("Chennai, 2nd Avenue, Anna Nagar") end endend
    58. 58. context "#rating" do [ [ "pretty good", 4 ], [ "bad", 1 ], [ "okay", 3 ], [ "awesome", 5 ], [ "meh", 2 ] ].each do |review, rating| it "should match a review of #{review} to a rating of #{rating} stars" do DosaTracker::DosaStandMapper.new( review => "it was sort of #{review}" ).rating.should == rating end endend
    59. 59. def rating case @inputs["review"] when /bad/; 1 when /meh/; 2 when /okay/; 3 when /pretty good/; 4 when /awesome/; 5 endend
    60. 60. TipKeep objects testable by reducing internal dependencies. Each method tested individually.
    61. 61. context ".build" do EXAMPLE_CSV = <<-CSVname,city,address,district,review,dosa typesSukh Sagar,Chennai,2nd Ave,Anna Nagar,plain|paper|masala|mysore masala|ravaSri Sai Sagar,Bangalore,"5th Cross, 18th Main Road, HAL 2nd Stage",Indiranagar,plain|paper|masala|rava masala|mysore masala|coconutCSV it "should instantiate an array of mappers based on the file its given" do csv_file = Rails.root.join("test", "tmp.csv") csv_file.open("w") { |io| io << EXAMPLE_CSV } mappers = DosaTracker::DosaStandMapper.build(csv_file.open) mappers.size.should == 2 mappers[0].name.should == Sukh Sagar end end
    62. 62. def self.build(io) CSV.read(io, :headers => :first_row).map do |row| self.new(row.to_hash) endend
    63. 63. TipInitializers are dumb, factory methods are smart. Follow Rails factory patterns where appropriate.
    64. 64. Factory method
    65. 65. Factory method Initializer
    66. 66. context "#dosa_types" do it "map a single dosa type to a list with a single item" do DosaTracker::DosaStandMapper.new( dosa types => rava ).dosa_types.should == [ DosaType.new(:name => "rava") ] end it "map pipe-delimited dosa types to a list of multiple types" do DosaTracker::DosaStandMapper.new( dosa types => rava|masala|paper|butter ).dosa_types.should == [ DosaType.new(:name => "rava"), DosaType.new(:name => "masala"), DosaType.new(:name => "paper"), DosaType.new(:name => "butter") ] endenddef dosa_types @inputs["dosa types"].split("|").map do |name| DosaType.new(:name => name) endend
    67. 67. TipDont stub in the class you’re testing. It’s a smell. Reduce dependencies instead.
    68. 68. context "#to_model" do it "should expose a model object with the newly-populated data" do DosaTracker::DosaStandMapper.new( name => Sukh Sagar, city => Chennai, address => 2nd Avenue, Anna Nagar, review => Pretty good, dosa types => plain|paper|masala|mysore masala|rava ).to_model.location.should match("Chennai, 2nd Avenue, Anna Nagar") endend
    69. 69. class DosaStand < ActiveRecord::Base # Domain logic hereendmodule DosaTracker class DosaStandMapper def to_attributes { name: self.name, rating: self.rating, location: self.location, dosa_types: self.dosa_types } end def to_model DosaStand.new(self.to_attributes) end endend
    70. 70. TipAbstract when youve got a pattern. But not before.
    71. 71. TipWhen youve abstracted a pattern, make it a gem. This is how good ideas are born.You don’t have to release it.
    72. 72. Antipattern:Too much view logic
    73. 73. http://www.flickr.com/photos/donpezzano/3496645152/ Active Model
    74. 74. http://www.flickr.com/photos/donpezzano/3496645152/ Active Model No integration dependencies
    75. 75. http://www.flickr.com/photos/donpezzano/3496645152/ Active Model No integration dependencies Mix and match
    76. 76. http://www.flickr.com/photos/donpezzano/3496645152/ Active Model No integration dependencies Mix and match Quack like a duck
    77. 77. http://www.flickr.com/photos/donpezzano/3496645152/ Active Model No integration dependencies Mix and match Quack like a duck Keep it consistent
    78. 78. autoload :AttributeMethodsautoload :BlockValidator, active_model/validatorautoload :Callbacksautoload :Conversionautoload :DeprecatedErrorMethodsautoload :Dirtyautoload :EachValidator, active_model/validatorautoload :Errorsautoload :Lintautoload :MassAssignmentSecurityautoload :Name, active_model/namingautoload :Namingautoload :Observer, active_model/observingautoload :Observingautoload :Serializationautoload :TestCaseautoload :Translationautoload :Validationsautoload :Validator
    79. 79. Mix and match to suit your needs
    80. 80. class DosaSearchController < ApplicationController def new @search = DosaSearch.new end def show @search = DosaSearch.new(params[:search]) @results = @search.results endend
    81. 81. describe DosaSearch do include Test::Unit::Assertions include ActiveModel::Lint::Tests def model subject end ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m| example m.gsub(_, ) do send m end endend
    82. 82. class DosaSearch include ActiveModel::Conversion def initialize(attrs={}) @attributes = attrs end def persisted? false endend
    83. 83. TipIf you accept attributes, mass-assign. It’s simple and straightforward.
    84. 84. context "attributes" do it "should assign city" do DosaSearch.new(:city => "Chennai").city.should == "Chennai" endendcontext "validations" do it "should not be valid if a city is not specified" do DosaSearch.new.should have(1).error_on(:city) end it "should be valid if it has a city" do DosaSearch.new(:city => "Mysore").should be_valid endend
    85. 85. class DosaSearch include ActiveModel::Conversion include ActiveModel::Validations attr_reader :attributes attr_accessor :city validates_presence_of :city def initialize(attrs={}) @attributes = attrs @attributes.each do |key, value| send "#{key}=", value end end def persisted? false endend
    86. 86. class DosaSearchController < ApplicationController def new @search = DosaSearch.new end def show @search = DosaSearch.new(params[:search]) @results = @search.results endend
    87. 87. Antipattern: Slavish Adherence (with zombies)
    88. 88. The Uncanny Valley
    89. 89. class Person include Validatable validates_presence_of :name attr_accessor :nameend
    90. 90. class Person include Validatable validates_presence_of :name, :times => 1 attr_accessor :nameend
    91. 91. class MortgageApplication include Validatable validates_presence_of :ssn, :groups => [:saving, :underwriting] validates_presence_of :name, :groups => :underwriting attr_accessor :name, :ssnend
    92. 92. class MortgageApplication include Validatable validates_presence_of :ssn, :groups => [:saving, :underwriting] validates_presence_of :name, :groups => :underwriting attr_accessor :name, :ssnend>> application = MortgageApplication.new>> application.ssn = 377990118>> application.valid_for_saving?=> trueapplication.valid_for_underwriting?=> false
    93. 93. Validations! Everywhere!
    94. 94. http://www.flickr.com/photos/rodolphoreis/5253294758/ [your library here]
    95. 95. Validations was a great gem. It solved a real need.
    96. 96. Database.establish_connection
    97. 97. ActiveRecordDatabase.establish_connection
    98. 98. ActiveRecord ValidatableDatabase.establish_connection
    99. 99. ActiveRecord ValidatableDatabase.establish_connection [your library here]
    100. 100. Post-Rails?http://www.flickr.com/photos/vogelium/2105821119
    101. 101. Rails isn’t going anywhere
    102. 102. What is Ruby on Rails anyway?
    103. 103. What is Ruby on Rails anyway? Routing?
    104. 104. What is Ruby on Rails anyway? Routing? Requires?
    105. 105. What is Ruby on Rails anyway? Routing? Requires? A set of conventions?
    106. 106. Post-Rails:use individual pieces without being tied to the whole
    107. 107. ActiveRecord anywhere First-class SinatraUnintrusive ActiveSupport
    108. 108. More generally, code is now more portable
    109. 109. Rails 3 Active ModelActive Active Action ActionRecord Resource Mailer Pack Active Railties Support
    110. 110. Sinatra Active ModelActive ActionRecord Mailer Active Support
    111. 111. What happens when stuff gets modular
    112. 112. How to learn Ruby
    113. 113. How to learn Ruby (secret)
    114. 114. “Dude, this is RubyConf. How many people here do you really think don’t already know Ruby?”
    115. 115. 1Read Ruby Code
    116. 116. 1aRead good Ruby Code
    117. 117. 2Write Ruby Code
    118. 118. 2aWrite Ruby Code (without Rails)
    119. 119. 3Structure your libraries like gems Run an internal gem server Release a gem!
    120. 120. Robots do what every other robot does
    121. 121. Robots do what every other robot does Don’t be a robot!
    122. 122. Brian Guthriebguthrie@thoughtworks.comhttp://twitter.com/bguthriequestions? http://www.flickr.com/photos/jonnya/4212907371/
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×