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

Service Modules

Service Modules

Lightning talk about refactoring Rails services from classes/objects to stateless modules.

Presented at the Ruby on Rails Oceania meetup on 11 July 2017.

Presentation slide deck markdown and speaker notes (useable in Deckset):
https://github.com/paulfioravanti/presentations/tree/master/service_modules

Abda861707b1e78e0fce47ced55f84ee?s=128

Paul Fioravanti

July 11, 2017
Tweet

Transcript

  1. Service Modules A minor refactoring @paulfioravanti 1

  2. @paulfioravanti 2

  3. Service Classes @paulfioravanti 3

  4. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 4
  5. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 5
  6. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 6
  7. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 7
  8. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 8
  9. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 9
  10. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if user && BCrypt::Password.new(user.password_digest) == params[:password] # ... else # ... end end end @paulfioravanti 10
  11. class UserAuthenticator def initialize(user) @user = user end def authenticated?(unencrypted_password)

    return false unless @user BCrypt::Password.new(@user.password_digest) == unencrypted_password end end @paulfioravanti 11
  12. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.new(user).authenticated?(params[:password]) # ... else # ... end end end @paulfioravanti 12
  13. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.new(user).authenticated?(params[:password]) sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 13
  14. ! @paulfioravanti 14

  15. BUT @paulfioravanti 15

  16. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.new(user).authenticated?(params[:password]) # ... else # ... end end end @paulfioravanti 16
  17. authenticator = UserAuthenticator.new(user) authenticator.authenticated? @paulfioravanti 17

  18. authenticator = UserAuthenticator.new(user) authenticator.authenticated? authenticator.two_factor_enabled? @paulfioravanti 18

  19. authenticator = UserAuthenticator.new(user) authenticator.authenticated? authenticator.two_factor_enabled? authenticator.authenticate_with_facebook @paulfioravanti 19

  20. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.new(user).authenticated?(params[:password]) # ... else # ... end end end @paulfioravanti 20
  21. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.authenticated?(user, params[:password]) # ... else # ... end end end @paulfioravanti 21
  22. class UserAuthenticator def initialize(user) @user = user end def authenticated?(unencrypted_password)

    return false unless @user BCrypt::Password.new(@user.password_digest) == unencrypted_password end end @paulfioravanti 22
  23. class UserAuthenticator def authenticated?(unencrypted_password) return false unless @user BCrypt::Password.new(@user.password_digest) ==

    unencrypted_password end end @paulfioravanti 23
  24. class UserAuthenticator def authenticated?(user, unencrypted_password) return false unless @user BCrypt::Password.new(@user.password_digest)

    == unencrypted_password end end @paulfioravanti 24
  25. class UserAuthenticator def authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 25
  26. class UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 26
  27. class UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 27
  28. ! @paulfioravanti 28

  29. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.authenticated?(user, params[:password]) # ... else # ... end end end @paulfioravanti 29
  30. BUT @paulfioravanti 30

  31. class UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 31
  32. class UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 32
  33. module UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 33
  34. module UserAuthenticator def self.authenticated?(user, unencrypted_password) return false unless user BCrypt::Password.new(user.password_digest)

    == unencrypted_password end end @paulfioravanti 34
  35. module UserAuthenticator module_function def self.authenticated?(user, unencrypted_password) return false unless user

    BCrypt::Password.new(user.password_digest) == unencrypted_password end end @paulfioravanti 35
  36. module UserAuthenticator module_function def authenticated?(user, unencrypted_password) return false unless user

    BCrypt::Password.new(user.password_digest) == unencrypted_password end end @paulfioravanti 36
  37. module UserAuthenticator module_function def authenticated?(user, unencrypted_password) return false unless user

    BCrypt::Password.new(user.password_digest) == unencrypted_password end end @paulfioravanti 37
  38. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.authenticated?(user, params[:password]) sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 38
  39. class SessionsController < ApplicationController def create user = User.find_by(email: params[:email])

    if UserAuthenticator.authenticated?(user, params[:password]) sign_in user redirect_to dashboard_path else flash[:alert] = "Login failed." render "new" end end end @paulfioravanti 39
  40. Do you REALLY need that OBJECT? @paulfioravanti 40

  41. if not, go module @paulfioravanti 41

  42. Thanks! @paulfioravanti @paulfioravanti 42