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

One Year with Hanami

One Year with Hanami

Have you ever heard of Hanami? Have you considered using it for your new project, but you don’t know what to expect? This talk will clear your doubts - my team has been using Hanami for more than a year and I’m going to share our experience with the framework.

Grzegorz Witek

August 04, 2018
Tweet

More Decks by Grzegorz Witek

Other Decks in Technology

Transcript

  1. ONE YEAR WITH HANAMI @ A R N V A

    L D , P U N E , 2 0 1 8
  2. 5 WHAT IS HANAMI • long-standing Japanese tradition of welcoming

    spring • web framework written in Ruby image source: https://hanamirb.org
  3. 6 BRIEF INTRODUCTION Hanami is a full-featured web framework Hanami

    is modular Hanami is lightweight Hanami promotes good practices
  4. 8 OUR TIMELINE June 2017 R U N N I

    N G P R O D U C T I O N January 2017 F I R S T C O M M I T July 2017 2 N D A P P L I C A T I O N March 2018 H A N A M I 1 . 1
  5. 12 Each action is a separate class with call method.

    Testing controller is as simple as calling Action.new.call(params) one controller action = one class
  6. 13 Each action is a separate class with call method.

    Testing controller is as simple as calling Action.new.call(params) one controller action = one class /apps
 /admin
 /config
 /controllers
 /orders
 /index.rb
 /create.rb
 /customers
 /index.rb
 /create.rb
  7. 14 controller actions are magical Hanami Action module wraps around

    your class’ call method. The value you return from call is ignored, instead you must modify class’ attributes
  8. 15 controller actions are magical Hanami Action module wraps around

    your class’ call method. The value you return from call is ignored, instead you must modify class’ attributes class Index
 include MyApp::Action
 
 def call(params)
 “this is action”
 end
 end Index.new.call({}) [200,
 … a lot of headers,
 []]
  9. 16 controller actions are magical Hanami Action module wraps around

    your class’ call method. The value you return from call is ignored, instead you must modify class’ attributes class Index
 include MyApp::Action
 
 def call(params)
 status 200, “this is action”
 end
 end Index.new.call({}) [200,
 … a lot of headers,
 [“this is action”]]
  10. 17 controller actions are magical Hanami Action module wraps around

    your class’ call method. The value you return from call is ignored, instead you must modify class’ attributes class Index
 include MyApp::Action
 
 def call(params)
 self.body = “this is action”
 self.status = 403
 end
 end Index.new.call({}) [403,
 … a lot of headers,
 [“this is action”]]
  11. 18 Views in Hanami are objects that encapsulate logic that

    is used in the template Templates are representation of the data returned to the user views != templates
  12. 19 Views in Hanami are objects that encapsulate logic that

    is used in the template Templates are representation of the data returned to the user views != templates # view
 class Index
 include MyApp::View
 
 def users_age
 Time.now.year - user.year_of_birth
 end
 end # template
 <div class=“user”>
 <span class=“age”>
 <%= users_age %>
 </span>
 </div>
  13. 20 Views in Hanami are objects that encapsulate logic that

    is used in the template Templates are representation of the data returned to the user built-in helpers are private
  14. 21 Views in Hanami are objects that encapsulate logic that

    is used in the template Templates are representation of the data returned to the user built-in helpers are private # view
 class Index
 include MyApp::View
 
 def total_cost
 format_number(cost)
 end
 end # template
 <div class=“order”>
 <span class=“cost”>
 <%= total_cost %>
 </span>
 </div>
  15. 24 Repository pattern separates the entities (individual objects) from the

    repository (a collection of objects) It means that queries will be in different class than individual object methods repository pattern
  16. 25 Repository pattern separates the entities (individual objects) from the

    repository (a collection of objects) It means that queries will be in different class than individual object methods repository pattern class OrderRepository < Hanami::Repository
 associations do
 belongs_to :customer
 end 
 
 def future
 orders.where { delivered_at.is(nil() }
 end
 end class Order < Hanami::Entity
 def description
 “#{product.name} #{total_cost}”
 end
 end
  17. 26 3 layers around the database Hanami model library relies

    on Rom-rb which relies on Sequel Sometimes we can’t achieve what we want in Hanami model and we need to go down to another layer of abstraction
  18. 27 Validations are a mixin that can be included anywhere

    - they perfectly fit controllers or service objects validations separated from entities
  19. 28 Validations are a mixin that can be included anywhere

    - they perfectly fit controllers or service objects validations separated from entities class Create
 include MyApp::Action
 
 params do
 required(:title).filled(:str?)
 required(:amount).filled(:int?)
 end
 end
 
 class CreateOrder
 include Hanami::Validations
 
 validations do
 required(:title).filled(:str?)
 end
 end
  20. 31 Starting a new Hanami project creates /apps directory with

    one application there Having multiple applications in one project is not a special case, but a standard mountable apps are first class citizens
  21. 32 Starting a new Hanami project creates /apps directory with

    one application there Having multiple applications in one project is not a special case, but a standard mountable apps are first class citizens /apps
 /admin
 /config
 /controllers
 /orders
 /customers
 /web
 /config
 /controllers
 /api
 /config
 /controllers
  22. 33 not that modular Hanami libraries are independent of each

    other. However, Hanami application gem relies on most of the gems. Even if you don’t need mailers - you’ll have them in Gemfile.lock
  23. 34 Hanami promotes good engineering practices: separating layers of the

    application, writing code that’s easy to test, making most of the code private emphasis on architecture
  24. 37 Hanami utils do not monkey patch standard Ruby classes.

    Instead they add their own classes on top of the standard ones no monkey patching
  25. 38 Hanami utils gem provides a simple class that helps

    implementing service objects in a consistent manner interactors
  26. 39 magic in interactors Similarly to controller actions, the result

    is based on instance variables, not on the value you return from your call function
  27. 40 magic in interactors class CreateUser
 include Hanami::Interactor
 
 expose

    :user
 
 def call(params)
 @user = User.new(params)
 end
 end
 
 creator = CreateUser.new
 result = creator.call(params)
 result.user Similarly to controller actions, the result is based on instance variables, not on the value you return from your call function
  28. 41 small ecosystem Hanami is still considered a new framework,

    despite being more than 3 years old. There’s still few resources and libraries that help develop Hanami applications
  29. 43 YOU CAN USE HANAMI FOR most web applications even

    non-web applications (model, validations, mailers)
  30. 44 YOU MIGHT RECONSIDER IF YOU BUILD application that needs

    a lot of external libraries project with a lot of complex queries simple CRUD applications
  31. ONE YEAR WITH HANAMI @ A R N V A

    L D , P U N E , 2 0 1 8 wonderful