Hanami::Controllerで共通の処理を差し込む

Meetup #100 - Kanazawarb に参加したらちょっと高まったので!

Hanamiは比較的継承が少ない

Hanami のコードの一つの特徴として、「継承を避けて mixin を使いがち」というものがある。もう少し具体的には

パス実現方法
apps/Action も View も moulde の mixin
lib/Hanami::Entity も Hanami::Repository も継承
lib/*/mailers/mixin
db/migrations/単なる DSL

のようになっていて、簡単に言うと Rails のようには

ApplicationController にメソッドを追加したらすべての controller で使える、みたいな素朴な OOP が通用しない

ようになっている。

これはこれで巨大な superclass を作らないようにさせる矯正ギプスとして面白いなと思う反面、mixin が多くなるのは Ruby 力を要求しやすいのでは? という気もしないでもない。

ApplicationControllerの代わりになるもの

application.rb の中の

module Web
  class Application < Hanami::Application
    configure do
      ..
      # Handle exceptions with HTTP statuses (true) or don't catch them (false).
      # Defaults to true.
      # See: http://www.rubydoc.info/gems/hanami-controller/#Exceptions_management
      #
      # handle_exceptions true

      controller.prepare do
        # include MyAuthentication # included in all the actions
        # before :authenticate!    # run an authentication before callback
      end
    end
  end
end

ここ。

Controllerのbefore, after callback

Actions: Control Flow | Hanami Guides

Controller には before / after の callback があって、Symbol を使ってメソッドを呼んだり、直接 block を与えたりすることができる。これは Rails の Controller によく似ていて、この before / after メソッドを 上の controller.prepare block にも与えることができる。

もし ApplicationController の before / after で処理を加えていたのなら、ここに同じように書くことができる。

configure do
  controller.prepare do
    before do
      ..
    end
  end
end

また、この中で self を参照すると実際に request を受けた Controller を取得できる。

例外を拾う

例外を拾う方法は以下のようになっている。

フレームワーク例外を処理するメソッド
Railsrescue_from
Hanamihandle_exception

Rails の ApplicationController で言う rescue_from は Hanami では handle_exception になるんだけど、これも上の before / after と同じように Action に該当する class 内に書いても controller.prepare に与える block 内に書いても同じように動作する。

ただし、development では handle_excepions が false になっているので、

  configure :development do
-   handle_exceptions false
+   handle_exceptions true
  end

に変更しておかないと実際のエラーを目視しながら開発することはできない。これも Rails と同じだと思う。

超今さらS3 + CloudFront + CloudFormationでWebサイトを公開する設定についてOriginとProtocolの注意点

※ 独自ドメイン関係の話は一切ないです。あくまで公開できる状態になるまでで S3 Web Site Hosting と CloudFront の Origin の設定と Protocol の話のみです。

S3はWeb Site Hostingにすべし

最近は AWS 側で不必要に S3 Bucket を公開してしまわないように Web UI でいろいろ警告してくれるというか分かりやすくしてくれていて、「もしかして S3 の Web Site Hosting って実は使ってほしくないのかな?」という雰囲気を感じていたんだけど、どうもそういう意図はないらしい。うっかりを防ぎたいだけっぽい。

というのも、

Web Site Hosting にしておかないと IndexDocument などの機能が効かないので / で終わる Directory へのアクセスは不可能

だから。

※ 逆に、 / で終わる URI が世界に共有されないのであれば Web Site Hosting でなくてもよい。

cf. ウェブサイトエンドポイント - Amazon Simple Storage Service

CloudFrontからS3へCustom Originで繋ぐ

CloudFront から S3 を見にいく場合、S3 Origin としてアクセスしにいくか Custom Origin としてアクセスしにいくかを選べる。

結論から言うと上と同じ理由で

Web サイトとして S3 を使う場合は Custom Origin にする

のが正解。S3 Bucket としてではなくただの Web サイトとしてアクセスしにいく方式だ。

そのため、DomainName の設定は

<bucket-name>.s3-website-<region>.amazonaws.com

にしておく必要がある。

S3 Origin としてアクセスする方式でも asset や upload 済みの「ファイルだけにアクセスさせる」場合は問題ないのだが、「HTTP でリソースにアクセスできることと Web サイトとしてアクセスできることの意味は異なる」ところがポイント。

例えば上のように / で終わる URI に対して CloudFront にアクセスがあった場合、CloudFront は S3 に対してもまったく同じように / というリソースを要求するのだが、これは S3 Object としては存在しない。あくまで S3 上では Object として存在しているのではなく Prefix として機能しているだけなので、これにアクセスすることはできないのだ。

※ トップページ / に対してだけは DefaultRootObject を設定できるのがまた事態をややこしくしている。これは本当にトップの / に対してだけしか効かない。

もし / で終わる URI にアクセスできているとしたら、それは Web Site Hosting 機能の IndexDocument のおかげである。そして Web Site Hosting に対して CloudFront からリクエストするためには Custom Origin にしておく必要がある。

ウェブサイトエンドポイント - Amazon Simple Storage Service

仕上げにCloudFrontからS3へはhttp-onlyで繋ぐ

CloudFront は Origin を複数設定できるのだが、CloudFormation の設定を YAML で書くとすると、

Origins:
  - Id: <Name>
    CustomOriginConfig:
      OriginProtocolPolicy: http-only

としておくのが正解。

CustomOriginConfig では OriginProtocolPolicy が required なのでこれを http-only にしておく。

順番に見ていくと、

  • Origins の設定のところには S3OriginConfig か CustomOriginConfig のいずれかが required
  • S3 Website Hosting に接続するには CustomOriginConfig が required
  • CustomOriginConfig を設定するためには OriginProtocolPolicy が required

という寸法。

S3のWeb Site Hostingはhttp-only

ウェブサイトエンドポイント - Amazon Simple Storage Service

S3 の Web Site Hosting の機能で提供されるのは上の「ウェブサイトホスティング」に該当する。

ということは「SSL 接続をサポートしません」なので、上のように

Origins:
  - Id: <Name>
    CustomOriginConfig:
      OriginProtocolPolicy: http-only

で http-only にしておくのが正解。これで CloudFront へのアクセスが http でも https のどちらであっても、S3 へは http で接続しにいく。

これを指定しておかずにうっかり https でリクエストすると謎の timeout に苦しむことになる。

cf.

おまけ

CloudFormation を使えば確かに設定をコードで管理できるようにはなるが、決してお手軽に設定できるわけではない。

その設定になる理由はすべて資料と現象の観測と収集できる情報から掘り下げていくしかない。

例えば CloudFront で /path/to/resource/ へアクセスすると timeout するが /path/to/resource/index.html へアクセスすれば ok 、http ではアクセスできて https でアクセスできない、といったことは順番に試して現象を観測して分類、整理して解決していくしかない。

そうたくさんくり返すわけでもないこの手の作業こそ基本が大切。

プロメトリック試験受けた

落ちた。

すぐに結果が分かるのである意味すごいショックだけど立ち直りも早い。

素の Ruby 環境で Fabrication

ダミーデータがたくさん欲しい

自分の仕事場はちょっと変わっているのでダミーのテキストを用意するのはそれっぽい人に頼むと可能ではあるのですが、本来こんなものは機械に作らせればいいのです。とは言えわざわざダミーデータ生成ツールを作るのはダルいし、便利なものも知らなかったので今まではなんとなく人海戦術でやってました。ごめんなさい。

最近ちょっと Rails づいているので fixture replacement の文脈でいくつかデータ生成ツールを見ていた(試してないの多数)のですが、2010冬の段階では Fabrication の人気が上がってきているようですね。(まだ ruby-toolbox.com では名前を見ないけど。)

ということで使ってみた

paulelliott/fabrication - GitHub

まずはよく見る Faker と組み合わせる例。

※ なお、url の部分の処理は参考にした hibariya さんのコード丸パクリです。

気をつけるポイント

Rails 流の Model クラスを想定しているので、この場合は Company クラスのインスタンス変数に読み書きの権限を与えてください。

Fabricate.attributes_for() するなら Struct を使っても結果はまったく同じなので一つの手としてはアリかもしれません。

cf. Fabricationを使ってみた - のどをRubyでいっぱいにして

Faker の代わりに forgery を使う

sevenwire/forgery - GitHub

ruby-toolbox.com の Random Data Generation の項目 では faker よりも forgery の方が人気が高いようですので、こっちも試してみます。

上の Faker の例とまったく同じものを作ってみました。中身を見ると Faker よりもすぐ使えるものが多いからもしかして便利? Formats や Dictionaries が準備されているので Faker よりも作れるダミーデータの種類を増やしやすいのかもしれません。

cf. [sinatra for flasher] 大量のダミーデータを返すAPIを作る - func09

ちなみに今回のコードの全体像

こちら

gist: 748375 - fabrication with faker and forgery- GitHub

git clone して

$ ruby fab.rb -h

で分かりますが、

  • class の生成方法
  • fabrication と組み合わせるダミーデータ生成ライブラリ
  • fabrication で作るデータの形式

を選ぶことができます。

参考

ISO9660 の CD-R よりも UDF の CD-RW/DVD の方が互換性って高い?

詳しく調べたことがないんでアレなんだけど、日本語ファイル名を含むデータをクロスプラットフォームで、ネットワークではなく物理的な記録メディアでやりとりしようと思ったら UDF がいいんじゃないかって気がしてきた。

cf. MacintoshとWindowsファイル送信の掟 (MacとWinの共存)

ファイル名の長さの制限とか使える文字の制限は残るにせよ、それはネットワークを経由しようが同じことだしな。

MO の場合は Mac の側で Windows フォーマットに、Classic では 230MB まで、OSX では確認できた限りでは 640MB まで対応しているが、MO ってメディアが高いのでやっぱり「渡しっぱなし」にしにくいし、そもそもドライブを備えている機械が限られる。その点、CD/DVD はたいていの PC にドライブはついてるし、メディアも安いので気楽だ。

UDF は環境によって reader (ドライバとか機能拡張とか)が必要なのが問題っちゃ問題だけども。ヘタに UDF Bridge で焼いちゃうと ISO9660 互換になって逆に読めてほしい情報が欠落する可能性もあるしな。様々なプラットフォームで同じ情報を読み出せるという意味での互換性を重視するなら UDF のみの方がいいような気がする。

互換性の高いフォーマットであれば Switch の際に資産として活用しやすい。ちょっと時間があったら試してみるか。

最近 spam がすごいな

※ Web じゃなくてメールの方ね。

寝て起きたら 100通とか溜まってるんですけど、そんなもんなん? 1別に有名人じゃないんだけど、昔公開していたものがそのまま流通してたり、極一部には使用中のメールアドレスがそのまま載ってるものもあるから、そういう関係なのかなぁ。

メールアドレスとハンドルが直接結びつかないようにするとか、工夫しないとダメかしらん。でもアドレス変更は面倒くさいんだよねぇ〜。一応今はプロバイダのフィルタで弾いてから受信してるんだけど、なんかほとんど spam だけでメールボックス半分埋まってるし。どうなんだそれ。自分で受信してるメールの量は増えてないのに、メールボックスの埋まり具合がこの1年で倍くらいになってるような気がする。

あ。よく考えたら普通に受信するメールよりも spam の方が保存期間長いんだよな。そりゃおかしいわ。というわけで変更変更。よし、様子見してみよう。

  1. 昼間もそれなりにきてるので、1日200 - 300 くらいですか。2, 3年前にはせいぜい数十だったような気がするんだけど…。 

あ。そうか。MacIE 終了か。

Mactopia Japan : Internet Explorer 5 for Mac

2005 年 12 月 31 日をもちまして Internet Explorer 5.1.7 および Internet Explorer 5.2.3 の無償サポートを終了いたします。 詳細は、「無償サポートが終了する製品のお知らせ」をご覧ください。

まー未だに MacIE を使うような人はどうせこんなお知らせも各種ニュースもチェックしてないだろうし、Safari なんか使わないだろうから、Safari のシェアが伸びるようなこともそうないだろう。つーことは、まっくラブな人以外は基本的に Web 屋での影響はあんまりなさげ。(どうせまだしばらくは MacIE での動作確認はするに決まっている。)

卓上加湿器げと

決して過失機ではありません。

昨日、リニューアルオープンした電気屋を覗いてみて見つけた製品。卓上向けで場所も取らないし、3200円となかなか手頃だったので職場に導入。ブツは TIGERの ASM-A HW

北陸の冬は湿度が高いとよく言われるがどの建物のどの部屋も湿度が高いわけではない。エアコンや機密性などの関係で妙に乾燥しているところもあるのです。もう顔は突っ張るわ目は痛いわ大変だったのだけど、それがマイナスイオンの効果もあって、、、てのは今日はちょっと雨模様でよく分かりません。

明日以降も継続的に使ってるうちに何か気づくかも。

About

例によって個人のなんちゃらです