ネタからほんとに知らなかったことまでたくさん入ってて面白い。タイトルは 10 Things とあるけど、実際は「10個くらいは知らないことが含まれてると思うよ」という意味に近い。
Apple In-Ear headphonesのイヤーチップ(イヤーパッド?)を両方紛失した。ここ一ヶ月ほど、よく外れるようになっていたのでまずいなと思っていたものの、一気に両方無くなるとは思わなかった。
ネットで調べたらSONYの交換用イヤーチップが互換性があるという話だったが、昨日寄った店の店頭に並んでいなかったので、ダメ元でaudio-technicaのイヤーチップを買ってみたところ、問題なく使えた。純正品に比べると結構固くて嵌めづらいが、こちらのほうが外れにくくてよさそう。多少圧迫感を感じるが、自分にとっては問題になるほどでもない。純正品は3サイズ1セットしか販売していないそうなので、自分の欲しいサイズのものだけ買いたいという人はトライしてみる価値あり。
どうやって生成するんだろうと思っていたら、単に RoR のリポジトリを clone してきて rake rdoc するだけでした。
$ git clone https://github.com/rails/rails.git $ cd rails $ git checkout v3.2.2 $ bundle install $ bundle exec rake rdoc
前回までは Rails Best Practicesのスライドから引用していたが、それも終わったので今回からはオリジナルのコンテンツを書いていくことにする。
Railsでは元々Ruby本体に用意されている基本クラスを結構拡張している。これらを知ることでより効率良くプログラムをかけるようになる状況も多々ある。APIドキュメントから1クラスずつ紹介していくことにする。まず、今回はStringだ。
Railsで追加されているメソッドは、主にRails内部で多用される文字列の変換に関するものが多い。以下に利用頻度の高そうなものをピックアップしてみた。
classifyとcontantizeの組み合わせは、文字列からクラスを取得する場合に重宝する。たとえば、商品情報を含んだCSVを取り扱う例を考えてみよう。CSVは以下のような形式とする。
class, id, price Car, 40, 120000000 Bread, 50, 200 Phone, 15, 50000
このCSVを読み込み、それぞれclass列に指定されたクラスで該当するidのレコードの価格をアップデートするとき、rowという変数にハッシュで一行毎のデータが入っているとすれば、以下のようにすればclassの値にかかわらず同じコードで処理が出来る。
row[:class].classify.constantize.find(row[:id]).update_attribute(:price, row[:price]) # row[:class]が Phone であれば、 Phone.find(40).update_attribute(:price, 50000)と同じ。
実際にはこのように商品毎にクラスを定義することは無いと思うが、コントローラ等で文字列に応じてメソッドを送るクラスを変えたいケースは多々あると思うので、classify.constantizeの組み合わせは覚えて置いて損は無いと思う。
Rails Best Practices View more presentations from Wen-Tien Chang
84ページ以降にはビューのプラクティスが書かれている。
まず重要なのは、”Never Logic code in views”(ビューにロジックを書くな)という大前提である。モデルの中で完結するロジックはモデルに記述し、コントローラで処理すべきものはコントローラに書く。そして、ビューではそれぞれの値をどのように出力するかだけにフォーカスするようにする、ということである。
1の”Move code into controller”は非常にシンプルだが、Post.find(:all) をコントローラに移してビューは@postsの中身を表示するだけにしている。これは後々特定の部分をpartialに切り出すような場合を考慮しても、事前にロジックを排除しておくことが望ましいと言える。
2の”Move code into model”はモデルにロジックを記述するというもの。これはビューだけでなくコントローラでも言えることだが、ビューを書いていて表示のための条件分岐などを書きたくなることもよくある。その場合にはモデルでそれらの条件分岐をまとめるコードを書くのがいい。また、Cucumberなどを使ってBDDでoutside-in(シナリオを記述してからビュー、コントローラ、モデルとTDDで実装を進めていく方法)を取っている場合、ビューの段階でこのようにモデルにロジックを実装するように進めていくのが望ましい。
3の”Move code into helper”は、主にヘルパーメソッドを使って行うHTMLの生成で、必要なオプションを作る処理をヘルパー内部に記載するということを示している。ここでは、selectタグに引き渡すoptionsの情報を構築するメソッドをヘルパーに移動している。
これら3つのtipsで注意すべきは、モデル・コントローラ・ヘルパーのどこにコードを移すべきかである。基本的に、モデルだけで処理が完結するものはモデルに移動すべきであるといえよう。コントローラへコードを移すケースは、2つ以上のモデルを操作するコードか、paramsを利用したモデルの生成、sessionへの書き込みを扱うコードになるだろう。ヘルパーへコードを移動する場合は上述のようにHTML生成に関する場合が中心になるが、例に出ているcurrent_userのようにモデルを生成するものであってもシンプルで、かつ頻繁にビューで用いられるものも含まれてくるだろう。
これらのtipsは単にシステム内で2カ所以上で重複するコードをまとめる際にも有用だが、できればビューにロジックを書き始めず、最初からモデルやコントローラでロジックをまとめるようにコーディングできれば、結果的にそれぞれの再利用性が向上してコーディングの時間を削減することにもなるだろう。
4の”Replace instance variable with local variable”は、ビュー内部でのコードの移動であるといえる。一部のビューをpartialに切り出す場合、インスタンス変数を参照していたコードがあれば、それをローカル変数を参照するように書き換え、renderメソッドで:localsの形で引き渡すように変更しようというtips。こうすることによって、partialの再利用性が高まる。
最後の”Use form builder”は、ヘルパーへのコード移動に近いと言える。複数のフォームで共通する構成を持っている場合、それらをFormBuilderとしてまとめてビューでの記述をよりシンプルにする方法だ。この例では、text_fieldとtext_areaのそれぞれでlabel_tagを記述していた部分をMyFormBuilderの内側でそれぞれtext_fieldとtext_areaを呼び出せばオプションの値を利用してlabelも付与するようにしている。
このアプローチは、デザインガイドラインが完備されていて、かつプログラマだけがビューを操作するのであれば非常に使い勝手が良いのだが、アプリケーションがまだ急成長している段階でCSSにも変更が多発する状況だと、デザイナとの協働が行いづらいこともある。特にerbを直接編集できるデザイナがいるのであれば、ガイドラインが落ち着くまでは無理にカスタムのFormBuilderを使う必要はないとも思う。これはpartialとしてビューを一部切り出すときも悩む問題であるが、これはサービス全体を見渡してラフスケッチやサンプルのデザイン、及び仕様書にある情報から「partialとして切り出して再利用することができるものか」というのを推測しつつ進めていくしかないだろう。
Rails Best Practices View more presentations from Wen-Tien Chang
コントローラ内で重複するコードで、特に各アクション実行時に必要なモデルを用意するような場合はbefore_filterを使ってコードを集約しよう、というのがこのTipsである。ここではcurrent_user.posts.find を呼び出している箇所をfind_postというメソッドにまとめ、before_filterで指定している。このようなコードはrails3にて
$ script/rails g resources User
などとした場合に各アクションに記載されていることが多い。同じことを行っているコードであれば、1カ所に集約するほうがコード全体の見通しもよくなるため、積極的に使いたいtipsである。ただ、新たにアクションを追加したときにbefore_filterでそのアクションを新たに指定しなくてはいけないのを忘れて「なぜ動かない!」と頭を悩ませやすいこともあることには注意を。
ここではbefore_filterで :only を使っているが、反対に:except も使える。また、skip_before_filterも併せて使われることが多い。詳細は ActionController::Filters::ClassMethodsを参照して欲しい。
Rails Best Practices View more presentations from Wen-Tien Chang
「とにかく必要なものには全部インデックスを張れ」というのがこのTipsである。インデックスとはなにか、というのはRDBMSの知識になるので詳細は触れないが、Railsでモデルを作成してマイグレーションファイルで作業をする場合、どこにインデックスを貼るかは以下のように考えれば大きく間違うことはないだろう。
一番いいのはきちんと必要性を理解した上でインデックスを張ることだが、よくわからなければとりあえず一通りインデックスは貼っておくほうがいいかもしれない。
以前から気になっていた3Mゴールドプライバシーフィルター(以下GPFと呼ぶ)を購入した。電車や喫茶店等、他人に横から作業内容を見られるというのは、なんとなく微妙な気分というだけでなく、場合によってはクライアントの重要情報が映ることもあるので避けるべき事態。そのため、以前からプライバシーフィルタはよく使っていたものの、このゴールドプライバシーフィルターを一度使ってみたいと思っていた。だが、Macbook Proだとモアレがひどくて使えないという海外情報があり、購入前に試してみてからでないと不安だなと思っていた。
今週アキバヨドバシに行く用事があり、偶然以前から気になっていた3Mのゴールドプライバシーフィルターを発見。、員さんにテストしてみたいと確認したところ、売り場で値札の隣に貼ってある小さく切り取られたサンプル品を使ってチェックさせてくれた。これぞ実店舗の強み。気になるモアレは、この前に使っていた同じく3Mのセキュリティ/プライバシーフィルター スタンダードタイプ(以下、SPFと呼ぶ)に比べてむしろ軽減されているくらいだったので、即購入を決めた。MBA13インチなら、13.3Wサイズのものがフィットする。
数日使ってみた感想だが、GPFはSPFに比べて光の透過率がやや高いようで、高度に関する不満は少ない。モアレもSPFだと「みづらいな」と思うことがあったが、店頭でチェックしたとき同様、GPFはそれよりもモアレが少なく、快適である。そして何より、視野角の外から見た場合のフィルタの見え方がすごい。ゴールドと銘打っているだけあり、ピカピカに反射する。SPFの場合は視野角を外れると、徐々に暗くなって最終的に見えなくなるという感じであったが、GPFの場合は光が反射して見えるのを防ぐという印象が強い。
だが、GPFではSPFにはなかった映り込みがある。正面で作業していても、鏡のようにこちら側を映してしまう。試してはいないが、自分の背中側で照明が明るい場所や、屋外で使用するのはもしかしたら難しいのかもしれない。
プライバシーフィルタは探してみると視野角や光の透過率など考慮する項目も多く、かつ液晶ディスプレイとの相性、そして見えやすさに関する個人の嗜好なども入ってくるため、選び方が難しい。作業を行う環境によってもそれぞれの製品で得手不得手が変わってくる。最終的にはある程度の目処を付けた上で思い切って買うしかないのが実情だが、今回のヨドバシカメラのようにファーストインプレッションだけでも実機でテストできる店舗があれば、そちらで試して購入するのがいいだろう。
Rails Best Practices View more presentations from Wen-Tien Chang
このTipsはmigrationでシステムに必要となるデータを生成するのはやめてseeds.rbを使おうというもの。seeds.rbは 2.3.4 から導入されているため、それ以前ではこういったやり方をしている事例が多かったということを示している。
ところが、seeds.rbに入れればいいといっても運用開始後のサービスではそう簡単にもいかない。たしかにサービスを立ち上げるときはseeds.rbでほぼデータが固定的なテーブルについてはデータを入れておくことはできる。だが、運用が開始されてから rake db:seed を走らせるというのは難しいケースが多いだろう。そのため、自分はデータを生成する専用のモジュールを作っておき、実際のメソッドはシーズ用メソッドの中に記述し、それをseeds.rbから呼び出すようにしている。
# lib/myservice/seeds.rb
module Myservice::Seeds
def self.roles
%w(admin author editor account).each do |name|
Role.create!(:name => name)
end
end
end
# db/seeds.rb
Myservice::Seeds.roles
このように記述するといくつかのメリットがある。
最初は簡単な内容だけで済むseeds.rbが、そのうちいろいろと多くのことをやろうとするようになるケースが多いので、最初から分割していく方向で考えると後からかける手間が減るだろう。