もっとControllerから分離してtestableに

関心

Rails の Controller にメソッドを生やすとテストしにくい。できるだけ分けたい。1

とりあえず思いついてたり実現できていたりすることをメモ。

Controllerの基本

まずは概念の整理から。

のうえで、どうしても Rails で残りがちなものが以下かなという気がしている。これらをどうバラすかのメモ。

※ Strong Parameters についてもいたずらに private メソッドが増えるのはよくないと感じていて、そもそも dry-validation など代替の手法があるが、validation の話はそれだけでそれなりに大きいので今回は除外。

before_actionをバラしたい

  • 副作用アリなら module へバラして mixin
    • 関連するメソッド群を一つの module に固めておく
    • 極力 controller に依存する処理を集約して単独でテストできる部分を増やすように
    • controller に依存する部分は普通に適当な controller にincludeして書けばよい
  • 副作用ナシで request を叩き落とすだけなら constraint へ

rescue_fromをバラしたい

  • V, Cのいずれにも依存しない副作用は C で rescue せずにRack middleware へ逃す
    • ActiveRecord 周りとか
  • View の layout や content に依存しない response も Rack middleware で可能

rescue_fromをclassでバラすこともできるけど

rescue_from をできるだけ testable にするために constraint のように独立した class にできないかと試行錯誤したが、できることはできるけど、あんまりメリットない気がする。せっかくなので一応書き出しておくけど。

rescue_from には block か Method オブジェクトに変換できる Symbol しか与えることができない。後者も最終的には Proc オブジェクトになるので、結局 Proc オブジェクトしか与えることができない。これはコードを追うと中で class を見て場合分けしているので避けようがない。そこで以下のような class を作ったとしても、

class Handler
  def call(exception)
  end
end

実際には以下のように Proc オブジェクトに変換して with に与える必要がある。

rescue_from Exception, with: Handler.new.method(:call).to_proc

だいぶおおげさではあるが、よほど複雑な処理をするのであればこういう書き方も可能。ただし、self が合わないのでそのままでは実行時の controller の中の値にはタッチできない。「そのままでは」がキモで、ちゃんと辿れば可能。

exception.bindings.first.receiver

とやれば実際に rescue した controller インスタンスが取得できるので、ここから request オブジェクトなどを参照できる。

まぁなかなかこんな方法使わないかなぁという気もするが、Exception Handler を class ベースにして(例えば特別なログを出力する、何らかのレポートサービスに通知するなど)継承したい実装を用意しておくというのは一つの手法としてアリかもしれない。単に rescue しただけで片付けてしまうと事実が消えてしまうが、その記録を毎度毎度ゼロから書くのもバカバカしいので。

  1. Rails は 1 Action : 1 Method になるのである程度以上の複雑さを持った場合に安易に private メソッドが増えやすい。private メソッドはテストしにくいので悪。Hanami 方式なら 1 Action : 1 Class なのでいいんだけど。 

なんかプレゼント当たったよ

Tシャツにサンダルという極めてラフなカッコで電車に4時間乗って行ったオレ様の LLSpirit の感想ですよ。(TrackBackセンターってないみたいね。)ボール投げのプレゼントに当たったのですが、このプレゼントは正直「仕事しろ」と言われているようで若干複雑な気分ですよ。

当日の神保町はですね、やはり何百人とそっち系の人がいるので「そういうオーラ」が漂ってましたね。なんつーか一人一人は別にそこら辺にいても何の違和感もないんでしょうけど、集まるとやはり何か独特のものが生まれます。というか会場で明らかに発表とは関係のないコードをいじっている人がチラホラいるのはなんだろうと思った。いやまぁ、自分も機械が軽くてバッテリが保つなら同じことやったと思うけどね。

以下、発表の内容も踏まえつつ感想など。

  • 和田先生の話を聞いて歯車重要って思った。つか歯車って面白いな。
  • Perl 5.10 機能増えすぎ
  • 予想通り DoCoMo 2.0 系のプレゼンあり。Ruby の 2.0 は出ません。「もしかして機能」も載りません。
  • PHP の人ぶっちゃけすぎ。Python とのギャップがすごすぎ。ちょっと Python ステキ。
  • Xtal の人の喋りがヒットしまくり。「あとは FizzBuzz です。」ってまぁそうなんだけど。
  • なでしこの人は大人だなぁ。そして質問をした Dan の中の人の「はぁ〜〜」っていう感嘆に大爆笑。なでしこすげぇ。

VM の話はどうせ分からないからと中抜けしてホテルへチェックイン。

  • amachang て本当にあのスタイルで生きている人なんだ。そこに感心。(別に悪い意味はどこにもないです。)
  • S6(仮)の、ページ内のどこでもプレゼンにできる機能とインデックスの機能はかなりステキ。
  • Gauche の人の発想がビックリ。vnc を使ってみたかった、スライドは画像で適当に作れ、という割り切り方にビックリ。Dynamic サイコー。
  • プレゼンは紙芝居形式でなくてよいのではないかという会場からの指摘は個人的には的外れな感じがした。見せる内容や会場をあまり選ばずに汎用に使える方式はそれほど多くないと思う。
    • てなことを書いていたら種明かしが。んーいずれにせよかなり利用シーンが限定されると思うし、それ「プレゼンツール」や「プレゼン」である必要ないんじゃ1
  • 効果がスライドの中にコードっぽく入ってしまうのはどうだろう、というのは自分も思った。XML にした Ocaml版はオーサリングツールでフォローというスタイルでうまくハマりそうだけど、オーサリングも含めてプレゼンだよなぁという気もする。
  • そう思うと実はオーサリングも発表も楽な高橋メソッドというのはやはりすごい。
  • モテと非モテの夢のコラボ希望。
  • otsune の中の人のチャットツッコミはやはり才能だと思った

※ 当日会場で見かけた、とびきりイヤなオーラを発していた長髪の人はもしや otsune の中の人じゃないよなぁ…。なんつーか、LLSpirit でヒソカを見た気がした。

  • テンプレートエンジンはまた新しくなったらしい
    • Kwartz はもうやめたのかな
  • イメージファイトのプレゼンすげぇ
    • スライドの見た目をもう少し見やすく作ってくれると文句なくサイキョーです
  • XBYAK すごすぎ

サイボウズ・ラボの人が多いなぁ。

その後は知ってる人もいないので、東京の知り合いと合流して飲んで寝ました。

楽しかったよ。また何かの機会に参加できればいいなと思います。

  1. 例えば時間軸をいじるのは面白いけど、オーディエンスが同じ時間を共有しないのであれば、爆笑や拍手の瞬間も共有できなくなってしまう。そんな「ライブ」面白くないYO! ツールそのものやアイディアは否定しないけど、なんかメディアアートの世界に入りつつあるような気がする。 

ロイターのフィードがなかなかよい感じ

通常のニュースのフィードっていいのないなぁとずっと思ってたんだけど、ロイター通信のものがよさげ。

  • ちょっとだけど本文が入ってる
  • HTML のページもそれなりに読みやすい

辺りがポイント高し。

ずっと asahi.com だったんだけど本文ないし、だいたいフィード出してるサイトって少ないし、以前は自分で探したりしたけど最近はもう auto-discovery に Firefox が反応しないとないものとみなしちゃうんで、あるんだかどうだかがそもそも「分からない」。フィード生成サービスを使ったフィードもあんまり使いやすくないし1、何より毎日インタラクティブ始め、なんであんなに見にくいのか。ニュースを読みにサイトを訪れることすら苦痛だ。

ということでロイター通信いいですよ。編集方針が日本のメディアと違うところもまたおかし。地元のニュースにさっぱり弱くなってしまうがそれは以前からだから気にすまい。

  1. Google ニュースのフィードは一瞬でサービス停止しちゃうし。 

diigo にしてみた

あんまり新しいものに飛びつかない方なんだけど、del.icio.us は日本語検索がちょっと使いものにならないし、かといって偏りまくったはてなを使う気にもならないので何やら評判の diigo にしてみた。

結論から言うと機能が多くてよく分からないというのが正直なところなんだけど、日本語検索はおろか、ブックマークしたページをキャッシュしてくれてそのキャッシュの全文検索までできるのは非常に助かる。要するに diigo にブックマークさえしておけば、「あーその話どこかで見たな」というものを探しやすくしてくれる。

同じことは Plagger + Gmail とかでもできるんだけど、自分で何一つ工夫することなく実現可能なところが怠惰な人間にはサイコー。

あとはドラッグしてハイライトさせた文言を記憶してくれるとか、あれだな前から欲しい欲しいと言っていた既存のサイトに対する Web 付箋がキタっていうかそんな感じ。

blog もついてるのでこれだけでメモ関係は集約できるかもしんない。ただしフィードリーダーはついてないけど。

個人的にはツールバーは場所取っていやだな。del.icio.us はブックマークレット + extension でメニュー追加、というスタイルだったのでツールバー周りを比較的すっきりさせられるのがよい。サイト全体も diigo の方が情報量が多く、エフェクトもあれこれあって、ちょっとうざい。でも検索の便利さがあるから戻れそうにないな、こりゃ。

あ。

げげげげ。

タグ入力時に補完が効かなくない? えええええええ。そんな不便すぎる。

あ。違うこれ。ツールバーやめた。Diigolet にすればいいんだ。そしたら補完も効くし場所も取らない。あーこれはいいぞ。ブックマークの編集の際にはやっぱり補完が効かないけど、これはブックマークレットでできてるんだから本体の方でできないわけがない。いずれその機能も入るものとみなす。まぁでも操作感はやっぱ del.icio.us の方がいいな。

[2006-10 追記]ずっと感じていたことですが、どうも補完用のデータを取得して実際に補完が効き始めるまでの時間が、del.icio.us より Diigo の方がかなり長いようです。だからだいたいは待っていれば補完が効くようになりますが、確実に効くようになるかというとよく分からないというのが実際のところ。あと補完のための処理が Diigo は重たい。効いたら効いたで邪魔くさい。日本語の全文検索のためとは言え、どうにかならんかこれ。

Jcode.pm 2.0 って出てたのね

ports が上がってたんで気がついた。

ChangeLog から。

2.00 2005/05/16 19:07:51
! Jcode.pm
  2.00 released ex officio!

Perl 5.8.1 以降では Encode の wrapper として働き、バイナリのインストールが不要になったと。しょぼいレンタルスペースでも Jcode.pm を使えるようになったという解釈で合ってるのかな? Perl 4 時代のノウハウで jcode.pl バリバリの CGI なんかを書いている人が Perl 5 で Unicode の恩恵に与りやすくなったとも言えるか。jcode.pl + simaguni.pl → Jcode.pm の動きは起きるか?

在野 Perl/CGI プログラマの間での今の主流がなんなのか、知らないんだけど。

復旧の歩みは遅く

とりあえず退避先のディスクを昼休みに買いに出るが 5400rpm のものが品切れ。うーん。廃熱の問題を疑っているのに速いディスクにしてどうする。

ということで昼間一切作業できず。夜改めて買いに出て今動いているのとまったく同型のディスクを購入。別に同じものにしたかったわけじゃないが、たまたま同じ条件(容量は別に大きくなくてよく、スピードは 5400rpm で流体軸受け)にしたら同じディスクが網に引っかかっただけ。1年半ほど経っているが、40GB なんて今となっちゃ小容量の HDD の置かれている状況はほとんど変化がないんだろう。

で、ケースが窮屈なのでスリムケーブルも購入。実際組んでみたら少し長いorz まぁ短いよりは断然いいのですが。組み上げて FreeSBIE で Go! と思ったら立ち上がらねーでやんの。仕方ないので KNOPPIX で起動。フツーに立ち上がる。

何も考えずに dd で2つのディスク間でデータをコピーしてみる。Input/output error がやはり起きる。ということはだ。

2002/11/07 自宅(1) 「復活の日: FreeBSD ディスククラッシュ事件総括」

で読むような感じでエラーを無視してコピーするオプションを使わなきゃいけないんだなーということ、このエラーは単に filesystem の不整合というレベルじゃないんだなぁということと、この先はちょっと時間掛かりそうだなぁということが分かる。(転送速度が 2.5MB/s しか出てないのも分かる。)

分かったところで帰る。くそ。明日は早くからやろう。

About

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

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm