Mobbの機能拡張を実現するhelpersとregister


この記事は Mobb/Repp Advent Calendar の五日目です

Mobbの機能拡張

これまで見てきたように、MobbにはSinatraとほぼ同じ仕組みが多数存在します。そして今日紹介するhelpers/registerメソッドも、Sinatra由来の機能です。これら2つのメソッドは、Sinatraと全く同じコードが書かれているので、挙動も全く同じです。

helpers

helpersメソッドは、トップレベルモード(require ‘mobb’をしてそのままロジックを書き始めるケース)では暗黙的に作成されるMobbのアプリケーションクラスを、モジュラーモード(require ‘mobb/base’ して自分でクラスを定義するケース)ではhelpersが呼び出されたクラスをそれぞれコンテキストとして、渡されたブロックをclass_evalで実行します。ブロックではなくモジュールを渡した場合は、そのモジュールがincludeされます。

モジュラーモードでは、そもそもhelpersの中で定義しようがクラスの中で定義しようが、クラスのインスタンスメソッドとして定義されるのであまり違いはありません。ですが、トップレベルモードの場合、Rubyのmainクラスで定義したメソッドはObjectのプライベートメソッドとして定義されるので、いろいろなものを汚染しかねません。そのため、暗黙的に作られるMobbアプリケーションのクラスに、helpersを使って直接定義を行います。

https://docs.ruby-lang.org/ja/latest/class/main.html

やっていることは結局の所include呼び出しとあまり変わりませんが、ブロックを渡せるところが軽量でいいと思います。

helpersメソッドの中身は、Mobb::Baseを継承したアプリケーションを拡張しています。

register

helpersがclass_evalを行うのに対して、registerはclassにextendをおこないます。もしブロックが渡された場合は、そのブロックの内容で即時的にModuleオブジェクトを作成し、それをextendします。

includeとextendの違いはいくつかありますが、その一つにincludeはクラスを拡張するのに対し、extendはクラスオブジェクトを拡張する、つまりクラスメソッドを定義するという点が挙げられます。

たとえば、次のコードは実際にhelloを受け取ったときに失敗します。

なぜならば、helloのブロックが実行されるのは、Botインスタンスのコンテキストですが、registerメソッドが作成するのはBotのクラスメソッドだからです。インスタンスからは、クラスメソッドを参照することは通常できません。正しく動かす場合には、settingsを使ってアプリケーションクラスに対するアクセスが必要です。

また、helpersと大きく違うのは、registerはextendを実行したあとのフックを持っています。

registerを使用すると、Botクラスの各メソッドにアクセスが可能です。つまり、Mobb::Baseクラスを直接機能拡張することが可能なのです。

helpers or register ?

さて、helpersとextendsですが、面白いことにこの2つのメソッドはそれぞれ互いを互いの中で呼ぶことが出来ます。例えば、このような使い方です。

registerの中からhelpersを使うには、registeredの引数に渡されたアプリケーションクラスを経由して行います。

helpersの中からregisterを使うのは、わかりやすいですね。コンテキストが特に変わっていないからです。

このように、helpers と register は、使い方によっては別にどちらを使っても良いように思いますが、それぞれ記述の容易さなどから次のように使い分けられます。

helpersは、Mobbアプリケーションの実行時に使いたい機能、すなわち on メソッドや cron メソッドのブロックの中から使いたいヘルパーメソッドを定義するのに使用されます。ユーザーは、自身のビジネスロジックを記述するために、helpersを利用することになると思います。

それに対してregisterは、アプリケーションの起動時、すなわち構築のときに使われるMobbそのものを拡張するケースに用いられます。

Mobbアプリケーションを書くユーザーが最も利用するのは、helpersです。むしろ、registerを利用するケースは殆ど無いでしょう。ですが、Mobbアプリケーションの拡張を書く必要があり、それを再利用するケースでは、registerを使用します。例えば、MobbからActiveRecordを利用するmobb-activerecordというgemは、registerを使った拡張という形で書かれています。

わりと似たような機能ですが、やっていることは歴然と違いそれぞれ用途はっきりとわかれているので、みなさんも自分の必要に応じたほうを利用してください。


この記事は未分類に投稿されました. このパーマリンクをブックマークする。 コメントを投稿するか、トラックバックをどうぞ: トラックバック URL.

コメントする

あなたのメールは 絶対に 公開されたり共有されたりしません。 * が付いている欄は必須項目です

次の HTML タグと属性が使用できます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

*
*