Architecting your Rails app for success! (EuRuKo 2013)

Architecting your Rails app for success! (EuRuKo 2013)

6d48d3849102b57bbc1462c0da0b3866?s=128

Benjamin Smith

June 29, 2013
Tweet

Transcript

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

    29, 13
  2. Ben Smith Saturday, June 29, 13

  3. Ben Smith Saturday, June 29, 13

  4. Ben Smith Saturday, June 29, 13

  5. Ben Smith Saturday, June 29, 13

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

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

    June 29, 13
  8. MVC @benjamin_smith Saturday, June 29, 13

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

  10. success Saturday, June 29, 13

  11. long project Saturday, June 29, 13

  12. big dev team Saturday, June 29, 13

  13. lots of codez Saturday, June 29, 13

  14. scalable Saturday, June 29, 13

  15. big bang release Saturday, June 29, 13

  16. success • long project • big dev team • lots

    of code • scalable • big 1st release @benjamin_smith Saturday, June 29, 13
  17. a grain of salt @benjamin_smith Saturday, June 29, 13

  18. success • long project • big dev team • lots

    of code • scalable • big 1st release @benjamin_smith Saturday, June 29, 13
  19. engines Saturday, June 29, 13

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

  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
  22. started simple @benjamin_smith Saturday, June 29, 13

  23. Saturday, June 29, 13

  24. Saturday, June 29, 13

  25. Saturday, June 29, 13

  26. Saturday, June 29, 13

  27. Saturday, June 29, 13

  28. Saturday, June 29, 13

  29. Saturday, June 29, 13

  30. Saturday, June 29, 13

  31. Saturday, June 29, 13

  32. not too bad Saturday, June 29, 13

  33. Saturday, June 29, 13

  34. Saturday, June 29, 13

  35. Saturday, June 29, 13

  36. Saturday, June 29, 13

  37. Saturday, June 29, 13

  38. Saturday, June 29, 13

  39. Saturday, June 29, 13

  40. Saturday, June 29, 13

  41. Saturday, June 29, 13

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

  43. Saturday, June 29, 13

  44. Saturday, June 29, 13

  45. Saturday, June 29, 13

  46. Saturday, June 29, 13

  47. Saturday, June 29, 13

  48. Saturday, June 29, 13

  49. Saturday, June 29, 13

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

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

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

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

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

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

  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
  57. bundle gem gem_name @benjamin_smith Saturday, June 29, 13

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

  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
  60. got it? got it? Saturday, June 29, 13

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

  62. fully contained engines • all tables namespaced • migrations •

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

  64. Saturday, June 29, 13

  65. Saturday, June 29, 13

  66. Saturday, June 29, 13

  67. Saturday, June 29, 13

  68. Saturday, June 29, 13

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

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

  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
  72. one table per migration http://pivotallabs.com/moving-db-tables-between-rails- engines/ Saturday, June 29, 13

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

  74. Saturday, June 29, 13

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

  76. fully contained engines • all tables namespaced • migrations •

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

  78. Saturday, June 29, 13

  79. Saturday, June 29, 13

  80. Saturday, June 29, 13

  81. class User < ActiveRecord::Base has_many :posts end class Post <

    ActiveRecord::Base belongs_to :user end Saturday, June 29, 13
  82. Saturday, June 29, 13

  83. domain api Saturday, June 29, 13

  84. domain api • simple classes to wrap ActiveRecord calls •

    take as input: params or ids • output PORO @benjamin_smith Saturday, June 29, 13
  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
  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
  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
  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
  89. Saturday, June 29, 13

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

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

  94. Saturday, June 29, 13

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

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

  98. Saturday, June 29, 13

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

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

  101. started simple Saturday, June 29, 13

  102. Saturday, June 29, 13

  103. I live my life one green build at a time

    Saturday, June 29, 13
  104. Saturday, June 29, 13

  105. Saturday, June 29, 13

  106. Saturday, June 29, 13

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

  108. Saturday, June 29, 13

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

  110. Saturday, June 29, 13

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

  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
  114. thumbs up @benjamin_smith Saturday, June 29, 13

  115. Saturday, June 29, 13

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

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