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

Hanami: because sometimes, you need to re-invent the wheel

Hanami: because sometimes, you need to re-invent the wheel

Hanami is a modern web framework for Ruby. It’s a full-featued MVC framework with asset integration. What could it possibly have to offer over Rails? As it turns out, quite a bit: a lightweight framework, OOP, plain old Ruby and, above all, simplicity. Sometimes it is worth it to re-invent the wheel.

Presented at Utrecht.rb.

Arjan van der Gaag

May 02, 2016
Tweet

More Decks by Arjan van der Gaag

Other Decks in Programming

Transcript

  1. View Slide

  2. What would you like to complain about?
    [ ] Too much magic
    [ ] Too much boilerplate
    source: @phillip_webb

    View Slide

  3. What would you like to complain about?
    [ ✔ ] Too much magic
    [ ] Too much boilerplate
    source: @phillip_webb

    View Slide

  4. ARJAN VAN DER GAAG (@AVDGAAG)
    HANAMI
    …because sometimes, you need to

    re-invent the wheel

    View Slide

  5. ARJAN VAN DER GAAG
    arjanvandergaag.nl • @avdgaag • brightin

    View Slide

  6. “Hanami is a Ruby MVC web framework
    comprised of many micro-libraries. It
    has a simple, stable API, a minimal DSL,
    and prioritises the use of plain objects
    over magical, over-complicated classes
    with too much responsibility.”

    View Slide

  7. “The natural repercussion of using
    simple objects with clear responsibilities

    is more boilerplate code.”

    View Slide

  8. ARJAN VAN DER GAAG (@AVDGAAG)
    CONTROLLER

    View Slide

  9. ARJAN VAN DER GAAG (@AVDGAAG)
    class Create
    include Web::Action
    def call(params)
    # book = ...
    redirect_to routes.book_path(book.id)
    end
    end

    View Slide

  10. ARJAN VAN DER GAAG (@AVDGAAG)
    class Create
    include Web::Action
    params do
    param :book do
    param :pages, type: Integer, size: 0..9999
    param :title, presence: true
    end
    end
    def call(params)
    if params.valid?
    # ...
    end
    end
    end

    View Slide

  11. ARJAN VAN DER GAAG (@AVDGAAG)
    MINIMAL INTERFACES

    View Slide

  12. ARJAN VAN DER GAAG (@AVDGAAG)
    class Show
    include Web::Action
    expose :book
    def call(params)
    @book = BookRepository.find(params[:id])
    end
    end

    View Slide

  13. ARJAN VAN DER GAAG (@AVDGAAG)
    RSpec.describe Show do
    it 'is successful' do
    response = Show.new.call('id' => '1')
    expect(response[0]).to eql(200)
    end
    end

    View Slide

  14. ARJAN VAN DER GAAG (@AVDGAAG)
    class Show
    include Web::Action
    expose :book
    def initialize(repository: BookRepository)
    @repository = repository
    end
    def call(params)
    @book = @repository.find(params[:id])
    end
    end

    View Slide

  15. ARJAN VAN DER GAAG (@AVDGAAG)
    RSpec.describe Show do
    it 'exposes the book found in the repository' do
    book = Book.new
    action = Show.new(repository: double(find: book))
    action.call('id' => '1')
    expect(action.exposures[:book]).to be(book)
    end
    end

    View Slide

  16. ARJAN VAN DER GAAG (@AVDGAAG)
    VIEW

    View Slide

  17. ARJAN VAN DER GAAG (@AVDGAAG)
    class ApplicationController < ActionController::Base
    helper :all
    end

    View Slide

  18. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Views::Books
    class Index
    include Web::View
    end
    end

    View Slide

  19. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Views::Books
    class Index
    include Web::View
    def render
    'hello, world'
    end
    end
    end

    View Slide

  20. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Views::Books
    class Index
    include Web::View
    include MyHelper
    end
    end

    View Slide

  21. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Views::Books
    class Index
    include Web::View
    def books
    locals[:books]
    end
    end
    end

    View Slide

  22. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Views::Books
    class Index
    include Web::View
    def books
    locals[:books].map do |book|
    Web::Presenters::BookPresenter.new(book)
    end
    end
    end
    end

    View Slide

  23. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Presenters
    class BookPresenter
    include Hanami::Presenter
    def title
    super.upcase
    end
    end
    end

    View Slide

  24. ARJAN VAN DER GAAG (@AVDGAAG)
    module Web::Presenters
    class BookPresenter
    include Hanami::Presenter
    def title
    super.upcase
    end
    end
    end
    book = Book.new(title: 'Pride & Prejudice')
    presenter = Web::Presenters::BookPresenter.new(book)
    presenter.title # => "PRIDE &AMP; PREJUDICE"

    View Slide

  25. ARJAN VAN DER GAAG (@AVDGAAG)
    MODEL

    View Slide

  26. ARJAN VAN DER GAAG (@AVDGAAG)
    class Book
    include Hanami::Entity
    attributes :title, :author, :pages
    end
    Book.new(title: '1984')
    # => ## @pages=nil>

    View Slide

  27. ARJAN VAN DER GAAG (@AVDGAAG)
    class BookRepository
    include Hanami::Repository
    end
    BookRepository.find(1)
    # => ## Orwell" @pages=1234>
    BookRepository.persist(Book.new(title: '1984'))
    # => ## @pages=nil>

    View Slide

  28. ARJAN VAN DER GAAG (@AVDGAAG)
    class AccountRepository
    include Hanami::Repository
    def self.find_by_username(username)
    query do
    where(username: username)
    end.first
    end
    end

    View Slide

  29. ARJAN VAN DER GAAG (@AVDGAAG)
    MONOLITH FIRST

    View Slide

  30. LIB
    APPS/WEB

    View Slide

  31. LIB
    APPS/WEB APPS/API

    View Slide

  32. LIB
    APPS/WEB APPS/ADMIN
    APPS/API

    View Slide

  33. ARJAN VAN DER GAAG (@AVDGAAG)
    WASTE OF EFFORT TO RE-
    CREATE LOTS OF MOSTLY
    THE SAME TOOLS?

    View Slide

  34. ARJAN VAN DER GAAG (@AVDGAAG)
    SOMETIMES, YOU NEED TO

    RE-INVENT THE WHEEL

    View Slide

  35. “With large, ongoing software projects, a
    lot of the features that help with simple
    demo apps become irrelevant. Or worse,
    they become disadvantages and
    bottlenecks, and sometimes downright
    obstacles to any further development.”
    Filip Hracek, The ‘Hello World’ Fallacy

    View Slide

  36. ARJAN VAN DER GAAG (@AVDGAAG)
    SIMPLICITY > CONVENIENCE

    View Slide

  37. ARJAN VAN DER GAAG (@AVDGAAG)
    YOU’RE WRITING RUBY

    View Slide

  38. What would you like to complain about?
    [ ✔ ] Too much magic
    [ ] Too much boilerplate
    source: @phillip_webb

    View Slide

  39. ARJAN VAN DER GAAG (@AVDGAAG)
    SEE HANAMIRB.ORG

    View Slide

  40. ARJAN VAN DER GAAG (@AVDGAAG)
    EMACS INTEGRATION
    https://github.com/avdgaag/projectile-hanami

    View Slide

  41. ARJAN VAN DER GAAG
    arjanvandergaag.nl • @avdgaag • brightin

    View Slide