いくつか調べ物をしていてiOS 6 のSafariでファイル画像アップロードができることをやっと知りました。これで responsive なサイトを作る敷居は一つ下がった様に感じます。
これまでiOSで画像アップロードができないためだけにモバイルアプリを制作していた会社も少なくないのではないかと思うと、仕様変更がちょっとあるだけでいままでの努力がなんだったんだと泣き寝入りをせざるを得ないのはちょっと儚さを感じます…。
Thursday, 20 December 2012
Wednesday, 19 December 2012
私は16歳で高校を卒業してプログラムをしています。就職過程に一石
これは私本人の話ではないのですが、最近こんな人の記事を読みました。
http://jarredsumner.com/
私は16歳で高校を卒業してプログラムをしています。
履歴書を会社に送るよりも会社の人たちが来ていそうなミートアップイベントに参加して人と直接話しをしたよっていう話を書いています。
こんな投稿でも、100社に履歴書を送って面接で断られまくってという無意味な精神修行過程をもっと有意義な過程に昇華する一石になればと思います。
以下本人のサイトから抜粋です。
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にします。
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がとても使えそうですが、そもそもどこまでコミットできるかという判断が解決していないですね…。
そんな視点を持ちつつなんとはなしに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を導入したタイミングのどこかで自動でテストの時にデータベースのコレクションを削除してくれるスクリプトも導入されるのかと思ったらそんなことは無い様ですね…。
一時的に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"から幾つか私が参考になった箇所を少しずつ書いていきます。
validates_uniqueness_of :product_number, allow_nil: true
としていたのですが、モデルのインスタンスを新規保存・更新するとエラーも出ないのに、何故かDBのデータが更新されません???。暫く迷っているうちにふとindexの時に
index( {model_number: 1}, {unique: true} )
と書いた事に思い当たりました。DBがロールバックした事実をmongoidの方でユーザに報せる機構が内容です。ActiveRecordでもDBのレベルでの一意性のチェックなどはしないのが良いプラクティスだそうです。SQLデータベースでもこの辺りの実装は異なるらしいので互換性の実装が難しいのでしょうね。それとももっと他の所に問題があるのでしょうか。もっとDBの実装を理解しないと問題の本質が分からないです(残念ですが)。MongoDBでも例えばクラウドサービスのMongoHQなどでは若干仕様を変えている可能性はありますね…。
クラウドのファイルストレージサービスが推奨されています。現時点で代表的なサービスはS3ですね。
これはモデルにコードを記述して、
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でモック・スタッブできるそうなので、ここにもテストを書かない口実は無さそうです…。
{
"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
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を使った方が無駄が無いかもしれないですね。
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"から幾つか私が参考になった箇所を少しずつ書いていきます。
デフォルトの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
私も以前に作ったショッピングカートのルートをリファクタリングしないと駄目です…。
ユーザとアプリケーションの信頼を確保するために正確なエラー表示が必要です。サーバサイドのエラーは管理者に報告して、ユーザサイドのエラー(例えばメールアドレスが違うなど)はユーザにその旨を伝えると同時に、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のバリデーション機能などを使用してレスポンスを返すのが的確な挙動です。
もう一つの問題としては、大きなプロセスの仕事があります。この場合、対処方法の一つとしてはプロセスをキューに押し込んでしまい、バックグラウンドで仕事をしてもらい順々にこなしてもらうというものです。ライブラリとしてはdelayed_jobというのとRescueというgemがあるそうです。delayed_jobはSQLを、RescueはRedisを使ってキューを管理するそうです。
ちなみにeventmachineなどconcurrencyライブラリもありますが、大きな仕事の場合は同時にさばく意味が少ないので、外部APIから情報を引っ張ってくるなど待ち時間が発生して処理に時間がかかる仕事と、プロセスの処理自体に計算の時間がかかるなどの仕事はそれぞれ異なるストラテジーでさばく必要がある様ですね。
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"から幾つか私が参考になった箇所を少しずつ書いていきます。
クラスを分ける、モジュールを使う、callbackを使うなどORM自体で搭載されている機能は使用するという解決策を。
@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のプラクティスをうまく実行すればしんどいコードを書かなくても済みそうですね。
こうやっていくとだんだんとスパゲッティーになっていくので、こういう書き方は一切辞めて下のように is_guest? is_manager? などと役割役割の名前でauthorizationを実装します。また、役割もデータベースに保存しないでコンスタントとしてハードコードしてしまいます。
多くの場合、役割をデータベーすに保存するのはメリットが少ないそうです。
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を発効してくれ様です。
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というのは面白く感じました。成功例を並べられても正直面白くないですが、人の失敗を例に挙げて解説してくれるのはとても興味深く面白く感じました。
少しずつ学んだ事を記事に書いてはいきたいと思います。
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を作れます。
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
フリーランス仕事サイト
それで最近登録してみたのですが、やはり仕事の量も質もかなり良く感じます。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で書く方向性で。
<% 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で書く方向性で。
Subscribe to:
Posts (Atom)