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


関連記事

RSpecの個人的Tips集〜その1〜

1 はじめに2 テストコードの実行をスキップする3 共通のテストコードを用意する4 外部APIの返却値をスタブにする5 さいごに はじめに みなさん、テストコードは書かれているでしょうか? 私も極力書 ...

Go言語

Go言語のエラーハンドリングとログローテーション

1 はじめに2 エラーハンドリング2.1 error インターフェース2.2 pkg/errors パッケージ3 独自のエラータイプ付き errorsパッケージを作成4 log パッケージ4.1 lo ...

laravel logo

Laravelのブラウザテスト「Dusk」をシンプルなCRUDで始めてみよう

1 はじめに2 Laravel Duskのセットアップ3 新規登録のテスト3.1 テスト対象となるコード3.2 Duskのテストコード3.3 テストの実行4 更新のテスト4.1 テスト対象となるコード ...

laravel logo

[Laravel] middlewareでHTTPリクエストの前後に処理を入れる

1 はじめに2 middlewareとは3 実装3.1 middleware作成3.2 コード実装4 middleware定義4.1 常に呼び出す4.2 特定のURLにアクセスした時のみ呼び出す4.3 ...

rails

Ruby、Railsの時間に関するメソッドを使用してみた

はじめに 普段PHPのお仕事をしています、tonnyです。 半年程前からRuby on Railsの勉強を始めました。 今回はよく使う時間に関するメソッドついてまとめたいと思います。 目次 1 はじめ ...

フォロー

blog-page_side_responsive

2017年9月
 12
3456789
10111213141516
17181920212223
24252627282930

アプリ情報

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