Where communities thrive

  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
  • 08:26
    Mukesh23singh starred hanami/view
  • Jan 22 20:22
    depfu[bot] labeled #613
  • Jan 22 20:22
    depfu[bot] opened #613
  • Jan 22 20:22

    depfu[bot] on update

    Update dry-types to version 1.5… (compare)

  • Jan 22 20:17
    depfu[bot] labeled #169
  • Jan 22 20:17
    depfu[bot] opened #169
  • Jan 22 20:17

    depfu[bot] on update

    Update dry-struct to version 1.… (compare)

  • Jan 22 17:59
    pzgz starred hanami/router
  • Jan 22 14:45
    bozhenaboichuk starred hanami/hanami
  • Jan 21 21:44
    jodosha commented #211
  • Jan 21 21:44
    jodosha milestoned #211
  • Jan 21 21:44
    jodosha labeled #211
  • Jan 21 21:43
    jodosha review_requested #211
  • Jan 21 21:43
    jodosha assigned #211
  • Jan 21 16:06
    geordidearns starred hanami/model
  • Jan 21 13:45
    graudeejs review_requested #210
  • Jan 21 12:50

    depfu[bot] on check


  • Jan 21 11:48

    depfu[bot] on check

    Pin concurrent-ruby to version … (compare)

  • Jan 21 08:56
    vanyavasylyshyn starred hanami/hanami
  • Jan 19 18:44
    joshfng starred hanami/router
Yuriy Tsemashko
Hi there!
Kuchaev Ilya
Screenshot 2020-11-02 at 13.50.14.png
The project is somehow alive, but it's not very optimistic )
One year from the latest release!
release per year is almost non maintained.
Actually the team is working hard on v2

Actually the team is working hard on v2


Yuriy Tsemashko

Hi. Please help me to understand how to organize my architecture better. Imagine I have a feature that requires to touch several repositories, models and so on. For example, I have a function CreateTransaction(from_account, to_account, amount) which does the next things: create debit Transaction on to_account, create credit Transaction of from_account. This operation has some restriction: the amount cannot be 0 or negative, the accounts should be different and so on. So, I need some validations.

The validations are described only in scope of actions (I like having data validations dependent on ,let's say, the protocol level). But of course the CreateTransaction logic must not be implemnted in an action as it might be used from several protocols: from web gui, from json API, from protobuf api and so on

what would be is the right choice of how to implement my CreateTransaction?
as Hanami uses dry-rb a lot, I'm looking at dry-rb gem. I found dry-struct. If I include some validations into my class which extends Dry::Struct, i can build pretty nice business function

But of course I can create just my own class with an instance method "call" and put some if conditions:

class CreateTransactionOperation
def initialize(from, to, amount)

def call
return :error_1 if amount <= 0
return :error_2 if from == to

bla bla bla
bla bla

and it will work obviously.

Yuriy Tsemashko
but is there a ready-to-use solution?
Brett Dudo
Hello, folks! I've been working with hanami-api, and it's getting large. I'd like to move to controllers. Is that pretty straight forward? Anything to add to the initializers to auto require all the controller files?
to clarify, I'd like to do api + controllers
this example in the api readme is the only thing that touches on it get "/users", to: Actions::V1::Users::Index.new
Brett Dudo
and where should I call Hanami::Controller.load!?
Brett Dudo
tinkering with folder structure
Sebastjan Hribar
@azzz we have a similar use case, where we had to implement touching multiple repos, doing some checks, catching exceptions and so forth. We now have all business logic for this in an interactor. For example, a request comes in through ajax to an action that calls this interactor. Have a look here to see how Hanami implements them. I find interactors to be a great way to organize such code.

Actually the team is working hard on v2

Sure! But why it's like invisible for the others?
30 Jan 2019

Yuriy Tsemashko
@sebastjan-hribar thanks, I didn't find the interactors before.
Brett Dudo
when using "actions" with hanami-api, the self.body= setter doesn't seem to work. This works. Feels like I'm not doing something correctly, though
also, I couldn't get validations to work. is the dot syntax correct, or the block syntax? there's competing docs
Brett Dudo
if anyone finds this... I ended up just keeping things in config.ru, and it's pretty clean with the serializers
kelvin romero
Hello everyone. Any of you happen to use some health check gem for Hanami?
Sebastjan Hribar
I've recently asked about getting the controller for each action. I need to get controller name, like Task. I couldn't find any other way but to pars Web::Controllers::Task::New for example. Is there a better way?
by action you mean route ?
Sebastjan Hribar
I mean I currently deal with what is listed under Action if I run hanami routes: Web::Controllers::Users::Index. In this particular case I'd grab Usersand use singular form and Index.

HI, I noticed a problem during migration execution, basically I've got migration like this:

Hanami::Model.migration do
  change do
    create_table :users do
      primary_key :id

      column :email,              String, null: false
      column :encrypted_password, String
      column :phone_number,       String

      column :created_at, DateTime, null: false
      column :updated_at, DateTime, null: false

When I run it, it shows me following snippet

[hanami] [ERROR] PG::UndefinedTable: ERROR:  relation "schema_migrations" does not exist
LINE 1: SELECT NULL AS "nil" FROM "schema_migrations" LIMIT 1
                                  ^: SELECT NULL AS "nil" FROM "schema_migrations" LIMIT 1
[hanami] [INFO] (0.042149s) CREATE TABLE "schema_migrations" ("filename" text PRIMARY KEY)
[hanami] [ERROR] PG::UndefinedTable: ERROR:  relation "schema_info" does not exist
LINE 1: SELECT NULL AS "nil" FROM "schema_info" LIMIT 1
                                  ^: SELECT NULL AS "nil" FROM "schema_info" LIMIT 1

But, when I add null: true to encrypted_password and phone_number everything works smoothly. Both in hanami guide and in rom-sql I see this is an optional attribute. Anyone has idea what can cause this issue?

The 2 problem seem pretty unrelated, so I'd guess there is a typo somewhere
do you have other migration files ?
are you sure there isn't an invisble char (like unbreakble space) that messes up with the migration content ?
Kai Kuchenbecker
There isn't any actual problem in the provided log output
What's happening is that when migrations run the migrator first checks whether the required tables schema_migrations and schema_info exist, if they don't they are created.
Sadly this step is rather verbose and outputs this non-error as if it were an error... but it's how the underlying gem handles it and we cannot do much about it.

Hi, thank you @inouire_twitter and @kaikuchn for responding me. I'll verify if there is no invisible char when in the evening. Also, this is the only migration I have.

About the errors and checks - what I see is in related database schema_migrartions table is being created but no schema_info is present. Also, running hanami db prepare once again, on already migrated database, the output of execution remains the same.

Noman Ur Rehman
Are there documented problems with Hanami inside a container?
I remember everything working correctly long ago when I was using it on my local machine
But with Docker, I seem to be having a lot of boot issues
Everytime, it is something new :(
If anyone is curious about my problem I had - I should write at first what command I have used :) I used hanami db prepare (as guides described) instead of hanami db migrate.Basically, this command is for setup, but raises above errors. Running hanami db migrate did the job.
Sebastian Schürmann
hello. Just a short question: is there a hanami version of active_admin?
Sven Schwyn
@sebsonjura I've done quite some with work with AA and Rails, so although not 100% sure, I doubt there's a fork for Hanami. The coupling with Rails goes pretty deep. (Also, I wouldn't chose AA anymore for backends, we got a head start in the beginning, but ran into tons of trouble later on due to hardcoded opinions and limitations – however, your mileage may vary.)

Hello, I'm using hanami-api and hanami-controller (action) as standalone gems. Now I observe an issue and hope somebody can help me. I have a GraphQL-controller, which should use the Authorization-Header to authenticate. So in the controller I get the header-value as described in the docs:

bearer_token = request.env['HTTP_AUTHORIZATION']

this works for the first request after application-startup. If I change the header at the client application (i.e. to an invalid token). The controller gets always the token from the first request. So the header get cached. If I investigate the whole rack.env,


I get something like this:

  "rack.version"              => [
  "rack.errors"               => #<Rack::Lint::ErrorWrapper:0x000055bd2bc60b68 @error=#<IO:<STDERR>>>,
  "rack.multithread"          => true,
  "rack.multiprocess"         => false,
  "rack.run_once"             => false,
  "SCRIPT_NAME"               => "",
  "QUERY_STRING"              => "query=query%20($id:%20ID!)%20%7B%0A%20%20airport(id:%20$id)%20%7B%0A%20%20%20%20id%0A%20%20%20%20iataCode%0A%20%20%20%20name%0A%20%20%7D%0A%7D&variables=%7B%22id%22:1%7D",
  "SERVER_PROTOCOL"           => "HTTP/1.1",
  "SERVER_SOFTWARE"           => "puma 5.0.4 Spoony Bard",
  "GATEWAY_INTERFACE"         => "CGI/1.2",
  "REQUEST_METHOD"            => "GET",
  "REQUEST_PATH"              => "/graphql",
  "REQUEST_URI"               => "/graphql?query=query%20($id:%20ID!)%20%7B%0A%20%20airport(id:%20$id)%20%7B%0A%20%20%20%20id%0A%20%20%20%20iataCode%0A%20%20%20%20name%0A%20%20%7D%0A%7D&variables=%7B%22id%22:1%7D",
  "HTTP_VERSION"              => "HTTP/1.1",
  "HTTP_HOST"                 => "localhost:9292",
  "HTTP_USER_AGENT"           => "Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0",
  "HTTP_ACCEPT"               => "application/json, text/plain, */*",
  "HTTP_ACCEPT_LANGUAGE"      => "en-US,en;q=0.5",
  "HTTP_ACCEPT_ENCODING"      => "gzip, deflate",
  "HTTP_AUTHORIZATION"        => "Bearer old_token",
  "HTTP_CONNECTION"           => "keep-alive",
  "HTTP_COOKIE"               => "MicrosoftApplicationsTelemetryDeviceId=cd5cc910-fc4f-436e-8ea7-f93b17fd7093; MicrosoftApplicationsTelemetryFirstLaunchTime=2020-01-08T14:59:29.306Z",
  "puma.request_body_wait"    => 0,
  "SERVER_NAME"               => "localhost",
  "SERVER_PORT"               => "9292",
  "PATH_INFO"                 => "/graphql",
  "REMOTE_ADDR"               => "",
  "puma.socket"               => #<TCPSocket:(closed)>,
  "rack.hijack?"              => true,
  "rack.hijack"               => #<Proc:0x000055bd2bc60ff0 /home/armwur/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/rack-2.2.3/lib/rack/lint.rb:567>,
  "rack.input"                => #<Rack::Lint::InputWrapper:0x000055bd2bc60b90 @input=#<Puma::NullIO:0x000055bd2c024a88>>,
  "rack.url_scheme"           => "http",
  "rack.after_reply"          => [],
@_env={"rack.version"=>[1, 6], "rack.errors"=>#<Rack::Lint::ErrorWrapper:0x000055bd2ce5e158 @error=#<IO:<STDERR>>>, "rack.multithread"=>true, "rack.multiprocess"=>false, "rack.run_once"=>false, "SCRIPT_NAME"=>"", "HTTP_AUTHORIZATION"=>"Bearer new_token", "QUERY_STRING"=>"query=query%20($id:%20ID!)%20%7B%0A%20%20airport(id:%20$id)%20%7B%0A%20%20%20%20id%0A%20%20%20%20iataCode%0A%20%20%20%20name%0A%20%20%7D%0A%7D&variables=%7B%22id%22:1%7D", "SERVER_PROTOCOL"=>"HTTP/1.1", "SERVER_SOFTWARE"=>"puma 5.0.4 Spoony Bard", "GATEWAY_INTERFACE"=>"CGI/1.2", "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/graphql", "REQUEST_URI"=>"/graphql?query=query%20($id:%20ID!)%20%7B%0A%20%20airport(id:%20$id)%20%7B%0A%20%20%20%20id%0A%20%20%20%20iataCode%0A%20%20%20%20name%0A%20%20%7D%0A%7D&variables=%7B%22id%22:1%7D", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"localhost:9292", "HTTP_USER_AGENT"=>"Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0", "HTTP_ACCEPT"=>"application/json, text/plain, */*", "HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q=0.5", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_CONNECTION"=>"keep-alive
So the @_env of rack contains the new token. What I'm doing wrong?