BackEnd

RubyのHanamiチュートリアルをやってみた

投稿日:2017年9月13日 更新日:

はじめに

HanamiというRubyフレームワークが話題にあがっているようです。
今年のRuby Kaigi 2017でもAnton Davydov氏が発表されるようです。
Hanami – New Ruby Web Framework

今回はそんなHanamiのチュートリアルをやってみたいと思います。
公式ドキュメントはこちらになります。
HANAMI

日本語の「花見」から来ているのでしょう、TOPページは桜ですかね?

紹介

GUIDEの部分を和訳しているだけです。
(和訳はもしかすると誤りがあるかもしれませんが。。。その場合はコメントをいただけると幸いです。)

Hanamiとは?

Hanamiは、多くのマイクロライブラリーで構成された、RubyのMVCフレームワークです。
シンプルで安定したAPIと最小限のDSLを持ち、あまりにも多くの責任と魔法のように複雑なクラスを越え、プレーンなオブジェクトの使用を優先します。

明確な責任を持つ単純なオブジェクトを使用することにより、より定型的なコードになります。 Hanamiは、基本的な実装を維持しながら、余分な箇所を軽減する方法を提供します。

Hanamiを選ぶ理由

Hanamiを選ぶ理由は3つあります。

軽量

花見のコードは比較的短いです。実装に関係なく、すべてのWebアプリケーションが必要とすることのみに関心があります。
Hanamiにはいくつかのオプションモジュールが付属しており、他のライブラリも簡単に組み込むことができます。

アーキテクチャとして

あなたが「Rails Way」に反していると感じたことがあるなら、あなたは花見を良いと思うでしょう。
Hanamiはコントローラの動作をクラスベースに保ち、独立してテストしやすくしています。
また、Hanamiはユースケースオブジェクト(別名: interactors )にアプリケーション・ロジックを書くことをお勧めします。
ビューはテンプレートから分離されているため、内部のロジックを十分に包含してテストすることができます。

ちなみにHanamiはクリーンアーキテクチャに影響を受けているとのことです。

スレッドセーフ

スレッドの使用は、アプリケーションのパフォーマンスを向上させるのに最適です。
スレッドセーフなコードを書くのは難しいことではありませんし、Hanami(フレームワーク全体かその一部かに関わらず)は実行時スレッドセーフです。

チュートリアルのための準備

下記リンクのチュートリアルを実施していきます。
Getting Started

作成するものは、下記のような「本棚アプリ」になります。

「はじめに」にあたる部分のこの一言は良いですね。

But without change, there is no challenge and without challenge, there is no growth.

チュートリアルを進める上で必要な環境としては、

  • Ruby 2.3以上
  • SQLite 3以上

になります。

まずはGemのインストールです。
Gitihubリポジトリはこちらです。

プロジェクトを作成します。
デフォルトのDBはSQLiteになるようです。

いろいろファイルが生成されます。

Gemfile を見てみます。

テストフレームワークは minitest なのに、 spec ディレクトリが生成されているんですね。
(これは注釈がありましたが、 minitest でも RSpec でもどちらでもいけるそうです。)

これらのGemをインストールしてサーバーを起動します。
サーバーは2300番ポートで起動します。

これで http://localhost:2300 にアクセスすると、下記のページが表示されます。

 

実践

はじめてのテスト

テストをする前に、テスト環境のDBをセットアップしておきます。

これで db ディレクトリにSQLiteのファイルができます。

Hanamiは BDDBehavior Driven Development )を推奨しています。
実際にチュートリアルを実施する際には、テストコードから書いていますが、本記事ではテストコードは割愛させていただきます。
途中まで載せていたのですが、文章が冗長になってしまったので、泣く泣く削除しました。

もしテストコードもご覧になる場合は、下記のGithubリンクにてお願いします。
https://github.com/naoki85/bookshelf/tree/master/spec
(一応日本語でコメントもいれています。)

まずはルーティングを定義します。

ここはRailsと変わりません。
Homeコントローラーのindexメソッドを作成。。。と思ったら、コントローラーの定義の仕方が違いました。

コントローラーはまず、 apps/web/controllers の下に home ディレクトリを作成して、その中に index.rb というファイルを作成します。

モジュールで名前空間を切って、Railsでいうアクションがクラスになっています。
include Web::Action は現状、決まり文句でよさそうです。
def call(params) はマジックメソッドみたいなもので、このメソッドがないと呼ばれません。
params にGETやPOSTなどで渡されたパラメータが格納されます。

次にビューですが、基本的にレンダリングするだけであれば、 templates 以下に命名規則に従ってファイルを作成することで、そのテンプレートを表示してくれます。

ここまでで、テストは通りますが、 views 以下にビューコントローラーのようなファイルを作成しておきます。
今回は特にビューにロジックはないため、空のファイルですが、ヘルパー的なものを使用する場合やケースバイケースでテンプレートを変える場合などにお世話になりそうです。

こちらも名前空間を切って、決まり文句の include Web::View を記載しておきます。

テストを実行して、通ればOKです。

新しいアクションを生成

今度は本の一覧を表示するアクションを追加していきます。

Hanami Generatorでアクションを生成

rails generate のようなコマンドがHanamiにもあります。
指定したファイル群を生成してくれます。
今回は books#index を生成します。

テストコードも含めて生成されます。
routes.rb にも自動で追記されています。

ただ、Railsのようにテンプレートの中身まで勝手に作ってくれないようなので、実際に描画されるHTMLは記載する必要があります。

これでテストは通ると思います。

共通部分をLayoutにまとめる

templates/home/index.html.erbtemplates/books/index.html.erb の両方に <h1>Bookshelf</h1> が含まれています。
これは共通部分として、共通のテンプレートに記載します。
共通テンプレートは templates/application.html.erb になります。

これで共通部分に移せたので、先ほどの2つのファイルから h1 タグを消しておきます。

モデルの作成

Hanamiのモデルには entityrepository の2種類があります。

厳密な区分は違うと思いますが、私の解釈としては、

  • entity …SQLに依存しない状態でオブジェクトを管理する場合など
  • repository …テーブルにレコードを作成、更新、削除する場合など(SQLを発行)

SQLを発行するモデルと、DBとは関係なく状態を管理できるモデルという認識です。

実際に使ってみたいと思います。
hanami generate model で、マイグレーションファイルを含め、モデルに関連するファイルを生成できます。

apps ではなく、 libs 以下にモデルが作成されました。
ビジネスロジックは libs 以下で管理し、 apps 以下に複数のマイクロサービスを管理するという考えです。
これはHanamiの大きな特徴の一つです。

マイグレーションファイルは下記のように、 titleauthor カラムを追加します。

マイグレーションを実行します。

色々メッセージが出ると思いますが、下記のような状態になるかと思います。
(確認にはDB Browser for SQLiteを使用しました。)

生成された entityrepository のファイルはそれぞれ下記になります。
lib ディレクトリ以下に作成されており、ビジネスロジックは分けるという考えが伺えます。

それぞれ、HanamiのEntityとRepositoryを継承しており、これだけで最低限の動作ができるようです。
(RailsのActiveRecordみたいな感じですね。)

ちょっとしたコードの確認は hanami console でできます。
色々いじってみたので、まとめます。

Indexの修正

本の一覧表示である index アクションを修正してDBから引っ張ってくるようにします。

まずはコントローラーです。

@books = BookRepository.new.allbooks テーブルからレコードを全件取得してインスタンス変数にセットします。

ただ、 views 、および templates に渡すためにはexposeで指定する必要があります。

これで books 変数を views および templates にて使用することができるようになりました。
templates/books/index.html.erb を下記のように書き換えます。

これで、DBから取得した値の一覧画面ができました。

新規登録画面と登録処理

登録フォームと登録処理を作成していきます。

hanami generateでbooks#newを生成

また、 hanami generate コマンドで生成します。

先ほどと同様、ルーティングへの追記や必要なファイルは全て生成されています。

ただ、テンプレートは作成する必要があります。
今回は入力フォームが必要なので、HanamiのFormHelpersを使用します。
ここはRailsを初めとしたWebフレームワークに触ったことがあれば、理解しやすいかと思います。

hanami generateでbooks#createを生成

実際に新規登録処理をするbooks#createを生成します。

ちなみに create のルーティングはPOSTメソッドとして解釈されて追記されます。

ただ、コントローラーは修正の必要があるので、追記します。

かなり簡潔ですが、後ほどバリデーションを追加した際に、登録失敗した場合の処理も記載します。

パラメーターのバリデーション

バリデーションですが、モデルに書くものかと思いきや、Hanamiではコントローラー内の params で実施できるようです。

Parameters

requireで存在確認、 filledで型を判定しています。
実際に動かしてみると分かりますが、 paramsvalid? したタイミングで、下記のようなハッシュが含まれるようになります。

valid?false だった場合は、HTTPステータスコードの422番をセットして返します。

普通であれば、再度 new.html.erb をレンダリングするよう指示するところですが、それはコントローラーではなく、ビュー側の領分になります。

これでもしパラメーターが無効であっても、 new.html.erb をレンダリングできます。

最後にエラーメッセージを表示する部分を追記します。

ここまでで、下図のような画面になります。

ルーティングの修正

HanamiにもRESTなルーティングを生成できるresourcesが存在するため、そちらで修正しておきます。
この使い方はRailsとほとんど同じですね。

さいごに

チュートリアルが終わった後、CSSにMaterializeを使用してみてスタイリングしてみました。

ただ、 Assets まわりはよく分からなく、CDNでもドツボにはまってしまったので、フォントなどは使えていません。
チュートリアル終了〜上記の画面までの差分はこちらになります。
https://github.com/naoki85/bookshelf/commit/7a589c97560d9144bb1a0138241b949793fb8b06

blog-page_footer_336




blog-page_footer_336




-BackEnd
-

執筆者:


  1. ||=とおりすがり。 より:

    本家のチュートリアルと合わせて、こちらの記事も一緒に読み進めながらやってみました。おかげさまで内容を理解しながら完了できました。本当に助かりました。

comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

WebアプリケーションにLINEログインを組み込む

1 はじめに2 LINEログインとは2.1 LINEログインでできること2.2 LINEログインのフロー3 LINEログインの設定3.1 プロバイダーを新規作成する3.2 チャネルを作成する3.3 リ ...

Go言語

GoフレームワークGinでミドルウェアを使ってログインAPIを実装

1 はじめに2 ログインAPIの作成3 ログインのセッション管理4 ミドルウェア4.1 gin.Default()4.2 Logger4.3 Recovery4.4 sessions5 独自ミドルウェ ...

laravel logo

LaravelのArtisanコマンドを自作する

1 はじめに2 コマンドの作成方法3 コマンドの実装3.1 文字列出力3.2 引数3.3 オプション3.4 入力を使用した対話型3.4.1 ask()メソッド3.4.2 secret()メソッド3.4 ...

Go言語

GoのWeb Application Framework

1 はじめに2 代表的なGoのWAF2.1 軽量なWAF2.2 フルスタックなWAF3 Ginを使ってみる3.1 クエリパラメータ+ポストパラメータ3.2 ファイルアップロード3.3 URLのグループ ...

rails

Ruby2.4でCookieを手動で復号する際に発生したエラーの対処

1 はじめに1.1 前提条件2 発生したエラー2.1 実際のコード2.2 エラー詳細2.3 原因3 どう対処したか3.1 修正後のコード はじめに こんにちは、onoです。 現在開発中のアプリケーショ ...

フォロー

blog-page_side_responsive

2017年9月
 12
3456789
10111213141516
17181920212223
24252627282930

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。