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

Hidden gems in Ruby on Rails

Hidden gems in Ruby on Rails

Have you heard of a web framework called Ruby on Rails? There're a lot of stuff hidden under the hood of Ruby on Rails that you might not know about, and it might be really useful for you even if you aren't creating a web application. Let's not reimplement the wheel, and see what you can do if you include some part of Rails into your Ruby project.

Presented at RubyConf China 2013 on Oct 27, 2013.

Video is available at http://www.infoq.com/cn/presentations/hidden-gems-inside-those-of-Ruby-on-rails

Prem Sichanugrist

October 27, 2013
Tweet

More Decks by Prem Sichanugrist

Other Decks in Programming

Transcript

  1. Hidden gems in Ruby on Rails

    View full-size slide

  2. Prem Sichanugrist
    !
    !
    @sikachu
    /sikachu

    View full-size slide



  3. *57600x speed

    View full-size slide


  4. Flight attendance
    (Can speak Chinese)

    View full-size slide


  5. Me
    (Thai)
    Flight attendance
    (Can speak Chinese)

    View full-size slide



  6. (Cannot speak Chinese)
    Flight attendance
    (Can speak Chinese)
    Me


    View full-size slide


  7. 㟬૝ཁҰࠣ㠭佔吗?

    View full-size slide


  8. Yes, I would like some coffee,
    please.

    View full-size slide


  9. 㟬૝ཁҰࠣ䑊༉҃౶?

    View full-size slide


  10. 㟬૝ཁҰࠣ䑊༉҃౶?

    View full-size slide


  11. Yes, cream and sugar is fine.

    View full-size slide


  12. 䓟ཁෆཁ׃఺ॄ㜮?

    View full-size slide


  13. 䓟ཁෆཁ׃఺ॄ㜮?

    View full-size slide


  14. 㟬ت欢٣鸡೑҃ૉ৯?

    View full-size slide


  15. 㟬ت欢٣鸡೑҃ૉ৯?


    View full-size slide


  16. 㟬ت欢٣鸡೑҃ૉ৯?



    View full-size slide


  17. 㟬ت欢٣鸡೑҃ૉ৯?




    View full-size slide


  18. 㟬ت欢٣鸡೑҃ૉ৯?





    View full-size slide

  19. "Let's count how many
    people trying to speak
    Chinese to me"

    View full-size slide

  20. "This is going to be fun"

    View full-size slide

  21. I lost my count

    View full-size slide

  22. It feels great!

    View full-size slide

  23. Hidden gems in Ruby on Rails

    View full-size slide

  24. "Rails is HUGE"

    View full-size slide

  25. Rails is modular

    View full-size slide

  26. Pick only part you use

    View full-size slide

  27. "I'm not doing web
    application"

    View full-size slide

  28. Use Rails' components

    View full-size slide

  29. Actively maintained

    View full-size slide

  30. Fully tested

    View full-size slide

  31. "I'll implement them myself"

    View full-size slide

  32. gem  install  rails

    View full-size slide

  33. Rails
    • Action Mailer
    • Action Pack
    • Active Record
    • Active Model
    • Active Support
    • Railties

    View full-size slide

  34. Rails
    • Action Mailer
    • Action Pack
    • Active Record
    • Active Model
    • Active Support
    • Railties

    View full-size slide

  35. gem  "mail"

    View full-size slide

  36. Rails
    • Action Mailer
    • Action Pack
    • Active Record
    • Active Model
    • Active Support
    • Railties

    View full-size slide

  37. Action Dispatch
    Middleware

    View full-size slide

  38. [master][~/Projects/rails] ls \
    > actionpack/lib/action_dispatch/middleware
    callbacks.rb public_exceptions.rb ssl.rb
    cookies.rb reloader.rb stack.rb
    debug_exceptions.rb remote_ip.rb static.rb
    exception_wrapper.rb request_id.rb templates
    flash.rb session
    params_parser.rb show_exceptions.rb

    View full-size slide

  39. ActionDispatch::ShowException
    Rescue and display the exception message

    View full-size slide

  40. ActionDispatch::SSL
    Redirects all non-SSL requests to HTTPS

    View full-size slide

  41. ActionDispatch::Static
    Serves static file in the path

    View full-size slide

  42. Active Record

    View full-size slide

  43. Pick one:
    • Active Record
    • DataMapper
    • Sequel
    • NoSQL varieties

    View full-size slide

  44. Don't write raw
    SQL yourself

    View full-size slide

  45. http://xkcd.com/327/

    View full-size slide

  46. Active Model

    View full-size slide

  47. ActiveModel::Model

    View full-size slide

  48. Makes PORO acts

    like a model
    (PORO = Plain Old Ruby Object)

    View full-size slide

  49. ActiveModel::Model
    • Naming helpers
    • I18n support
    • Validation

    View full-size slide

  50. class  Person  
       include  ActiveModel::Model  
       attr_accesssor  :name,  :age  
    end  
       
    person  =  Person.new(name:  "Prem",  age:  27)  
    person.valid?  #=>  true  
    person.name  #=>  "Prem"

    View full-size slide

  51. ActiveModel::Model
    • Naming helpers
    • I18n support
    • Validation

    View full-size slide

  52. ActiveModel::Validations

    View full-size slide

  53. Add validations to PORO

    View full-size slide

  54. class  Person  
       include  ActiveModel::Validations  
       
       attr_accessor  :name,  :age  
       validates  :name,  presence:  true  
       validates  :age,  numericality:  true  
    end  
    !
    !
    !

    View full-size slide

  55. class  Person  
       include  ActiveModel::Validations  
       
       attr_accessor  :name,  :age  
       validates  :name,  presence:  true  
       validates  :age,  numericality:  true  
    end  
    !
    person  =  Person.new  
    person.name  =  ""  
    person.valid?  #=>  false

    View full-size slide

  56. Active Support

    View full-size slide

  57. Core Extensions

    View full-size slide

  58. String#inquiry

    View full-size slide

  59. country  =  'china'  
    country  =  country.inquiry  
    !
    country.china?  #=>  true  
    country.usa?  #=>  false

    View full-size slide

  60. String#squish

    View full-size slide

  61. very_complex_sql  =  <<-­‐SQL  
       SELECT  *  
       FROM  posts  
       WHERE  state='published'  
    SQL  
    !
    #  =>  "    SELECT  *\n    FROM  posts\n    
    WHERE  state='published'\n"

    View full-size slide

  62. very_complex_sql  =  <<-­‐SQL.squish  
       SELECT  *  
       FROM  posts  
       WHERE  state='published'  
    SQL  
    !
    #  =>  "SELECT  *  FROM  posts  WHERE  
    state='published'"

    View full-size slide

  63. String#strip_heredoc

    View full-size slide

  64. content  =  <<-­‐README  
       Hello  
           World!  
    README  
    !
    #=>  "    Hello\n        World!\n"

    View full-size slide

  65. class  FancyHello  
       def  initialize(user)  
           if  should_say_hello_to?  user  
               content  =  <<-­‐README  
                   Hello  
                       World!  
               README  
           end  
       end  
    end  
    !
    #=>  "                Hello\n                    World!\

    View full-size slide

  66. class  FancyHello  
       def  initialize(user)  
           if  should_say_hello_to?  user  
               content  =  <<-­‐README  
    Hello  
       World!  
    README  
           end  
       end  
    end  
    !
    #=>  "Hello\n    World!\n"

    View full-size slide

  67. content  =  <<-­‐README.strip_heredoc  
       Hello  
           World!  
    README  
    #=>  "Hello\n    World!\n"

    View full-size slide

  68. String#to_date
    String#to_datetime
    String#to_time

    View full-size slide

  69. Date.parse('2013-­‐10-­‐27')  
    #=>  Sun,  27  Oct  2013  
    '2013-­‐10-­‐27'.to_date  
    #=>  Sun,  27  Oct  2013  
       
    DateTime.parse('2013-­‐10-­‐27  09:40:00')  
    #=>  Sun,  27  Oct  2013  09:40:00  +0000  
    '2013-­‐10-­‐27  09:40:00'.to_datetime  
    #=>  Sun,  27  Oct  2013  09:40:00  +0000  
       
    Time.parse('09:40:00')  
    #=>  2013-­‐10-­‐27  09:40:00  +0800  
    '09:00:00'.to_time  
    #=>  2013-­‐10-­‐27  09:40:00  +0800

    View full-size slide

  70. Hash#transform_keys

    View full-size slide

  71. hash  =  {  foo:  'foo',  bar:  'bar'  }  
    #=>  {:foo=>"foo",  :bar=>"bar"}  
    !
    hash.transform_keys  {  |key|  
       key.to_s.capitalize  }  
    #=>  {"Foo"=>"foo",  "Bar"=>"bar"}

    View full-size slide

  72. Array#extract_options  
    Array#extract_options!

    View full-size slide

  73. Keyword arguments
    Until we all using Ruby 2.0

    View full-size slide

  74. #  say_hello("John",  "Jane",  language:  "zh-­‐CN")  
    def  say_hello(*names_or_options)  
       if  names_or_options.last.is_a?(Hash)  
           options  =  names_or_options.pop  
           names  =  names_or_options  
       else  
           options  =  {}  
           names  =  names_or_options  
       end  
       
       case  options[:language]  
       #  ...  

    View full-size slide

  75. #  say_hello("John",  "Jane",  language:  "zh-­‐CN")  
    def  say_hello(*names)  
       options  =  names.extract_options!  
         
       case  options[:language]  
       #  ...  

    View full-size slide

  76. #  say_hello("John",  "Jane",  language:  "zh-­‐CN")  
    def  say_hello(*names,  language:  "en-­‐US")  
       case  language  
       #  ...  
    !
    !

    View full-size slide

  77. Array#in_groups

    View full-size slide

  78. %w(1  2  3  4  5  6  7  8  9  10).in_groups(3)  
    #  =>  [  
    #            [1,  2,  3,  4],  
    #            [5,  6,  7,  nil],  
    #            [8,  9,  10,  nil]  
    #        ]

    View full-size slide

  79. Array#in_groups_of

    View full-size slide

  80. %w(1  2  3  4  5  6  7  8  9  10).in_groups_of(3)  
    #  =>  [  
    #            [1,  2,  3],  
    #            [4,  5,  6],  
    #            [7,  8,  9],  
    #            [10,  nil,  nil]  
    #        ]  

    View full-size slide

  81. STARTING_POKEMONS  =  %w(Chespin  Fennekin  Froakie)  
       
    if  STARTING_POKEMONS.include?(current_pokemon)  
       #  ...  
    end

    View full-size slide

  82. STARTING_POKEMONS  =  %w(Chespin  Fennekin  Froakie)  
       
    if  current_pokemon.in?(STARTING_POKEMONS)  
       #  ...  
    end

    View full-size slide

  83. Object#blank?  
    Object#present?

    View full-size slide

  84. str  =  nil  
    str.nil?  #=>  true  
    str.empty?  #=>  NoMethodError  
    str.blank?  #=>  true  
    str.present?  #=>  false  
       
    str  =  ""  
    str.nil?  #=>  false  
    str.empty?  #=>  true  
    str.blank?  #=>  true  
    str.present?  #=>  false  
       
    str  =  "Hello"  
    str.nil?  #=>  false  
    str.empty?  #=>  false  
    str.blank?  #=>  false  
    str.present?  #=>  true

    View full-size slide

  85. Active Support is
    lazy-loaded

    View full-size slide

  86. require  "active_support"

    View full-size slide

  87. require  "active_support"  
    "Hello".inquiry  
    !

    View full-size slide

  88. require  "active_support"  
    "Hello".inquiry  
    #=>  NoMethodError:  undefined  method  
    `inquiry'  for  "Hello":String

    View full-size slide

  89. require  "active_support"  
    "Hello".inquiry  
    #=>  NoMethodError:  undefined  method  
    `inquiry'  for  "Hello":String

    View full-size slide

  90. require  "active_support/all"

    View full-size slide

  91. require  "active_support/all"

    View full-size slide

  92. require  "active_support/core_ext/string/inquiry"

    View full-size slide

  93. require  "active_support/core_ext/string"

    View full-size slide

  94. http://guides.rubyonrails.org

    View full-size slide

  95. Thank you!
    Prem Sichanugrist

    (@sikachu)
    http://learn.thoughtbot.com

    20% off promotion Code:
    RUBYCONFCHINA
    I also have some stickers

    View full-size slide