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 Slide

  2. Prem Sichanugrist
    !
    !
    @sikachu
    /sikachu

    View Slide

  3. View Slide

  4. View Slide



  5. *57600x speed

    View Slide


  6. Flight attendance
    (Can speak Chinese)

    View Slide


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

    View Slide



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


    View Slide

  9. View Slide


  10. 㟬૝ཁҰࠣ㠭佔吗?

    View Slide

  11. View Slide


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

    View Slide


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

    View Slide


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

    View Slide


  15. Yes, cream and sugar is fine.

    View Slide


  16. 谢谢

    View Slide


  17. View Slide


  18. 䓟ཁෆཁ׃఺ॄ㜮?

    View Slide


  19. 䓟ཁෆཁ׃఺ॄ㜮?

    View Slide


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

    View Slide


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


    View Slide


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



    View Slide


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




    View Slide


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





    View Slide

  25. View Slide

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

    View Slide

  27. "This is going to be fun"

    View Slide




  28. View Slide

  29. I lost my count

    View Slide

  30. It feels great!

    View Slide

  31. 谢谢

    View Slide

  32. Hidden gems in Ruby on Rails

    View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. View Slide

  38. View Slide

  39. View Slide

  40. "Rails is HUGE"

    View Slide

  41. View Slide

  42. View Slide

  43. Rails is modular

    View Slide

  44. Pick only part you use

    View Slide

  45. "I'm not doing web
    application"

    View Slide

  46. View Slide

  47. Use Rails' components

    View Slide

  48. Actively maintained

    View Slide

  49. Fully tested

    View Slide

  50. "I'll implement them myself"

    View Slide

  51. gem  install  rails

    View Slide

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

    View Slide

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

    View Slide

  54. gem  "mail"

    View Slide

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

    View Slide

  56. Action Pack

    View Slide

  57. Action Dispatch
    Middleware

    View Slide

  58. [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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

  62. Active Record

    View Slide

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

    View Slide

  64. Don't write raw
    SQL yourself

    View Slide

  65. http://xkcd.com/327/

    View Slide

  66. Active Model

    View Slide

  67. ActiveModel::Model

    View Slide

  68. Makes PORO acts

    like a model
    (PORO = Plain Old Ruby Object)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  72. ActiveModel::Validations

    View Slide

  73. Add validations to PORO

    View Slide

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

    View Slide

  75. 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 Slide

  76. Active Support

    View Slide

  77. Core Extensions

    View Slide

  78. String

    View Slide

  79. String#inquiry

    View Slide

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

    View Slide

  81. String#squish

    View Slide

  82. very_complex_sql  =  <    SELECT  *  
       FROM  posts  
       WHERE  state='published'  
    SQL  
    !
    #  =>  "    SELECT  *\n    FROM  posts\n    
    WHERE  state='published'\n"

    View Slide

  83. very_complex_sql  =  <    SELECT  *  
       FROM  posts  
       WHERE  state='published'  
    SQL  
    !
    #  =>  "SELECT  *  FROM  posts  WHERE  
    state='published'"

    View Slide

  84. String#strip_heredoc

    View Slide

  85. content  =  <    Hello  
           World!  
    README  
    !
    #=>  "    Hello\n        World!\n"

    View Slide

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

    View Slide

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

    View Slide

  88. content  =  <    Hello  
           World!  
    README  
    #=>  "Hello\n    World!\n"

    View Slide

  89. String#to_date
    String#to_datetime
    String#to_time

    View Slide

  90. 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 Slide

  91. Hash

    View Slide

  92. Hash#transform_keys

    View Slide

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

    View Slide

  94. Array

    View Slide

  95. Array#extract_options  
    Array#extract_options!

    View Slide

  96. Keyword arguments
    Until we all using Ruby 2.0

    View Slide

  97. #  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 Slide

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

    View Slide

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

    View Slide

  100. Array#in_groups

    View Slide

  101. %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 Slide

  102. Array#in_groups_of

    View Slide

  103. %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 Slide

  104. Object

    View Slide

  105. Object#in?

    View Slide

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

    View Slide

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

    View Slide

  108. Object#blank?  
    Object#present?

    View Slide

  109. 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 Slide

  110. Disclaimer

    View Slide

  111. Active Support is
    lazy-loaded

    View Slide

  112. require  "active_support"

    View Slide

  113. require  "active_support"  
    "Hello".inquiry  
    !

    View Slide

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

    View Slide

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

    View Slide

  116. require  "active_support/all"

    View Slide

  117. require  "active_support/all"

    View Slide

  118. View Slide

  119. View Slide

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

    View Slide

  121. require  "active_support/core_ext/string"

    View Slide

  122. http://guides.rubyonrails.org

    View Slide

  123. Thank you!
    Prem Sichanugrist

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

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

    View Slide