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

Architecting your Rails app for success! (EuRuK...

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. success • long project • big dev team • lots

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

    of code • scalable • big 1st release @benjamin_smith Saturday, June 29, 13
  3. 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
  4. 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
  5. 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
  6. fully contained engines • all tables namespaced • migrations •

    tests @benjamin_smith Saturday, June 29, 13
  7. 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
  8. fully contained engines • all tables namespaced • migrations •

    tests @benjamin_smith Saturday, June 29, 13
  9. class User < ActiveRecord::Base has_many :posts end class Post <

    ActiveRecord::Base belongs_to :user end Saturday, June 29, 13
  10. domain api • simple classes to wrap ActiveRecord calls •

    take as input: params or ids • output PORO @benjamin_smith Saturday, June 29, 13
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. ... 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
  19. 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