最近仕事で PHP 製のレガシーなウェブアプリの API を Rails でつくるということをやっていまして(僕がイチから構築したわけではないですが)、Rails way に沿っていないスキーマの DB を扱う際に苦労しました。
そのとき苦労した点を一昨日 RubyHiroba 2014 というイベントで発表してきたのでスライドを公開します。
タイトルは一部変更しました。
スライドは添え物で、ほとんど口で説明したのでなかなか理解しづらい点はあるかもしれませんが、このエントリーでは一番ハマった点だけ紹介します。
例: Sale has_many sale_details
例えば、下記のようなテーブル定義があったとして、
CREATE TABLE `sales` ( `id` `account_id`, … CREATE TABLE `sale_details` ( `id` `account_id` `sales_id` # ここが sale_id ではないのがポイント
モデルのアソシエーションを Sale has_many sale_details
にしたいとします。
sale.sale_details
sale.sale_details
したときに下記のような SQL を実行してほしいときは、
SELECT `t_sales_detail`.* FROM `t_sales_detail` WHERE t_sales_detail`.`sales_id` = 999
アソシエーション設定に foreign_key
と primary_key
オプションを使います。
class Sale < ActiveRecord::Base has_many :sale_details, :foreign_key => :sales_id, :primary_key => :id end
もう一歩進めて、インデックスをうまく使えるようにする
例えば、インデックスが下記のような複合インデックスになっていたら、
add_index "sale_details", ["account_id", "sales_id"], :name => …
このままではインデックスが使えないので、下記のような SQL がほしい。
SELECT `t_sales_detail`.* FROM `t_sales_detail` WHERE t_sales_detail`.`account_id` = 123 AND t_sales_detail`.`sales_id` = 999
そのときはアソシエーションを下記のように設定する必要があります。
class Sale < ActiveRecord::Base has_many :sale_details, :foreign_key => [:account_id, :sales_id], :primary_key => [:account_id, :id] end
とかいう辺りが Rails Guides の該当箇所を読んでもよく理解できなかったので、手を動かしながら調べて分かったことを紹介した感じです。興味がある方はスライドのほうを見てみてください。
Rails Guides の日本語版が出たようです
で、その Rails Guides なのですが、話逸れますけど、日本語版が先日公開されたようです。中の人である [twitter:@yasulab] さんが RubyHiroba で Rails Guides の中の仕組みを発表されていました。こういうのめっちゃ有り難い!感謝です!
謝辞
RubyHiroba 2014 運営チームのみなさん、おつかれさまでした。本当にありがとうございました!この場を借りてお礼申し上げます。