Thursday 20 December 2012

iOS 6 のSafariでファイル画像アップロードができることを知りました

いくつか調べ物をしていてiOS 6 のSafariでファイル画像アップロードができることをやっと知りました。これで responsive なサイトを作る敷居は一つ下がった様に感じます。

これまでiOSで画像アップロードができないためだけにモバイルアプリを制作していた会社も少なくないのではないかと思うと、仕様変更がちょっとあるだけでいままでの努力がなんだったんだと泣き寝入りをせざるを得ないのはちょっと儚さを感じます…。

Wednesday 19 December 2012

私は16歳で高校を卒業してプログラムをしています。就職過程に一石

これは私本人の話ではないのですが、最近こんな人の記事を読みました。

http://jarredsumner.com/

私は16歳で高校を卒業してプログラムをしています。

履歴書を会社に送るよりも会社の人たちが来ていそうなミートアップイベントに参加して人と直接話しをしたよっていう話を書いています。

こんな投稿でも、100社に履歴書を送って面接で断られまくってという無意味な精神修行過程をもっと有意義な過程に昇華する一石になればと思います。

以下本人のサイトから抜粋です。

If you’re an engineer, go to meetups hosted or attended by employees of the company you want to work for. In the Bay Area, there’s SFRuby, AirBnB Tech Talks, GitHub Drinkups, and numerous more. Usually, several technical recruiters attend who really want to hire engineers. Talk to them as a human being, and they’ll treat you like one.

Tuesday 18 December 2012

Riak link syntax

key-valueストアのRiakではREST APIを標準で提供していますが、そのリンクを辿るには次のようにcurlなどでクエリを出します。

http://localhost:8091/riak/bucket/key/bucket,key,keep

例えばスパゲッティーペペロンチーノのレシピを書いてその写真をアップロードしたとすると、

http://localhost:8091/riak/recipes/spaghetti-peperoncino/photos,_,0

でリンクした写真のリストを見れます。最後のkeepのフラッグは写真の情報だけを見たいときは0にして、写真にたどり着くまでの過程にあったオブジェクトのデータも取得したいときは1にします。

Monday 17 December 2012

Ruby CI tools

最近一度プルリクエストをしたGitHubのコードに問題がある事が分かりました。多分自分が書いたコードではなくて依存しているgemが使っているAPIの仕様が変わったのではないかと思います。テストを書く事を提案してみようかどうか、どこまでプロジェクトにコミットするのかなど判断にまだ迷っています。

そんな視点を持ちつつなんとはなしにSlimのGithubレポジトリを眺めていると、Travis CI以外にも二つコードの状態を示していそうなバッジがついていました。少し調べてみると、一つは異存しているgemの状態をチェックするGemnasiumというツールでした。もう一つはCode ClimateというクラスファイルごとにCode Smellなどの観点からコードの健全性を見せてくれるツールでした。

目先、GemnasiumとTravis CIがとても使えそうですが、そもそもどこまでコミットできるかという判断が解決していないですね…。

Saturday 15 December 2012

Mongoidを使ってRSpecでテストした時にFactoryGirlでバリデーションエラーが無くならない

Mongoidを使ってアプリケーションを作っていて、RSpecでテストした時にFactoryGirlでバリデーションエラーが無くならないという事がありました。

一時的にtestの環境ではヴァリデーションをスキップするという方法でしのいでいたのですが、実はspec_helperにDBのコレクションをbefore(:each)のタイミングでドロップするという設定が必要だという事でした。これを実行してみると、問題無くバリデーションエラーがとれました。mongoid-rspecのドキュメンテーションにもこんな事は書いていなかったと思うし、ドキュメントの読み方が悪いのでしょうか…。

http://adventuresincoding.com/2012/05/how-to-configure-cucumber-and-rspec-to-work-with-mongoid-30

database_clearnerのgemを導入したタイミングのどこかで自動でテストの時にデータベースのコレクションを削除してくれるスクリプトも導入されるのかと思ったらそんなことは無い様ですね…。

プログラミング関連書籍譲ります



読み終わった書籍を交換するBookMoochというサービスを暫く利用しているのですが、数冊プログラミングに関わる書籍を加えておきました。興味のある方は"BookMooch request"をもらえれば送ります。

http://bookmooch.com/m/inventory/taro

Friday 14 December 2012

Ruby on Rails AntiPatterns (3) このシリーズはこれで終わりです

Saleh, T.とPytel, C.著の"Rails AntiPattern"から幾つか私が参考になった箇所を少しずつ書いていきます。

AntiPattern: 何故かデータベースに保存されていない…

これは最近暫く悩んだ問題です。MongoDBをMongoidを使っていたのですが、モデルのバリデーションのところで

validates_uniqueness_of :product_number, allow_nil: true

としていたのですが、モデルのインスタンスを新規保存・更新するとエラーも出ないのに、何故かDBのデータが更新されません???。暫く迷っているうちにふとindexの時に

index( {model_number: 1}, {unique: true} )

と書いた事に思い当たりました。DBがロールバックした事実をmongoidの方でユーザに報せる機構が内容です。ActiveRecordでもDBのレベルでの一意性のチェックなどはしないのが良いプラクティスだそうです。SQLデータベースでもこの辺りの実装は異なるらしいので互換性の実装が難しいのでしょうね。それとももっと他の所に問題があるのでしょうか。もっとDBの実装を理解しないと問題の本質が分からないです(残念ですが)。MongoDBでも例えばクラウドサービスのMongoHQなどでは若干仕様を変えている可能性はありますね…。

AntiPattern: アセットをアプリケーションサーバのファイルシステムに保存する

例えばユーザがアップロードした画像や音楽などのファイルをアプリケーションサーバのファイルシステムに保存すると、サーバ移行やデプロイの際に無駄に作業が増えてしまうことが多い様です。
クラウドのファイルストレージサービスが推奨されています。現時点で代表的なサービスはS3ですね。

AntiPattern: テストされていないrake tasks

rakeのタスクはプロジェクトルートでrake spec raketasksなどとしてテストを走らせる事ができないため、テストでカバーされない事が多い様です。

これはモデルにコードを記述して、

class Post < ActiveRecord::Base
  def send_summary_report_to_admin
    ### Here comes actual codes...
  end
end

rake taskには

namespace :send_summary_report_to_admin
  task search: :environment do
    Post.send_summary_report_to_admin
  end
end

と記述すると、他のモデルと同じようにrake spec:models でテストできます。

ちなみにAntiPatternではないですが、他の人が書いたライブラリを利用する際は下の事を参照にすると良いとの事です。
T: Test  テストでカバーされているか?
A: Activity ユーザに使われているか?
M: Maturity 実際にある程度の期間動いているか?
テストでカバーされていないライブラリにはテストを書くという貢献の仕方もOSSの世界なのであり得るそうですが、人が作ったコードにテストを書くという行為はちょっと勇気が要りますね。メンテナンスの責任も勿論大きくなりますし…。実際ある文献によるとプログラミングの50%はメンテナンスに割かれているそうです。

テストはできるだけ自分で書いた全ての行をカバーするべきである、それができない時は最低限ブロックのレベルでテストを書くべきだという基準を耳にします。責任のあるコードを書くのは大変ですね。例としてmongoidのコードを見てみると、実際のコードとテストコードの割合は約2:1。大体これぐらいが良いプラクティスの目安なのでしょうか…?

ちなみにちなみにネットワークのレスポンスはFakeWebというgemで、ファイル読み書きはFileUtils::NoWriteでモック・スタッブできるそうなので、ここにもテストを書かない口実は無さそうです…。

AntiPattern: レスポンスが200OKなのにbodyはエラーですと言っている…

これはHTTP APIを提供しない限り許されるのかもしれませんが、レスポンスコート200を返しながら.jsonのレスポンスは

{
  "error": {
    "message": できません
  }
}

などとなっているのはAPIのコンシューマとしては不便です。レスポンスコードはW3のサイトに記載されています。ざくっと見たらコードの数はそんなに多くないので、対応するのは難しくなさそうです。

HTTPステータスコードはコントローラで下のように返します。

respond_to |format|
  format.json {
    render json: @post.errors, status: :unprocessable_entity
  }
end

RailsでのHTTPレスポンスコードとシンボルのマッピングは下のサイトにあります。

http://www.codyfauser.com/2008/7/4/rails-http-status-code-to-symbol-mapping

AntiPattern: respond_to do |format| x 3 x methods.count

コントローラのメソッド毎にそれぞれhtmlとxmlとjsonでのレスポンスの挙動が書かれていています。Rails3で導入されたresponderを使えば例えばindexは

def index
  @posts = Post.all
  respond_to do |format|
    format.html
    format.xml { render xml: @posts}
  end
end



def index
  @posts = Post.all
  respond_with(@posts)
end

と書けるそうです。

何故scaffoldでもこちらの方法でコードを生成しないのかは少し不思議です。確かにこのメソッドを使うとコントローラのコードを見ただけではxmlでサービスを提供しているのか、jsonのレスポンスも生成されるのか分からないですね。これは必要に応じて使い分けでしょうか。ウェブアプリケーションの中で統一してしまって、全てのレスポンスはxmlとjsonで返すというような指針を決めてしまえばresponderを使った方が無駄が無いかもしれないですね。

Thursday 13 December 2012

iPad (3rd Generation) WiFi model needs a new owner

The iPad has been sold. Thank you for your interestes.

An iPad needs a new owner for 35,000 yen.

The iPad is 3rd Generation WiFi model (no mobile phone network), with Retina Display, 64 GB storage capacity, Apple Care+ covered until April 2014.

I have used the iPad always with Belkin's case, thus I see very little scratch.

You can find more information on Apple's website:

Preferably I would like to hand over the iPad in person, but I can also ship it to a remote location (within Japan).

Let me know if you have questions.

My contact details are

Taro Murao
phone: 090-1951-6892
email: taro.murao@gmail.com



Ruby on Rails AntiPatterns (2)

Saleh, T.とPytel, C.著の"Rails AntiPattern"から幾つか私が参考になった箇所を少しずつ書いていきます。

AntiPattern: RESTfulでないアプリケーション

状況が許す限りscaffoldの状態に近いルーティングに保つのが良いプラクティスの様です。

デフォルトのCRUDにコントローラのメソッドを追加する際にも例えばconfig/routes.rbの中で

resources :orders do
  collection do
    post :shipping
    post :billing
  end
end

とすると下のようなパスが作成されます。

/orders/new
/orders/shipping
/orders/billing
/orders/1

これを書き直して

resources :orders do
  members do
    post :shipping
    post :billing
  end
end

とすると下のようにもっとRESTfulな下のようなパスをつくってくれます。

/orders/new
/orders/1/shipping
/orders/1/billing

私も以前に作ったショッピングカートのルートをリファクタリングしないと駄目です…。

AntiPattern: 何故か500ページが表示される

ユーザがボタンをクリックして何故か知らないけど500ページが表示されたり、トップページにリダイレクトされてエラーメッセージも表示されないなどのサイトが多いらしいです(耳が痛い…)。
ユーザとアプリケーションの信頼を確保するために正確なエラー表示が必要です。サーバサイドのエラーは管理者に報告して、ユーザサイドのエラー(例えばメールアドレスが違うなど)はユーザにその旨を伝えると同時に、New Relicなどのログシステムを使って管理者に随時報告するのが筋な様です。
エラーをキャッチする際にもメソッドにエラーの際はnilを返すようにして do_this rescue nilとするのは無責任なので、メソッドの中で的確なエラーをキャッチして報告する仕組みにする必要があります。
例えばメールを送信する場合はまず

config.action_mailer.raise_delivery_errors = true

にします。

Net::HTTPでは下のようにエラーが下のように定義されている様なので、

SMTP_SERVER_ERRORS = [TimeoutError,
  IOError,
  Net::SMTPUnknownError,
  Net::SMTPServerBusy,
  Net::SMTPAuthenticationError]

SMTP_CLIENT_ERRORS = [Net::SMTPFatalError,
  Net::SMTPSyntaxError]

管理者のログシステムとしてHoptoadを使用した場合、コントローラでは

と書く事ができるらしいです。

なんでもかんでもbegin/rescueしたら良い訳でも無く、例えばメールアドレスの誤入力など例外ではなく、通常の行動として予想できる内容はActiveRecordのバリデーション機能などを使用してレスポンスを返すのが的確な挙動です。

AntiPattern: 長いレスポンス待ち

問題の一つは、外部サービスを使っている場合(例えば外部サーバのSMTPを使ってメールを送信する場合)サーバからのレスポンスが遅い場合があります。デフォルトではNet::HTTPのタイムアウトは30秒に設定されているそうですが、これを3秒に設定するという対処方法があります。
もう一つの問題としては、大きなプロセスの仕事があります。この場合、対処方法の一つとしてはプロセスをキューに押し込んでしまい、バックグラウンドで仕事をしてもらい順々にこなしてもらうというものです。ライブラリとしてはdelayed_jobというのとRescueというgemがあるそうです。delayed_jobはSQLを、RescueはRedisを使ってキューを管理するそうです。
ちなみにeventmachineなどconcurrencyライブラリもありますが、大きな仕事の場合は同時にさばく意味が少ないので、外部APIから情報を引っ張ってくるなど待ち時間が発生して処理に時間がかかる仕事と、プロセスの処理自体に計算の時間がかかるなどの仕事はそれぞれ異なるストラテジーでさばく必要がある様ですね。


Wednesday 12 December 2012

Ruby on Rails AntiPatterns (1)

Saleh, T.とPytel, C.著の"Rails AntiPattern"から幾つか私が参考になった箇所を少しずつ書いていきます。

AntiPattern: Fat Models

"Fat Model, Skinny Controller"という言葉は聞きますが、too fat modelはそもそもコードが読めなくなるし、Railsのパターン以前にOOPやもっと足下の理念から外れてしまいます。

クラスを分ける、モジュールを使う、callbackを使うなどORM自体で搭載されている機能は使用するという解決策を。

AntiPattern: ながーいSQLチェーン

例えば人気のある記事トップ10を引っ張って来る時にコントローラの中で、

@posts = Post.where(status: "published", order: "number_visited DESC").limit(10)

とするよりも

モデルの中で

class Post

  scope :tops, where(status: "published", order: "number_visited DESC").limit(10)

end

とすれば

@posts = Post.tops

だけですみます。これはテストを書く際にも

before(:each)
  published_posts = create(:posts)
  Post.stub(:where){published_posts}
  tops_posts = published_posts.take(10)
  published_posts.stub(:limit).with(10) {top_posts}
end

などというスタッブ・モックチェーンを書かなくても済みます。テストを書く際にメソッドチェーンはしんどい…。"Don't ask codes but tell what to do."というような言葉もありましたが、やはりTDDのプラクティスをうまく実行すればしんどいコードを書かなくても済みそうですね。

AntiPattern: 入り組んだユーザ権限処理(authorization)

authorizationの実装を下の様にするケースが多いそうです。

こうやっていくとだんだんとスパゲッティーになっていくので、こういう書き方は一切辞めて下のように is_guest? is_manager?  などと役割役割の名前でauthorizationを実装します。また、役割もデータベースに保存しないでコンスタントとしてハードコードしてしまいます。

多くの場合、役割をデータベーすに保存するのはメリットが少ないそうです。

Monday 10 December 2012

ActiveRecord #count, #length, #size

データベースのクエリを使ってできる事はRubyで書かないのが一つのパフォーマンスを向上するキーになるのは当然ですが、勿論それにはデータベースのクエリやORMのコマンドを知らないといけないですね。

limit(num)などは明らかにORMっぽいコマンドなので分かりやすいのですが、最近になってようやくORM使用の際の#count, #length, #sizeの相違についての記事を読みました。結論でActiveRecordでは#countはSQLでCOUNTを出します。#lengthはSQLでは処理されないので、一度配列としてデータを取ってきてRubyとして配列の長さを数えます。#sizeについては、既に配列としてデータを取ってきているオブジェクトに対しては配列の長さを返し、まだクエリのProcで残っているものに対してはCOUNTを発効してくれる便利な関数です。

こういう事を知らないでいつの間にか無駄なデータ転送を強いるコマンドを闇雲に走らせている可能性は冷や汗ですね…。

ちなみに私が最近メインで使っているmongoidでも#countはMongoDBのcountを発効してくれ様です。

Saturday 8 December 2012

Ruby on Rails 人の失敗から学ぶ

私の経験としては失敗からは学ぶ事がとても多い様に感じます。自分で失敗すると印象が強く残るからでしょうか?でも人の失敗を観察する機会でも学びが多い様に感じます。これは自分の失敗と人の失敗を重ね合わせるというプロセスを勝手に頭の中でしているのでしょうか?

Saleh, T & Pytel, C著 "Rails AntiPattern"という本を読みました。興味深く、おもしろく、苦い内容でした。

デザインパターンの書籍は見る機会が多いのですが、AntiPatternというのは面白く感じました。成功例を並べられても正直面白くないですが、人の失敗を例に挙げて解説してくれるのはとても興味深く面白く感じました。

少しずつ学んだ事を記事に書いてはいきたいと思います。

Friday 7 December 2012

Ruby Array#each_sliceメソッド

配列を4つごとに区切った後で更にその4つを.eachで繰り返したいということは多くあるのではないでしょうか?

RoRでの実装はeach_sliceを使ってこうしました(slimを使ったviewのテンプレートです)。

- @products.each_slice(4) do |products|
  ul
    - products.each do |product|
      li= product.name

これで

ul
  li
  li
  li
  li

ul
  li
  li
  li
  li

ul
  li
  li

と続くHTMLを作れます。

Wednesday 5 December 2012

Array#eachでまとめてメソッド定義

例えばユーザ認証で

class User
  ROLES = %w(contributor manager admin)

  attr_accessor :role

  def is_contributor?
    self.role == "contributor"
  end

  def is_manager?
    self.role == "manager"
  end

  def is_admin
    self.role == "admin"
  end
end

user = User.new

user.role = "contributor"

user.is_admin? #--> false

user.is_contributor? #--> true


というコードを簡略にして

class User
  ROLES = %w(contributor manager admin)

  attr_accessor :role

  ROLES.each do |role|
    define_method "is_#{role}?" do
      self.role == role
    end
  end
end

とリファクタリングできます。

Tuesday 4 December 2012

フリーランス仕事サイト



フリーランスへの仕事発注サイトはかなりたくさんありますが、知り合いのデザイナーが自分の経験ではいつもElanceで仕事を受けていたという話を聞きました。

それで最近登録してみたのですが、やはり仕事の量も質もかなり良く感じます。Stack Overflowが運営するCareers 2.0も良い仕事がありそうですが、こちらはどちらかというとパーマネントのポジションがほとんどのようです。Elanceはプロジェクトベースの仕事がメインで掲載されています。

ちなみにスキルチェックのテストもあり、私はRailsのテストを受けたのですがやっと”可”のスコアでした。Rubyのテストは全然だめでした。こんなレベルではまだ技術者とも呼べませんね…。トップ5%とかいうひとのスコアを見ると、歴然と差があるなあと感じます。まだまだこれからですね。


Monday 3 December 2012

viewでcontent_forを使うか、ヘルパーメソッドを使うか?

最近 Rails の viewで

<% content_for :title do "Title" end %>

として

<%= yield :title %>

とすれば yieldされた場所にcontents_for の内容が返ってくる事を知りました。テンプレートでcontents_for で定義した内容をlayoutの例えば<title>とか<meta name="description" contents="">などに使えそうです。

ヘルパーを使うのとどちらが良いのかと考えた時、ロジックとしてはコントローラから渡されたコンテンツをviewの中でcontents_forとしたほうが奇麗だと思います。

しかしコードが重複しがちな所があるので、やはり使い分けが必要でしょうか。取りあえずはできるだけcontents_for / yieldで書く方向性で。