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

Keeping Your Massive Rails App From Turning Into a S#!t Show (WindyCityRails 2013)

Benjamin Smith
September 12, 2013

Keeping Your Massive Rails App From Turning Into a S#!t Show (WindyCityRails 2013)

Benjamin Smith

September 12, 2013
Tweet

More Decks by Benjamin Smith

Other Decks in Technology

Transcript

  1. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show
    Thursday, September 12, 13

    View full-size slide

  2. Keeping Your Massive Rails
    App From Turning Into a
    SNAKE Show
    Thursday, September 12, 13

    View full-size slide

  3. Keeping Your Massive Rails
    App From Turning Into a
    SNAKE Show
    Thursday, September 12, 13

    View full-size slide

  4. Keeping Your Massive Rails
    App From Turning Into a
    CYLON Show
    Thursday, September 12, 13

    View full-size slide

  5. Keeping Your Massive Rails
    App From Turning Into a
    SHEEP Show
    Thursday, September 12, 13

    View full-size slide

  6. gem “sheep”
    gem “sheepsafe”
    gem “sheep-sebastian”
    gem “SheepDog”
    Thursday, September 12, 13

    View full-size slide

  7. gem “sheep”
    gem “sheepsafe”
    gem “sheep-sebastian”
    gem “SheepDog”
    Thursday, September 12, 13

    View full-size slide

  8. Thursday, September 12, 13

    View full-size slide

  9. Thursday, September 12, 13

    View full-size slide

  10. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show
    Benjamin Smith
    Thursday, September 12, 13

    View full-size slide

  11. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show
    Benjamin Smith
    Thursday, September 12, 13

    View full-size slide

  12. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show
    Benjamin Smith
    Thursday, September 12, 13

    View full-size slide

  13. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show
    Benjamin Smith
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  14. Keeping Your Massive Rails
    App From Turning Into a
    S#!t Show By Architecting
    It For Success
    Benjamin Smith
    Success
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  15. Benjamin Smith
    Success
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  16. Benjamin Smith
    Success
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  17. Benjamin Smith
    Success
    Architecting
    Rails
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  18. M
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  19. M V
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  20. M C
    V
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  21. once upon a time
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  22. success
    Thursday, September 12, 13

    View full-size slide

  23. long project
    Thursday, September 12, 13

    View full-size slide

  24. big dev team
    Thursday, September 12, 13

    View full-size slide

  25. lots of codez
    Thursday, September 12, 13

    View full-size slide

  26. scalable
    Thursday, September 12, 13

    View full-size slide

  27. big bang release
    Thursday, September 12, 13

    View full-size slide

  28. success
    • long project
    • big dev team
    • lots of code
    • scalable
    • big 1st release
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  29. a grain of salt
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  30. a grain of salt
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  31. success
    • long project
    • big dev team
    • lots of code
    • scalable
    • big 1st release
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  32. engines
    Thursday, September 12, 13

    View full-size slide

  33. a little background
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  34. the product
    • Multimedia content publishing
    • A social network
    • iOS app for consumers (using JSON API)
    • CMS (Rails) for admins
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  35. started simple
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  36. Thursday, September 12, 13

    View full-size slide

  37. Thursday, September 12, 13

    View full-size slide

  38. Thursday, September 12, 13

    View full-size slide

  39. Thursday, September 12, 13

    View full-size slide

  40. Thursday, September 12, 13

    View full-size slide

  41. Thursday, September 12, 13

    View full-size slide

  42. Thursday, September 12, 13

    View full-size slide

  43. Thursday, September 12, 13

    View full-size slide

  44. Thursday, September 12, 13

    View full-size slide

  45. not too bad
    Thursday, September 12, 13

    View full-size slide

  46. Thursday, September 12, 13

    View full-size slide

  47. Thursday, September 12, 13

    View full-size slide

  48. Thursday, September 12, 13

    View full-size slide

  49. Thursday, September 12, 13

    View full-size slide

  50. Thursday, September 12, 13

    View full-size slide

  51. Thursday, September 12, 13

    View full-size slide

  52. Thursday, September 12, 13

    View full-size slide

  53. Thursday, September 12, 13

    View full-size slide

  54. Thursday, September 12, 13

    View full-size slide

  55. but why stop there?
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  56. Thursday, September 12, 13

    View full-size slide

  57. Thursday, September 12, 13

    View full-size slide

  58. Thursday, September 12, 13

    View full-size slide

  59. Thursday, September 12, 13

    View full-size slide

  60. Thursday, September 12, 13

    View full-size slide

  61. Thursday, September 12, 13

    View full-size slide

  62. Thursday, September 12, 13

    View full-size slide

  63. how to get started
    Thursday, September 12, 13

    View full-size slide

  64. rails plugin new engine_name --mountable
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  65. gem "engine_name",

    path: "path/to/engine_name"
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  66. mount EngineName::Engine => "/engine_name",
    :as => "engine_name"
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  67. rails plugin new engine_name --mountable
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  68. rails plugin new engine_template --mountable
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  69. s/engine_template/new_engine_name/g
    s/EngineTemplate/NewEngineName/g
    for file in $(find . -name "*engine_template*")
    do
    mv $file `echo $file | sed s/engine_template/$1/`
    done
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  70. bundle gem gem_name
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  71. gem "gem_name",

    path: "path/to/gem_name"
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  72. bundle gem gem_template
    s/gem_template/new_gem_name/g
    s/GemTemplate/NewGemName/g
    for file in $(find . -name "*gem_template*")
    do
    mv $file `echo $file | sed s/gem_template/$1/`
    done
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  73. got it?
    got it?
    Thursday, September 12, 13

    View full-size slide

  74. engines the right way
    Thursday, September 12, 13

    View full-size slide

  75. fully contained engines
    • all tables namespaced
    • migrations
    • tests
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  76. table namespacing
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  77. Thursday, September 12, 13

    View full-size slide

  78. Thursday, September 12, 13

    View full-size slide

  79. Thursday, September 12, 13

    View full-size slide

  80. Thursday, September 12, 13

    View full-size slide

  81. Thursday, September 12, 13

    View full-size slide

  82. migrations inside
    engines
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  83. rake your_engine_name:install:migrations
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  84. module EngineWithMigrations
    class Engine < ::Rails::Engine
    isolate_namespace EngineWithMigrations
    initializer :append_migrations do |app|
    unless app.root.to_s.match root.to_s
    app.config.paths["db/migrate"] +=
    config.paths["db/migrate"].expanded
    end
    end
    end
    end
    http://pivotallabs.com/leave-your-migrations-in-your-rails-
    engines/
    Thursday, September 12, 13

    View full-size slide

  85. one table per migration
    http://pivotallabs.com/moving-db-tables-between-rails-
    engines/
    Thursday, September 12, 13

    View full-size slide

  86. testing the engines in
    isolation
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  87. Thursday, September 12, 13

    View full-size slide

  88. engines the right way
    Thursday, September 12, 13

    View full-size slide

  89. fully contained engines
    • all tables namespaced
    • migrations
    • tests
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  90. no circular
    dependencies
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  91. Thursday, September 12, 13

    View full-size slide

  92. Thursday, September 12, 13

    View full-size slide

  93. Thursday, September 12, 13

    View full-size slide

  94. class User < ActiveRecord::Base
    has_many :posts
    end
    class Post < ActiveRecord::Base
    belongs_to :user
    end
    Thursday, September 12, 13

    View full-size slide

  95. Thursday, September 12, 13

    View full-size slide

  96. domain api
    Thursday, September 12, 13

    View full-size slide

  97. domain api
    • simple classes to wrap ActiveRecord calls
    • take as input: params or ids
    • output PORO
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  98. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Thursday, September 12, 13

    View full-size slide

  99. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Thursday, September 12, 13

    View full-size slide

  100. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Thursday, September 12, 13

    View full-size slide

  101. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    class User
    def initialize(user_record)
    self.email = user_record.email
    end
    end
    Thursday, September 12, 13

    View full-size slide

  102. that’s a lie
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  103. it’s called the
    Data Mapper
    pattern
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  104. Thursday, September 12, 13

    View full-size slide

  105. @user.posts @post.user
    Thursday, September 12, 13

    View full-size slide

  106. class PostManager
    def find_all_by_user_id(user_id)
    PostRecord.where(user_id: user_id)
    # ... convert to PORO ...
    end
    end
    Thursday, September 12, 13

    View full-size slide

  107. class PostManager
    def find_all_by_user_id(user_id)
    PostRecord.where(user_id: user_id)
    # ... convert to PORO ...
    end
    end
    post_manager = PostManager.new
    @posts = post_manager.find_all_by_user_id(@user.id)
    Thursday, September 12, 13

    View full-size slide

  108. Thursday, September 12, 13

    View full-size slide

  109. Thursday, September 12, 13

    View full-size slide

  110. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    end
    Thursday, September 12, 13

    View full-size slide

  111. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    end
    user_manager = UserManager.new
    author = user_manager.find_by_id(@post.user_id)
    Thursday, September 12, 13

    View full-size slide

  112. Thursday, September 12, 13

    View full-size slide

  113. Thursday, September 12, 13

    View full-size slide

  114. engines the right way
    Thursday, September 12, 13

    View full-size slide

  115. no circular
    dependencies
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  116. started simple
    Thursday, September 12, 13

    View full-size slide

  117. Thursday, September 12, 13

    View full-size slide

  118. I live my life one green
    build at a time
    Thursday, September 12, 13

    View full-size slide

  119. Thursday, September 12, 13

    View full-size slide

  120. Thursday, September 12, 13

    View full-size slide

  121. Thursday, September 12, 13

    View full-size slide

  122. git whatchanged origin/master..
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  123. Thursday, September 12, 13

    View full-size slide

  124. how did it work out?
    Thursday, September 12, 13

    View full-size slide

  125. Thursday, September 12, 13

    View full-size slide

  126. engines are a pain...
    • LOW velocity for weeks (4-6)
    • client worries
    • opposite of Rails
    • one pair to start is a MUST
    • some technical hurtles
    • must be diligent about refactoring
    • monkey patching Rails
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  127. Thursday, September 12, 13

    View full-size slide

  128. ... but they get better
    • no slow down in development time
    • they age well
    • easier parallel development
    • potential for scaling
    • smart and fast build scripts
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  129. thumbs up
    @benjamin_smith
    Thursday, September 12, 13

    View full-size slide

  130. Thursday, September 12, 13

    View full-size slide

  131. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Thursday, September 12, 13

    View full-size slide

  132. thanks
    Thursday, September 12, 13

    View full-size slide

  133. more infoz:
    @benjamin_smith
    http://pivotallabs.com/tag/rails-application-suites/
    https://github.com/benjaminleesmith/sup_locator
    Thursday, September 12, 13

    View full-size slide