{"id":28357574,"url":"https://github.com/hanami/helpers","last_synced_at":"2025-07-04T08:05:34.197Z","repository":{"id":16983851,"uuid":"19746688","full_name":"hanami/helpers","owner":"hanami","description":"View helpers for Ruby applications","archived":false,"fork":false,"pushed_at":"2024-11-06T13:00:22.000Z","size":683,"stargazers_count":77,"open_issues_count":2,"forks_count":50,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-06-10T23:33:59.557Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://hanamirb.org","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hanami.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"hanami"}},"created_at":"2014-05-13T16:26:00.000Z","updated_at":"2024-12-10T10:08:22.000Z","dependencies_parsed_at":"2023-11-23T06:38:20.199Z","dependency_job_id":"d548669e-98a1-4e5a-a0db-9c01c79b874b","html_url":"https://github.com/hanami/helpers","commit_stats":{"total_commits":308,"total_committers":43,"mean_commits":7.162790697674419,"dds":0.3344155844155844,"last_synced_commit":"b9e8cf0fdc4599bd89cd374f43d56644c9e4054b"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/hanami/helpers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fhelpers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fhelpers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fhelpers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fhelpers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hanami","download_url":"https://codeload.github.com/hanami/helpers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hanami%2Fhelpers/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260787095,"owners_count":23063050,"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":[],"created_at":"2025-05-28T08:06:20.462Z","updated_at":"2025-06-22T03:31:37.799Z","avatar_url":"https://github.com/hanami.png","language":"Ruby","funding_links":["https://github.com/sponsors/hanami"],"categories":[],"sub_categories":[],"readme":"# Hanami::Helpers\n\nView helpers for Ruby applications\n\n## Status\n\n[![Gem Version](https://badge.fury.io/rb/hanami-helpers.svg)](https://badge.fury.io/rb/hanami-helpers)\n[![CI](https://github.com/hanami/helpers/workflows/ci/badge.svg?branch=main)](https://github.com/hanami/helpers/actions?query=workflow%3Aci+branch%3Amain)\n[![Test Coverage](https://codecov.io/gh/hanami/helpers/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/helpers)\n[![Depfu](https://badges.depfu.com/badges/7b30c5d2a2a78954e2ad86e5c7230c23/overview.svg)](https://depfu.com/github/hanami/helpers?project=Bundler)\n[![Inline Docs](http://inch-ci.org/github/hanami/helpers.svg)](http://inch-ci.org/github/hanami/helpers)\n\n## Contact\n\n* Home page: http://hanamirb.org\n* Mailing List: http://hanamirb.org/mailing-list\n* API Doc: http://rdoc.info/gems/hanami-helpers\n* Bugs/Issues: https://github.com/hanami/helpers/issues\n* Support: http://stackoverflow.com/questions/tagged/hanami\n* Chat: https//chat.hanamirb.org\n\n## Rubies\n\n__Hanami::Helpers__ supports Ruby (MRI) 3.0+\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'hanami-helpers'\n```\n\nAnd then execute:\n\n```shell\n$ bundle\n```\n\nOr install it yourself as:\n\n```shell\n$ gem install hanami-helpers\n```\n\n## Usage\n\n`Hanami::Helpers` offers a set of utilities to enrich web views.\n\n### HTML helper\n\nHTML5 markup generator (`#html`).\n\nView:\n\n```ruby\nmodule Users\n  class Show\n    include Hanami::Helpers\n\n    def sidebar\n      html.aside(id: 'sidebar') do\n        p \"Languages\", class: 'title'\n\n        ul do\n          li \"Italian\"\n          li \"English\"\n        end\n      end\n    end\n  end\nend\n```\n\nTemplate:\n\n```erb\n\u003c%= sidebar %\u003e\n```\n\nOutput:\n\n```html\n\u003caside id=\"sidebar\"\u003e\n  \u003cp class=\"title\"\u003eLanguages\u003c/p\u003e\n\n  \u003cul\u003e\n    \u003cli\u003eItalian\u003c/li\u003e\n    \u003cli\u003eEnglish\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/aside\u003e\n```\n\n### Form Helper\n\nForm generator for HTML5 (`#form_for`)\n\n#### Template Usage\n\nTemplate:\n\n```erb\n\u003c%=\n  form_for :book, routes.books_path do\n    text_field :title\n\n    submit 'Create'\n  end\n%\u003e\n```\n\nOutput:\n\n```html\n\u003cform action=\"/books\" method=\"POST\" accept-charset=\"utf-8\" id=\"book-form\"\u003e\n  \u003cinput type=\"text\" name=\"book[title]\" id=\"book-id\" value=\"\"\u003e\n  \u003cbutton type=\"submit\"\u003eCreate\u003c/button\u003e\n\u003c/form\u003e\n```\n\n#### View Usage\n\nView:\n\n```ruby\nmodule Books\n  class New\n    include Hanami::Helpers\n\n    def form\n      form_for :book, routes.books_path do\n        text_field :title\n\n        submit 'Create'\n      end\n    end\n  end\nend\n```\n\nTemplate:\n\n```erb\n\u003c%= form %\u003e\n```\n\nOutput:\n\n```html\n\u003cform action=\"/books\" method=\"POST\" accept-charset=\"utf-8\" id=\"book-form\"\u003e\n  \u003cinput type=\"text\" name=\"book[title]\" id=\"book-id\" value=\"\"\u003e\n  \u003cbutton type=\"submit\"\u003eCreate\u003c/button\u003e\n\u003c/form\u003e\n```\n\n#### Reuse Code\n\nViews:\n\n```ruby\nmodule Books\n  class New\n    include Hanami::Helpers\n\n    def form\n      Form.new(:book, routes.books_path)\n    end\n\n    def submit_label\n      'Create'\n    end\n  end\n\n  class Edit\n    include Hanami::Helpers\n\n    def form\n      Form.new(:book, routes.book_path(id: book.id), {book: book}, {method: :patch})\n    end\n\n    def submit_label\n      'Update'\n    end\n  end\nend\n```\n\nTemplates:\n\n```erb\n# books/new.html.erb\n\u003c%= render partial: 'books/form' %\u003e\n```\n\n```erb\n# books/edit.html.erb\n\u003c%= render partial: 'books/form' %\u003e\n```\n\n```erb\n# books/_form.html.erb\n\u003c%=\n  form_for form, class: 'form-horizontal' do\n    text_field :title\n\n    submit submit_label\n  end\n%\u003e\n```\n\nOutput for new:\n\n```html\n\u003cform action=\"/books\" method=\"POST\" accept-charset=\"utf-8\" id=\"book-form\"\u003e\n  \u003cinput type=\"text\" name=\"book[title]\" id=\"book-id\" value=\"\"\u003e\n  \u003cbutton type=\"submit\"\u003eCreate\u003c/button\u003e\n\u003c/form\u003e\n```\n\nOutput for edit:\n\n```html\n\u003cform action=\"/books/23\" method=\"POST\" accept-charset=\"utf-8\" id=\"book-form\"\u003e\n  \u003cinput type=\"hidden\" name=\"_method\" value=\"PATCH\"\u003e\n  \u003cinput type=\"text\" name=\"book[title]\" id=\"book-id\" value=\"TDD\"\u003e\n  \u003cbutton type=\"submit\"\u003eUpdate\u003c/button\u003e\n\u003c/form\u003e\n```\n\n### Escape helper\n\nHTML (`#h`), HTML attribute (`#ha`) and URL (`#hu`) escape helpers.\n\nView:\n\n```ruby\nmodule Users\n  class Show\n    include Hanami::Helpers\n\n    def home_page_link\n      %(\u003ca href=\"#{ hu(user.home_page_url) }\" title=\"#{ ha(user.name} }'s website\"\u003e#{ h(user.website_name) }\u003c/a\u003e)\n    end\n\n    def code_snippet\n      raw user.code_snippet\n    end\n  end\nend\n```\n\nTemplate:\n\n```erb\n\u003c%= home_page_link %\u003e\n\u003c%= code_snippet %\u003e\n```\n\nOutput:\n\n```html\n\u003ca href=\"https://example.org\" title=\"Maria's website\"\u003eMy Blog\u003c/a\u003e\n\u003ccode\u003eputs \"Hello, World!\"\u003c/code\u003e\n```\n\n### Routing Helper\n\nHanami and Hanami::Router integration (`#routes`).\n\nView:\n\n```ruby\nmodule Home\n  class Index\n    include Hanami::Helpers\n\n    def link_to_home\n      %(\u003ca href=\"#{ routes.home_path }\"\u003eHome\u003c/a\u003e)\n    end\n  end\nend\n```\n\nTemplate:\n\n```erb\n\u003c%= link_to_home %\u003e\n```\n\nOutput:\n\n```html\n\u003ca href=\"/\"\u003eHome\u003c/a\u003e\n```\n\n### Number Formatting Helper\n\nFormat numbers (`#format_number`).\n\nView:\n\n```ruby\nmodule Home\n  class Index\n    include Hanami::Helpers\n\n    def visitors_count\n      format_number '1000'\n    end\n  end\nend\n```\n\nTemplate:\n\n```erb\n\u003cp\u003e\u003c%= visitors_count %\u003e\u003c/p\u003e\n```\n\nOutput:\n\n```html\n\u003cp\u003e1,000\u003c/p\u003e\n```\n\n## Philosophy\n\nAll the Hanami helpers are modules to include.\n\nMost of the time they inject **private** methods.\nThis restriction prevents helper methods to be used on the outside (eg. in a template).\n\nWe want to encourage developers to use **meaningful** and **simple APIs** in their templates.\n\n### Bad style example\n\n```ruby\nmodule Users\n  class Show\n    include Hanami::Helpers\n  end\nend\n```\n\n```erb\n\u003c%= format_number user.followers_count %\u003e\n```\n\nThis style increases the complexity of the template and it makes testing hard.\n\n### Good style example\n\n```ruby\nmodule Users\n  class Show\n    include Hanami::Helpers\n\n    def followers_count\n      format_number user.followers_count\n    end\n  end\nend\n```\n\n```erb\n\u003c%= followers_count %\u003e\n```\n\nThis simplifies the markup.\nIn order to test the value that will be printed becomes easier: `Users::Show#followers_count`.\n\n## Versioning\n\n__Hanami::Helpers__ uses [Semantic Versioning 2.0.0](http://semver.org)\n\n## Contributing\n\n1. Fork it ( https://github.com/hanami/helpers/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Copyright\n\nCopyright © 2014-2021 Luca Guidi – Released under MIT License\n\nThis project was formerly known as Lotus (`lotus-helpers`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhanami%2Fhelpers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhanami%2Fhelpers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhanami%2Fhelpers/lists"}