Ruby on Railsで複合キーを扱う(2)
2012/03/26
前回は、Gemライブラリcomposite_primary_keys
を用いるとRailsアプリケーションにおいて複合キーでレコードを検索したり、複合キーを持つモデル同士を関連づけできることを確かめました。
今回はルーティング編です。
コントローラの生成・実装からルーティングの設定まで
% rails g controller departments index % rails g controller products index show
app/controllers/departments_controller.rb
を修正。
class DepartmentsController < ApplicationController def index @departments = Department.order("code, seq_number") end end
app/controllers/products_controller.rb
を修正。
class ProductsController < ApplicationController def index @department = Department.find(params[:department_id]) @products = @department.products.order("products.code, products.model_number") end def show @department = Department.find(params[:department_id]) @product = @department.products.find(params[:id]) end end
config/routes.rb
を修正。
Synthetos::Application.routes.draw do resources :departments do resources :products end end
ビューの実装
app/views/departments/index.html.erb
を修正。
<h1>Departments#index</h1> <ul> <% @departments.each do |d| %> <li> <%= d.name %>: <%= link_to "Products", [ d, :products ] %> </li> <% end %> </ul>
app/views/products/index.html.erb
を修正。
<h1>Products#index</h1> <ul> <% @products.each do |p| %> <li> <%= link_to p.name, [ @department, p ] %> </li> <% end %> </ul>
app/views/products/show.html.erb
を修正。
<h1>Products#show</h1> <ul> <li>Name: <%= @product.name %></li> <li>Code: <%= @product.code %></li> <li>Model number: <%= @product.model_number %></li> <li>Description: <%= @product.description %></li> </ul>
シードデータの投入
config/routes.rb
を修正。
%w(robot automobile ship).each do |code| Department.create!( code: code, seq_number: 1, name: code.capitalize, established_on: 2.years.ago ) end %w(alpha bravo).each do |code| Product.create!( code: code, model_number: 2012, department_code: "robot", department_seq_number: 1, name: code.capitalize, description: "" ) end
% rake db:reset
モデルの修正
Gemライブラリcomposite_primary_keys
の説明によれば、["robot", 1]
という複合キーを持つオブジェクト@department
に対して、to_param
メソッドを呼ぶと "robot,1"
という文字列が返ってくるべきなのですが、実際には "robot-1"
という文字列が返ってきます。これではいろいろとうまく動かないので、モデルに少し修正を加えます。
たぶん composite_primary_keys
がRails 3に完全に対応し切れていないためと思われます。作者に連絡したので、そのうちに直るでしょう。
app/model/department.rb
を次のように修正します。
class Department < ActiveRecord::Base self.primary_keys = :code, :seq_number has_many :products, foreign_key: [ :department_code, :department_seq_number ] def to_param persisted? ? to_key.join(',') : nil end end
同様に、app/model/product.rb
を次のように修正します。
class Product < ActiveRecord::Base self.primary_keys = :code, :model_number belongs_to :department, foreign_key: [ :department_code, :department_seq_number ], primary_key: [ :code, :seq_number ] def to_param persisted? ? to_key.join(',') : nil end end
ブラウザで動作確認
% rails s
ブラウザで http://localhost:3000/departments
を開くと次のような画面になります。
「Robot」の右の「Products」リンクをクリックすると次のような画面になります。URLに注目してください。
そして、「Alpha」リンクをクリックすると次のような画面になります。
ちょっとしたバグ(?)が見つかりましたが、ルーティングはうまく動いているようですね。ただし、URLにコンマ(,)が含まれる点はちょっと気になります。
次回は、複合キーの一つが文字列や数値ではなく、「期間」になっている場合について考えます。