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

Architecting your Rails app for success! (EuRuKo 2013)

Architecting your Rails app for success! (EuRuKo 2013)

Benjamin Smith

June 29, 2013
Tweet

More Decks by Benjamin Smith

Other Decks in Programming

Transcript

  1. Architecting your Rails
    app for success!
    Benjamin Smith
    Saturday, June 29, 13

    View Slide

  2. Ben Smith
    Saturday, June 29, 13

    View Slide

  3. Ben Smith
    Saturday, June 29, 13

    View Slide

  4. Ben Smith
    Saturday, June 29, 13

    View Slide

  5. Ben Smith
    Saturday, June 29, 13

    View Slide

  6. @benjamin_smith
    Ben Smith
    Saturday, June 29, 13

    View Slide

  7. Architecting your Rails
    app for success!
    Benjamin Smith
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  8. MVC
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  9. once upon a time
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  10. success
    Saturday, June 29, 13

    View Slide

  11. long project
    Saturday, June 29, 13

    View Slide

  12. big dev team
    Saturday, June 29, 13

    View Slide

  13. lots of codez
    Saturday, June 29, 13

    View Slide

  14. scalable
    Saturday, June 29, 13

    View Slide

  15. big bang release
    Saturday, June 29, 13

    View Slide

  16. success
    • long project
    • big dev team
    • lots of code
    • scalable
    • big 1st release
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  17. a grain of salt
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  18. success
    • long project
    • big dev team
    • lots of code
    • scalable
    • big 1st release
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  19. engines
    Saturday, June 29, 13

    View Slide

  20. a little background
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  21. the product
    • Multimedia content publishing
    • A social network
    • iOS app for consumers (using JSON API)
    • CMS (Rails) for admins
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  22. started simple
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  23. Saturday, June 29, 13

    View Slide

  24. Saturday, June 29, 13

    View Slide

  25. Saturday, June 29, 13

    View Slide

  26. Saturday, June 29, 13

    View Slide

  27. Saturday, June 29, 13

    View Slide

  28. Saturday, June 29, 13

    View Slide

  29. Saturday, June 29, 13

    View Slide

  30. Saturday, June 29, 13

    View Slide

  31. Saturday, June 29, 13

    View Slide

  32. not too bad
    Saturday, June 29, 13

    View Slide

  33. Saturday, June 29, 13

    View Slide

  34. Saturday, June 29, 13

    View Slide

  35. Saturday, June 29, 13

    View Slide

  36. Saturday, June 29, 13

    View Slide

  37. Saturday, June 29, 13

    View Slide

  38. Saturday, June 29, 13

    View Slide

  39. Saturday, June 29, 13

    View Slide

  40. Saturday, June 29, 13

    View Slide

  41. Saturday, June 29, 13

    View Slide

  42. but why stop there?
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  43. Saturday, June 29, 13

    View Slide

  44. Saturday, June 29, 13

    View Slide

  45. Saturday, June 29, 13

    View Slide

  46. Saturday, June 29, 13

    View Slide

  47. Saturday, June 29, 13

    View Slide

  48. Saturday, June 29, 13

    View Slide

  49. Saturday, June 29, 13

    View Slide

  50. how to get started
    Saturday, June 29, 13

    View Slide

  51. rails plugin new engine_name --mountable
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  52. gem "engine_name",

    path: "path/to/engine_name"
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  53. mount EngineName::Engine => "/engine_name",
    :as => "engine_name"
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  54. rails plugin new engine_name --mountable
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  55. rails plugin new engine_template --mountable
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  56. 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
    Saturday, June 29, 13

    View Slide

  57. bundle gem gem_name
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  58. gem "gem_name",

    path: "path/to/gem_name"
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  59. 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
    Saturday, June 29, 13

    View Slide

  60. got it?
    got it?
    Saturday, June 29, 13

    View Slide

  61. engines the right way
    Saturday, June 29, 13

    View Slide

  62. fully contained engines
    • all tables namespaced
    • migrations
    • tests
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  63. table namespacing
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  64. Saturday, June 29, 13

    View Slide

  65. Saturday, June 29, 13

    View Slide

  66. Saturday, June 29, 13

    View Slide

  67. Saturday, June 29, 13

    View Slide

  68. Saturday, June 29, 13

    View Slide

  69. migrations inside
    engines
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  70. rake your_engine_name:install:migrations
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  71. 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/
    Saturday, June 29, 13

    View Slide

  72. one table per migration
    http://pivotallabs.com/moving-db-tables-between-rails-
    engines/
    Saturday, June 29, 13

    View Slide

  73. testing the engines in
    isolation
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  74. Saturday, June 29, 13

    View Slide

  75. engines the right way
    Saturday, June 29, 13

    View Slide

  76. fully contained engines
    • all tables namespaced
    • migrations
    • tests
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  77. no circular
    dependencies
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  78. Saturday, June 29, 13

    View Slide

  79. Saturday, June 29, 13

    View Slide

  80. Saturday, June 29, 13

    View Slide

  81. class User < ActiveRecord::Base
    has_many :posts
    end
    class Post < ActiveRecord::Base
    belongs_to :user
    end
    Saturday, June 29, 13

    View Slide

  82. Saturday, June 29, 13

    View Slide

  83. domain api
    Saturday, June 29, 13

    View Slide

  84. domain api
    • simple classes to wrap ActiveRecord calls
    • take as input: params or ids
    • output PORO
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  85. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Saturday, June 29, 13

    View Slide

  86. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Saturday, June 29, 13

    View Slide

  87. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Saturday, June 29, 13

    View Slide

  88. 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
    Saturday, June 29, 13

    View Slide

  89. Saturday, June 29, 13

    View Slide

  90. @user.posts @post.user
    Saturday, June 29, 13

    View Slide

  91. class PostManager
    def find_all_by_user_id(user_id)
    PostRecord.where(user_id: user_id)
    # ... convert to PORO ...
    end
    end
    Saturday, June 29, 13

    View Slide

  92. 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)
    Saturday, June 29, 13

    View Slide

  93. Saturday, June 29, 13

    View Slide

  94. Saturday, June 29, 13

    View Slide

  95. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    end
    Saturday, June 29, 13

    View Slide

  96. 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)
    Saturday, June 29, 13

    View Slide

  97. Saturday, June 29, 13

    View Slide

  98. Saturday, June 29, 13

    View Slide

  99. engines the right way
    Saturday, June 29, 13

    View Slide

  100. no circular
    dependencies
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  101. started simple
    Saturday, June 29, 13

    View Slide

  102. Saturday, June 29, 13

    View Slide

  103. I live my life one green
    build at a time
    Saturday, June 29, 13

    View Slide

  104. Saturday, June 29, 13

    View Slide

  105. Saturday, June 29, 13

    View Slide

  106. Saturday, June 29, 13

    View Slide

  107. git whatchanged
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  108. Saturday, June 29, 13

    View Slide

  109. how did it work out?
    Saturday, June 29, 13

    View Slide

  110. Saturday, June 29, 13

    View Slide

  111. 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
    • monkey patching Rails
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  112. Saturday, June 29, 13

    View Slide

  113. ... 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
    Saturday, June 29, 13

    View Slide

  114. thumbs up
    @benjamin_smith
    Saturday, June 29, 13

    View Slide

  115. Saturday, June 29, 13

    View Slide

  116. class UserManager
    def find_by_id(id)
    User.new(UserRecord.find(id))
    end
    private
    class UserRecord < ActiveRecord::Base
    validates :email, presence: true
    end
    end
    Saturday, June 29, 13

    View Slide

  117. thanks
    Saturday, June 29, 13

    View Slide

  118. questions?
    @benjamin_smith
    http://pivotallabs.com/tag/rails-application-suites/
    Saturday, June 29, 13

    View Slide