Rubyの関数オブジェクト

  • 投稿日:
  • by
  • カテゴリ:

tl;dr;

基本的には以下のページで説明されているとおりだと思います。

この記事は、これらを少し長めのコードで試してみたものです。

関数オブジェクトを取得

Object#methodで取得できるとのことで、まずは試してみました。

以下のことが分かりました。

  • トップレベルでのメソッド定義はmodule Kernelにプライベートメソッドとして追加される
    • トップレベルのselfであるmainで呼べるようになる
  • method(:hello) (つまり self.method(:hello) で)トップレベルの hello をオブジェクトとして取得できる
  • 定義したクラスのメソッドも instance.method(:hello) で取得できる

レシーバの確認

Object#methodから返ってくるのはclass Methodのオブジェクトで、「メソッドの実体(名前でなく)とレシーバの組を封入します」とのことなので、どのような意味か確認しました。

Object#methodを呼んだ際のレシーバが、暗黙のレシーバであるselfとして封入されていそうです。

Procはどうなっているか?

暗黙のレシーバの確認をしていて、そういえばProcだどどうなんだろうと思って調べてみました。

Procは「ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです」とのことなので、selfへの参照も含まれるということだと思います。

class UnboundMethodの存在

ここまで忘れていましたが、Module#instance_methodを使うと、レシーバをもたないオブジェクトを取得することができるようです。

Module#instance_method に「バインドできるのは、 生成元のクラスかそのサブクラスのインスタンスのみです。」とあるとおり、確かにサブクラスでもないObjectをbindしようとしたらTypeErrorになりました。

まとめ

  • Object#methodで関数オブジェクトを取得できる
  • 関数オブジェクト(MethodやProc)はレシーバの情報ももっていて、オブジェクトをcallした場合にはそれが暗黙のレシーバとして使われる
    • レシーバをもたないclass UnboundMethodもあるが、UnboundMethod#bindしないと呼べない

ということのようです。

これは何か?

iOSの「ショートカットアプリ」用のショートカットをサーバー側で生成して、iPhoneからはQRコードを読むだけでインストールできるようにする、Movable Typeのプラグインです。

ShortcutsApp

このプラグインを使って生成したショートカットでは「Data APIのURL」のような設定が最初から埋め込まれているので、iPhone側では何も設定することなく利用することができます。(「Webサービスのパスワード」も埋め込むことができますが、暗号化はされません。その辺りの問題については以前の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルの記事の「サンプルを利用する場合の注意事項」参照してください)

使い方

プラグインのZIPファイルをダウンロードして、Movable Typeへインストールすると利用できるようになります。設定は特に必要ありません。

インストールすると左側のメニューに「ツール > ショートカット.app」が追加され、メニューをクリックすると利用できるショートカットの一覧が表示されます。一覧からは、「インストールボタンのクリック -> iOS端末でQRコードを読み込み -> 表示された画面からインストール」の流れでiOS端末にショートカットをインストールすることができます。

管理者ユーザーでアクセスしている場合には、一覧のインストールボタンの左側にユーザーアカウントの選択肢が表示されます。「パスワードを埋め込む」を選択した場合には、ここで選択したユーザーのWebサービスパスワードが埋め込まれたショートカットを用意できます。これを使うと「管理者ユーザーが代理でMT上で操作を行い、ショートカットの利用者にはメールでインストール用のURLを送る」というような運用をすることができます。

同梱されているショートカット

以下の2つのショートカットが同梱されています。

写真を投稿

「写真」アプリのシェアボタンから、ショートカットを選択するとそのまま記事を投稿できます。以前の記事の「iOS12のショートカットアプリとMovable TypeのData API」のサンプルで紹介したショートカットと同じものです。

「パスワードを埋め込む」を選択していない場合には、投稿時にWebサービスのパスワードの入力が必要になります。

再構築

すべてのテンプレートを再構築します。

システムコンテキストからインストールした場合にはMovable Type 内のすべてのサイトが、サイトのコンテキストでインストールした場合にはそのサイトが、それぞれ再構築されます。

Siriに再構築をお願いすることもできます。

ショートカットの追加

ショートカットは、「テーマ」のように後から追加することもできるようになっています。

ショートカットの書き出しファイルの仕様は以前の記事でも触れたのですが、アプリから書き出されるバイナリファイルをXML形式に変換して編集することが可能です。また、以前の記事の時点からの新しい発見もあって、「ショートカットアプリには、XML形式を再びバイナリに戻して読み込ませる必要がある」かと思っていたところ必ずしもそうではなく「shortcuts://import-shortcut というURLを使った場合には、XML形式のまま読み込ませることができる」ということが分かりました。このプラグインではこの方法を利用して、ショートカットをMTMLを使ったテンプレートで管理しています。バイナリ形式に戻す必要がないため(XMLファイルさえ生成できればよいので)、インストール先のサーバー環境を選ばずに動作するようになっています。

具体的なカスタマイズの手順

手順は以下の通りです。

  1. iOSのショートカットアプリでショートカットを作成する
  2. ファイルとして書き出す
  3. XML形式に変換する
  4. ショートカットの定義(プラグイン独自の shortcut.yaml )を書く
  5. プラグイン内のshortcutsディレクトリの下に入れる

1が非常につらい作業(ショートカットアプリ内で、GUIでかつ限りられた機能だけでのプログラミング)ではありますが、他は特に難しいことはないと思います。基本的にはテーマを追加するのと同じような手順です。

XML形式への変換

Macであれば以下のコマンドが利用できます。

plutil -convert xml1 -o MT用テンプレート.tmpl 書き出したファイル.shortcut

またはDockerを利用できる環境であれば、以下のコマンドが利用できます。

docker run -it --rm -v $PWD:/files usualoma/libplist plistutil -i /files/書き出したファイル.shortcut -o /files/MT用テンプレート.xml.shortcut

shortcut.yamlを書く

ショートカットの定義をshortcut.yamlに書きます。テーマでのtheme.yamlのようなもので、主なキーの意味は以下の通りです。

  • id : ショートカットのID
  • label : MTの管理画面上での名前
  • version : バージョン
  • name : インストール先のショートカットアプリでの名前
  • description : ショートカットの説明
  • install_instruction : インストールの手順などの説明文
  • view : 利用可能なコンテキスト(system、website、blog)
  • template : ショートカットのテンプレートのファイル
  • expires_in : インストール用URLの有効期限の秒数

同梱されているショートカットを雛形にすると簡単かもしれません。

トラブルシューティング

写真の投稿ができない

iOSの問題だと思うのですが、時々ショートカットが正常にインストールできないことがあり、「写真の情報を取得できない」という問題が発生することがあります。この問題は「インストール前に写真アプリを開いておく」ということで発生確率を下げることができそうなのですが、それでも発生することが稀にあります。

発生した場合には、インストールしたショートカットを一度削除して、インストールし直すという手順で修正されると思います。

まとめ

「写真アプリからのシェア操作で投稿できる」というのはなかなか新鮮な体験だと思うので、ぜひ試してもらえればと思います。

またこのプラグインの例ではでは「写真のアップロードから、記事の作成と公開」まで行っていますが、もっとシンプルに「写真をアップローロドするだけ」というようなショートカットも実際の運用では便利だったりすると思うので、ショートカットアプリとData APIを連携は考え方しだいで、いろいろと面白いことができそうな気がします。

この記事について

この記事は Movable Type Advent Calendar 2018 の10日目の記事です。

Happy Holidays!

発生する条件

php.iniで以下のように設定されている時に、multipart/form-dataでUTF-8の内容をPOSTすると文字化けすることがある。(application/x-www-form-urlencodedでは文字化けしない)

mbstring.encoding_translation = On
mbstring.http_input = auto
mbstring.internal_encoding = UTF-8

どんな流れで発生しているか?

PHPではPOST時のハンドラをMIMEタイプ毎に登録する仕組みになっているようで、mbstringでは以下の場所でapplication/x-www-form-urlencodedとmultipart/form-dataで別々のハンドラが登録されている。

https://github.com/php/php-src/blob/master/ext/mbstring/mbstring.c#L680-L681

application/x-www-form-urlencodedの場合はmbstring内でリクエストのボディ全体から文字コードを判定するため、期待した通りUTF-8として扱われる

multipart/form-dataの場合は以下の場所で文字コードの判別が行われるが、

https://github.com/php/php-src/blob/master/main/rfc1867.c#L427-L429

判別対象のデータが例えば以下のようなヘッダー行なので、

Content-Disposition: form-data; name="name"

「mbstring.http_input = auto」 => 「ASCII,UTF-8」だとASCIIだと判定されてしまい。その下に続く内容もASCIIとして「ASCII -> UTF-8」で変換が行われてしまう。

回避方法

以下のような方法がある。

  • 「mbstring.http_input = UTF-8」にする
  • フォーム要素に「multipart/form-data」をつけない
  • 全ての項目のname属性にマルチバイトの文字を入れる

以下のようなフォームであれば文字化けしない。

<form enctype="multipart/form-data" method="POST">
<input name="?" value="天野" />
</form>

この記事について

iOS12で利用できるようになったショートカットアプリは、自分の好みの「手順」をSiriから呼び出せるようにしたりホーム画面にショートカットを作ったりできるというものですが、その中でどうやら「手順」としてウェブAPIへのリクエストをなかなか自由にできるらしいという話を聞いたので、それならばということで、Movable TypeのData APIとの連携を試してみました。

この記事では、実際の運用でありえそうなパターンとして以下の3つのサンプルを紹介します。

  • 写真を選択して記事を作成
    • 写真は複数選択が可能で、記事には写真を撮影した際の位置情報が付与されます。
  • Evernoteから記事を作成
  • コンテンツタイプとしてURLを収集

それぞれのパターンについて、項目の下の方にエクスポートした「.shortcut」へのリンクを置きました。iOS12でショートカットアプリをインストールしてあれば、実際にショートカットを試してみることもできます。(動画では実行時にパスワードが表示されてしまっていますが、「.shortcut」からインストールされるバージョンでは実行しただけでは表示されないように修正されています。)

対象になるMTのバージョン

コンテンツタイプを利用するサンプルではMT7が必要です。それ以外のサンプルはMT6でも動作します。

写真を選択して記事を作成

ショートカットアプリを使うと「共有シート」に項目を追加して、選択した写真を「ショートカット」に渡すことができるようになります。

このサンプルではそれを使って、以下の操作で記事を作成できるようにしてみました。

  1. 写真を選択(複数可)
  2. シェアボタンから、登録したショートカットを選択
  3. タイトルと本文を指定

写真はアセットとしてアップロードされ、記事の本文に挿入されます。(カスタムフィールド版もあります)写真に位置情報が含まれている場合には、緯度と経度も投稿情報に含まれます。

MTへ画像を投稿.shortcut

カスタムフィールド版

カスタムフィールド版では、「記事」に対して以下のようなベースネームを持つフィールドが設定されていることを想定しています。

  • image
  • latitude
  • longitude

1枚目の画像がimageのフィールドに入り、2枚目以降の画像は本文に挿入されます。

MTへ画像を投稿(カスタムフィールド版).shortcut

Evernoteから記事を作成

メモアプリや編集アプリからデータを受け取り、MTで記事を作成するパターンです。ここではEvernoteと連携させています。

Evernoteでは普通に書くとh2、h3などの細かい指定はできないため、以下のような形で置き換えるようにしています。

  • 太字 -> h3
  • リスト -> そのまま
  • その他 -> divなどは削除し、極力シンプルなHTMLになるようにする

変換結果がやや不安定なので、このサンプルは現実的に使い物になるかどうかはやや微妙です。Markdownの編集アプリからそのままMarkdownとして投稿などの方が現実的かもしれません。

EvernoteからMTへ投稿.shortcut

コンテンツタイプとしてURLを収集

スマートフォンからアクションすると考えると、「記事」よりも細かい(「ソーシャルブックマークに追加」程度の)粒度でなにかできるとよい場合もあると思います。このサンプルでは、以下のようなフローで記事作成を行うための「URLの収集」をショートカットでできるようにしてみました。

  • 記事にするURLをスマートフォンで収集しておく
  • 後で収集したURLを組み合わせて「まとめページ」をつくる

こういった場合には、MT7のコンテンツタイプが使えそうです。

  • URL
  • タイトル
  • og:image
  • 埋め込みHTML

といったフィールドをもつコンテンツタイプを作り、ここにデータを貯めていきます。「タイトル」「og:image」はショートカットの中で自動で取得します。「埋め込みHTML」はURLがTwitterの場合にのみ、oembedのAPIを使って自動で取得します。(少し拡張すれば、YouTubeなどoembedのAPIを提供している他のサービスでも取得できるようになります)

URLをMTへ保存.shortcut

管理画面の方は以下のような雰囲気です。

ref-page-type.png
「参照ページ」コンテンツタイプ
a-ref-page.png
参照ページの編集
curation-page-type.png
「まとめページ」コンテンツタイプ
a-curation-page.png
まとめページの編集

サンプルの紹介は以上になります。

サンプルを利用する場合の注意事項

これらのショートカットアプリではWebアプリのパスワードを利用するのですが、「テキストデータ」としてしか保存する方法が見つからなかったので、「ショートカット」を開くと確認できる状態で保存されます。一応、通常の使用では表示されないように工夫はしているのですが、アプリから開くと容易に表示可能です。特に強い権限を持つユーザーで利用する場合には注意が必要です。(「iCloudキーチェーン」が使えるとよさそうなのですが、それはまだできないようで。)

「ショートカット」の可能性

ショートカットアプリで作成した「ショートカット」は共有のために書き出すことができるのですが、書き出されるファイルは(バイナリの)plist形式なので、少し手を加えることでテキストエディタで編集することもできます。Macであれば以下のようなコマンドを実行することで編集が可能です。(Linuxにも同様の結果を得ることができるコマンドがあります)

テキストとして編集できることにより、例えば以下のようなことができるようになります。

  • エンドポイントの設定の埋め込み
  • ユーザーIDやパスワードの埋め込み
  • メッセージの多言語化

これらを利用することで、例えばリテラシーの高くないユーザーに対しても「(編集済みの)ショートカットを受け取ってインストールするだけで、エンドポイントやパスワードを設定しなくても利用できる」というようにすることができそうです。

まとめ

これはなかなか面白いものだと思います。上のサンプルよりもっとシンプルなものでも、例えば「アセットの一括アップロード」だけでも十分に役立ちそうなので、MTを使っているならば(特別にマッチするような運用ではなくても)普通に便利に使えるような気がしています。 パスワードをそのまま埋め込まざるを得ないなど、現状としては課題もありますが、それらは今後のアップデートを(あまり期待せずに)待ちたいと思います。

MFA - MTで多要素認証を有効にするプラグイン

  • 投稿日:
  • by
  • カテゴリ:

Movable Typeで、サインイン時に多要素認証を利用できるようにするプラグインを公開しました。

現時点では「Eメールによる確認コードの送信」と「Google Authenticator(TOTPが利用できるデバイスやアプリ)による確認コードの生成」に対応しています。(どちらか一方のみを、システムで有効化できます)

いずれのプラグインも、Movable Type 6 でも Movable Type 7 でも利用できます。(どちらかというと Movable Type 7 に最適化されています)

Eメールによる確認コードの送信

デモ

使い方

以下の2つのプラグインをインストールします。

インストールすると全てのユーザーで、サインイン時にEメール経由で送信される確認コードの入力が必要になります。

Google Authenticatorによる確認コードの生成

デモ

インストールに必要な要件

CPANモジュールのDigest::HMAC_SHA1を必要としています。マネージドなレンタルサーバーではインストール済みであることが多いと思います。自分で環境を構築している場合には明示的にインストールする必要があるかもしれません。

また、同じくCPANモジュールのMath::Random::MTは、必須ではないものの推奨されています。このモジュールがインストールされていると暗号的により好ましい設定が生成されます。(ただ、多要素認証はパスワード認証を補強するものであるので、「インストールされていなくてやや好ましくない設定が生成される」状態ではあっても、充分に有用なものであると言えると思います)

使い方

以下の2つのプラグインをインストールします。

インストールすると各ユーザーが、ログイン後に「システム > 多要素認証」のメニュー内の「Google Authenticator」で有効と無効を切り替えられるようになります。Google Authenticatorだけでなく、 AuthyなどTOTPに対応している多要素認証のコードを生成するアプリケーションであれば利用できると思います。有効化されているユーザーでは、サインイン時に確認コードの入力が必要になります。

万が一、デバイスを紛失するなどでコードが生成できなくなった場合には、管理者としてサインインすると「システム > ユーザー」で多要素認証のリセットを行うことができます。(管理者がサインインできなくなった場合にはまずは落ち着いて、その後プラグインをアンインストールしてサインインして、サインイン状態のまま再度インストールするとサインイン状態が維持されるので、そこでリセットの操作を行うことができます)

TODO

現時点では、これらのプラグインでは最低限の機能しか提供されていませんが、今後としては以下のような展開があってもいいかもしれません。

  • リカバリーコードを利用できるようにする
    • デバイスが手元になかったり紛失したりしてしまった場合に利用できる、リカバリーコードを生成できるようになるとよさそうです
  • 有効にする認証のタイプを選択できるようにする
    • 現在は、システム全体でEメールかGoogle Authenticatorのどちらか一方しか利用できないので、ユーザー自身で複数のタイプから選択できるようになるとよさそうです
  • 多要素認証のポリシーをシステム全体で設定できるようにする
    • 「多要素認証を、全てのユーザーで必須にする」などのポリシーを定められるようになるとよさそうです

この記事について

この記事は Movable Type Advent Calendar 2017 の21日目の記事です。