Rubyベースの静的サイトジェネレータ「Middleman」では、主要なHTML要素を生成するためのヘルパーメソッドが予め用意されています。
ヘルパーメソッドの引数にオプションを指定することによって、id や class 等の属性値を指定することができますが、頻繁に使用する組み合わせがあるならば専用のヘルパーメソッド(カスタムヘルパ)を作ってしまった方が便利です。

例として、今回は Middleman に予め用意されている <a>タグを生成する「リンクヘルパ」 link_to メソッドを元に、リンクを新しいタブで開くようにする link_to_blank メソッドを作成してみました。

link_toメソッドの定義を確認

まずは、GitHubで公開されているMiddlemanのソースコードの中から、link_to メソッドの定義を確認します。

https://github.com/middleman/middleman/blob/master/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb
に含まれていましたので、抜粋しています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def link_to(*args, &block)
  url_arg_index = block_given? ? 0 : 1
  options_index = block_given? ? 1 : 2

  raise ArgumentError, 'Too many arguments to link_to(url, options={}, &block)' if block_given? && args.size > 2

  url = args[url_arg_index]

  if url
    options = args[options_index] || {}
    raise ArgumentError, 'Options must be a hash' unless options.is_a?(Hash)

    args[url_arg_index] = url_for(url, options)

    options.except!(:relative, :current_resource, :find_resource, :query, :anchor, :fragment)
  end

  super(*args, &block)
end

公式ドキュメントに記載の通り、link_to にはブロックを渡すことも出来るので、ブロックの有無に応じて使用する引数を切り替える処理になっている事が分かります。

ヘルパメソッドの追加

link_to メソッドを参考にして、link_to_blank メソッドを追加します。

config.rb 内の helpers do ~ end ブロック内にメソッドを定義することで、テンプレートファイル等からメソッドが使用可能となります。

1
2
3
4
5
6
7
8
9
10
11
12
13
helpers do

  def link_to_blank(*args, &block)
    options_index = block_given? ? 1 : 2

    args[options_index] ||= Hash.new
    args[options_index].store(:target, "_blank")
    args[options_index].store(:rel, "nofollow noopener noreferrer")

    link_to(*args, &block)
  end

end

link_to メソッドをそのまま link_to_blank メソッドに置き換えられるよう引数を同じにし、target="_blank" rel="nofollow noopener noreferrer" 要素を追加したうえで、link_to へ処理を引き継ぐ動作としました。

同様にして helpers do ~ end ブロック内に複数のメソッドを定義することが可能です。

モジュールファイルに分離して管理

追加したヘルパメソッドが多くなってくると、config.rb のコードが長くなってしまい、後々のメンテナンスが煩雑になってしまいます。
そこで、メソッドをモジュールファイルに分離して管理するのがスマートです。

今回はモジュールファイルとして、 helpers/link_helper.rb を作成しました。
メソッドの目的等に応じて、複数のモジュールファイルに分ける事も出来ます。

モジュールを定義し(今回は LinkHelper としました)、この中に config.rb に記述していたメソッド定義を移動します。
ファイル名やモジュール名は任意で付ける事ができますが、Rubyの命名規則に従いましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# モジュールの定義
module LinkHelper

  # Make <a> tag with target="_blank"
  def link_to_blank(*args, &block)
    options_index = block_given? ? 1 : 2

    args[options_index] ||= Hash.new
    args[options_index].store(:target, "_blank")
    args[options_index].store(:rel, "nofollow noopener noreferrer")

    link_to(*args, &block)
  end

end

続いて、作成したモジュールをMiddlemanで読み込むための設定を config.rb に記述すれば、helpers do ~ end ブロック内に定義した場合と同様にメソッドを呼び出せるようになります。

1
2
3
4
5
6
7
8
# モジュールファイル用のディレクトリを指定
set :helpers_dir, 'helpers'

# モジュールファイルを指定
require_relative 'helpers/link_helper'

# モジュール内のヘルパを読み込む
helpers LinkHelper