{"id":26237306,"url":"https://github.com/yuri-karpovich/api_hanami","last_synced_at":"2026-04-29T00:02:11.524Z","repository":{"id":193119382,"uuid":"303435849","full_name":"yuri-karpovich/api_hanami","owner":"yuri-karpovich","description":"JSON API based on Hanami::API","archived":false,"fork":false,"pushed_at":"2021-09-28T13:05:20.000Z","size":23,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-09-06T22:09:14.645Z","etag":null,"topics":["hanami","json-api"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yuri-karpovich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-10-12T15:33:58.000Z","updated_at":"2023-09-06T22:09:19.562Z","dependencies_parsed_at":null,"dependency_job_id":"caf998f3-703b-4d13-8896-4f77f8d24514","html_url":"https://github.com/yuri-karpovich/api_hanami","commit_stats":null,"previous_names":["yuri-karpovich/api_hanami"],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuri-karpovich%2Fapi_hanami","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuri-karpovich%2Fapi_hanami/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuri-karpovich%2Fapi_hanami/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuri-karpovich%2Fapi_hanami/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yuri-karpovich","download_url":"https://codeload.github.com/yuri-karpovich/api_hanami/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243341406,"owners_count":20275866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hanami","json-api"],"created_at":"2025-03-13T04:31:30.233Z","updated_at":"2026-04-29T00:02:11.432Z","avatar_url":"https://github.com/yuri-karpovich.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# API app example\n## Objectives\nThis is am example app. My goal was to create a concurrent? small and fast JSON API app. Requirements:\n- API calls should be faster than 100ms after data seeding (see [Data Seed](#data-seed))\n- DB = PostgreSQL\n- It's allowed to use any gems and ORMs\n- Don't use RoR\n- It's allowed to use DB capabilities to speed up responses\n- Code should be clean, e.g. don't use generators\n- Specs are required\n \n### Endpoints\nThere are 3 models - `User` (fields: login), `Post` (fields: title, content, author ip address) and `Rating` (fields: value(1..5)). `Rating` belongs to `Post`, `Post` belongs to `User`.\n\n#### Create Post\nParams: title, content, author ip, author login\n\nBehaviour: Create post. Create user if not exists\n\nResponse: 200 - created post attributes, 422 - in case of error  \n\n\u003e `POST http://127.0.0.1:9292/api/v1/posts?login=\u003cuser\u003e\u0026title=\u003ctitle\u003e\u0026ip=\u003cip\u003e\u0026content=\u003ccontent\u003e`\n\n#### Rate Post\nParams: post id, rating\n\nBehaviour: post has many ratings\n\u003e Important: action should work correctly on a concurrent update of the same post\n\nResponse: 200 - average post rating, 422 - in case of error\n\n\u003e `PUT http://localhost:9292/api/v1/posts/\u003cpost_id\u003e?rating=\u003crating\u003e`\n\n \n#### Top Posts by Rating\nParams: number of posts to return (optional)\n\nBehaviour: Collection of posts with their attributes should be returned\n\nResponse: 200 - N posts with their attributes  \n\n\u003e `GET http://localhost:9292/api/v1/posts?count=\u003ccount\u003e`\n\n#### List of IP addresses \nParams: user logins\n\nBehaviour: Get all user's IP addresses from his posts. It should be possible to get some users simultaneously\n\nResponse: 200 - users and their IP addresses\n\n\u003e `GET http://localhost:9292/api/v1/users/ip?logins=\u003clogin1\u003e%20\u003clogin2\u003e`\n\n### Data Seed\n`db/seed.db` file should be created. Import data to the DB using JSON API - start server and use API endpoints.\n\nDB should be filled with:\n- 100 uniq users\n- 50 uniq IP addresses\n- 200k posts\n \n \n## Solution\nThis was my first non-Rails API app so I decided to create an app from scratch using something extremely light and fast. \nI should have used `Roda` or `Hanami` but my decision was to try something experimental :) \nSo my choice for this test task is [`Hanami::API`](https://github.com/hanami/api). \n\n\u003e Actually I've benchmarked requests/second for `Hanami::API`, `Hanami::Router` and `Roda`  on ruby 2.7.0 and the winner was `Hanami::Router`. `Roda` was very close to it. \n\u003e Anyway I would prefer `Hanami` or `Roda` for production.\n\n## Quick start\nInstall gems:\n    \n    bundle install\n    \nStart Postgres server:\n    \n    docker-compose up -d\n\nPrepare database:\n    \n    bundle exec rake db:create RACK_ENV=production\n    bundle exec rake db:migrate RACK_ENV=production\n    \nStart server:\n\n    bundle exec bin/rackup -q -E production -o 127.0.0.1\n    \nStart data seed:\n\n    bundle exec rake db:seed RACK_ENV=production\n    \n## Run tests\n\n    bundle exec rake db:create RACK_ENV=test\n    bundle exec rake db:migrate RACK_ENV=test\n    bundle exec rspec\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuri-karpovich%2Fapi_hanami","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuri-karpovich%2Fapi_hanami","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuri-karpovich%2Fapi_hanami/lists"}