Hanamiで異なるappのroutesを使う場合

Hanami Guides / 1.1 / Routing / Basic Usage を見ると、Railsと同じように、
(Hanamiガイドより引用)

<%= routes.path(:greeting) %>
<%= routes.url(:greeting) %>
Or
<%= routes.greeting_path %>
<%= routes.greeting_url %>

としてroutingのパスが取得できる。

ただし、これはあくまでそのapp内でconfig/routes.rbで定義したルーティングのパスを取得だけとなる。異なるappのルーティングのパスを取得したい場合は、「app名.routes.ルーティング名_path」で指定ができる。

(例)
apps
 ├ gnote ← Gnoteアプリ
 ├ gnote_api ← GnoteApiアプリ

とあった場合に、Gnoteアプリから、GnoteApiアプリのlikesアクションのルーティングのパスを取得する場合は、Gnoteアプリ内で、「GnoteApi.routes.likes_path」と指定する。

なお、ルーティング名は、Railsと同じように、ターミナルから、「bundle exec hanami routes」を打てば表示される。その中のNameがルーティング名になる。

■参考サイト
Referencing a different app’s routes in Hanami

HanamiのRepositoryで作成した独自SQLクエリーのデータにアクセスする

Repositories: SQL Queries – Hanami に書かれているとおり、Repositoryに定義するだけだが、このままだとviewに渡されるまでメソッドが実行されないので、InteractorsとかControllerでクエリー結果のデータにアクセスしようと思っても、アクセスできない。

■HanamiのDBクエリー

HanamiのDBクエリーは、Ruby Object Mapper(ORM)Sequel が使われている。

以下、Hanami Guide v1.1からの引用。

Hanami queries are based on gems from ROM project, namely rom-repository and rom-sql. The gem rom-sql is itself based on Sequel project.
Learn more on how to craft queries with ROM and Sequel.

■最初から用意されているメソッドはアクセス可能

Repositories Overview #Interface – Hanami に書かれている、最初から用意されているallとかfirstなどのメソッドは、おそらくすぐにcallされているためか、データにアクセス可能。

■データにアクセスする方法

.call.collectionをつけると、クエリーを即時実行してデータにアクセスができる。

(例)
lib/gnote/repositories/message_repository.rb
—————————————————————–
class GnoteMessageRepository < Hanami::Repository
・・・
 def most_recent_posts(most_recent_start_date)
    gnote_messages
      .where(
        created_at: most_recent_start_date..CURRENT_DATE,
        is_deleted: nil
      )
      .order{ created_at.desc }
      .call.collection
  end
・・・
end
—————————————————————–

lib/gnote/interactors/index_messages.rb
—————————————————————–
require ‘hanami/interactor’
・・・
    def call
      @most_recent = @repository.most_recent_posts(MOST_RECENT_START_DATE) # call  lib/gnote/repositories/message_repository.rb
      Hanami.logger.debug @most_recent.inspect
    end
・・・
end
—————————————————————–

コンソールの出力結果
—————————————————————–
[tanebox] [DEBUG] [2018-01-05 23:02:48 +0700] [#2,
:created_at=>2018-01-05 07:51:54 UTC, :updated_at=>2018-01-05
07:51:54 UTC, :author_hash_ip=>nil, :content=>”カレー作ったえらい”,
:is_deleted=>nil}>, #1,
:created_at=>2018-01-04 13:35:21 UTC, :updated_at=>2018-01-04
13:35:21 UTC, :author_hash_ip=>nil, :content=>”早起きできた!”,
:is_deleted=>nil}>]
—————————————————————–

■.call.collectionをつけない場合

コンソールの出力結果(クエリー文が出力される)
—————————————————————–
[tanebox] [DEBUG] [2018-01-05 22:43:34 +0700] #= ‘2017-12-29’) AND (`created_at` <= ‘2018-01-06’) AND (`is_deleted` IS NULL)) ORDER BY `created_at` DESC”>>
—————————————————————–

■.callのみつけた場合

コンソールの出力結果(クエリー文とデータオブジェクトが出力される)
—————————————————————–
[tanebox] [DEBUG] [2018-01-05 22:53:52 +0700] #@source
=#= ‘2017-12-29’) AND (`created_at` <= ‘2018-01-06’) AND (`is_deleted` IS NULL)) ORDER BY `created_at` DESC”>>, @collection=[#2,
:created_at=>2018-01-05 07:51:54 UTC, :updated_at=>2018-01-05
07:51:54 UTC, :author_hash_ip=>nil, :content=>”カレー作ったえらい”,
:is_deleted=>nil}>, #1,
:created_at=>2018-01-04 13:35:21 UTC, :updated_at=>2018-01-04
13:35:21 UTC, :author_hash_ip=>nil, :content=>”早起きできた!”,
:is_deleted=>nil}>]>
—————————————————————–

■.callと.collectionの意味(推測)

ROMとSequelの両方のAPIドキュメントを見たがメソッドの解説を発見できなかったので以下推測。
・call → rubyのcallメソッドと同じ意味で、メソッドを即時実行(評価)する。.callをつけるまで実行されず(遅延評価)、逆にタイミングのよいときに実行させることができる。
・collection → collectionのattributeにアクセスする。.collectionをつけないと、@source(クエリー文)と@collection(データオブジェクト)が出力される。

■.callと.collectionをつけなかった場合のクエリー実行場所(推測)

Hanamiのソースコードを読んでないのであっているかわからないが、各レイヤーでdebugした結果だと以下のとおり。

ユーザーアクセス → Routes → Controller → Interactor → Repository, Entity → Interactor → Controller → |Viewレイヤーでクエリー実行| View, Template → 画面描画

■参考ソースコード

pinfluence/lib/pinfluence/repositories/moment_repository.rb

Hanamiのデバッグは Hanami.logger.debug

Hanamiでデバッグするときは、
「Hanami.logger.debug 調べたいもの.inspect」とすると、コンソールに「[web] [DEBUG] [2018-01-05 10:14:35 +0700] {:a=>1, :b=>2, :c=>3}」みたいな感じで 、中身が出力される。 (Raisだと、Rails.logger.debugっていうやつ)

(例)Hanami.logger.debug @post.inspect

■参考情報
Each project has a global logger available at Hanami.logger that can be used like this: Hanami.logger.debug “Hello”
Hanami – Logging