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

Beyond the Rails Way - Clean Architecture

Beyond the Rails Way - Clean Architecture

About architecture to make skinny models and skinny controllers

Patricia

March 10, 2018
Tweet

More Decks by Patricia

Other Decks in Programming

Transcript

  1. 4

  2. 5

  3. 6

  4. 8 class UserGroupsController def create # Assume @group is loaded

    from a before_action method if !current_user.is_old_enough_to_join_group?(@group) flash[:alert] = I18n.t('admin.trestle.flash.too_young') elsif current_user.is_group_limit_reached? flash[:alert] = I18n.t('admin.trestle.flash.too_many_groups') else user_group = UserGroup.new(user_id: current_user.id, group_id: @group.id) if user_group.save flash[:notice] = I18n.t('admin.trestle.flash.successfully_joined_group') else flash[:alert] = I18n.t('admin.trestle.flash.could_not_join_group') end end redirect_to group_path(@group) end end
  5. 9 class User < ApplicationRecord MAX_NUMBER_OF_GROUPS = 10 has_many :user_groups

    has_many :groups, through: :user_groups def is_old_enough_to_join_group?(group) age > group.minimum_age end def is_group_limit_reached? groups.count >= MAX_NUMBER_OF_GROUPS end end
  6. © 2017 InspiraSign - Template All rights reserved 10 “But

    what if there was a way to have both skinny models AND skinny controllers?!”
  7. 19 CreateUser Name Format Name Minimum 2 characters maximum 50

    characters. Email Must have valid format as in the example: [email protected]. Password At least 6 characters, maximum 15 characters. Password Confirmation Must be filled in identically to the password. Main Flow - Set of steps Exception Flow - What happened when things do not go well
  8. 28

  9. 29

  10. 30

  11. 31

  12. 33

  13. 34

  14. 36

  15. 39

  16. 40

  17. 42

  18. 43

  19. 44

  20. 45

  21. 47

  22. 48

  23. 49

  24. 50

  25. 52 class UserGroupsController def create result = AddUserToGroup.call group: @group,

    user: current_user message = result.message if result.success? flash[:notice] = message else flash[:alert] = message end redirect_to group_path(@group) end end
  26. 53 class AddUserToGroup include Interactor def call fail! message: I18n.t('admin.trestle.flash.too_young')

    unless is_old_enough_to_join_group? fail! message: I18n.t('admin.trestle.flash.too_many_groups') unless group_limit_reached? if create_new_user_group context[:message] = I18n.t('admin.trestle.flash.successfully_joined_group') else fail! message: I18n.t('admin.trestle.flash.could_not_join_group') end end private def group_limit_reached? context[:user].groups.count >= User::MAX_NUMBER_OF_GROUPS end def is_old_enough_to_join_group? context[:user].age >= context[:group].minimum_age end def create_new_user_group context[:user_group] = UserGroup.new(user_id: context[:user].id, group_id: context[:group].id) context[:user_group].save end end
  27. result = AddUserToGroup.call group: @group, user: current_user puts result.user_group =>

    #<UserGroup id: 1, user_id: 1, group_id: 1> puts result.message => You have successfully joined the Example group!