Ruby on Rails で "1対多" 関連を使ったサンプルを作成

d:id:fits:20070730:1185814188Grails を使って作成したサンプルと同様のものを Ruby on Rails で作成する。

  1. rails アプリケーションの作成
  2. モデルクラスの作成
  3. DB の作成
  4. コントローラーとビューの作成
  5. 実行

rails アプリケーションの作成

rails コマンドでアプリケーションを作成する

>rails testapp

モデルクラスの作成

モデルクラスを生成する前に、DB のマイグレーション用のファイルが生成されるように testapp/db ディレクトリ内に migrate ディレクトリを作成しておく

>cd testapp\db
>mkdir migrate

モデルクラスを script/generate を使って生成する。(testapp ディレクトリで実行)

>ruby script/generate model Author
>ruby script/generate model Book

Author と Book が "1対多" の関連を持つようにするには以下のような記述を行う。

testapp/app/models/author.rb
class Author < ActiveRecord::Base
  has_many :books
end
testapp/app/models/book.rb
class Book < ActiveRecord::Base
  belongs_to :author
end

DB の作成

モデルクラスの生成時に作成されたマイグレーション用のファイルにテーブルのカラム設定を記述する。

testapp/db/migrate/001_create_authors.rb
class CreateAuthors < ActiveRecord::Migration
  def self.up
    create_table :authors do |t|
      t.column :name, :string
    end
  end
  ・・・
end
testapp/db/migrate/002_create_books.rb
class CreateBooks < ActiveRecord::Migration
  def self.up
    create_table :books do |t|
      t.column :title, :string
      #author_id カラムは authors テーブルへの外部キー用
      t.column :author_id, :integer
    end
  end
  ・・・
end
テーブルの作成

rake コマンドを db:migrate を指定して実行し、DB テーブルの生成を行う(testapp ディレクトリで実行)

>rake db:migrate

コントローラーとビューの作成

script/generate に scaffold を指定してコントローラーとビューを生成する

>ruby script/generate scaffold Author
>ruby script/generate scaffold Book

ここで、RoR の scaffold によって生成されたビューでは Grails にように "1対多" の関連を入力するためのドロップダウンリスト等が表示されない、そのため自分で仕組みを用意する必要がある。

Book の new や edit 時に Store をドロップダウンリストで選択できるようにするには Book の _form.rhtml を以下のように変更する。

testapp/app/views/books/_form.rhtml
<%= error_messages_for 'book' %>
<!--[form:book]-->
<p><label for="book_title">Title</label><br/>
<%= text_field 'book', 'title'  %></p>

<!-- 以下を追加する -->
<p>Author<br/>
<%= collection_select :book, :author_id, Author.find_all, :id, :name %></p>
<!--[eoform:book]-->

Author の edit 時に Book の new ページに移動するリンクを表示するには Author の edit ページと Book のコントローラーを以下のように変更する

testapp/app/views/authors/edit.rhtml
<h1>Editing author</h1>

<% form_tag :action => 'update', :id => @author do %>
  <%= render :partial => 'form' %>
  <%= submit_tag 'Edit' %>
<% end %>

<b>Books:</b>
<ul>
  <% @author.books.each do |b| %>
      <li><%= link_to h(b.title), :action => 'show', :controller => 'books', :id => b.id %></li>
  <% end %>
</ul>

<!-- Book の new ページへのリンク -->
<%= link_to 'Add Book', :action => 'new', :controller => 'books', :id => @author.id %> |
<%= link_to 'Show', :action => 'show', :id => @author %> |
<%= link_to 'Back', :action => 'list' %>
testapp/app/controllers/books_controller.rb
class BooksController < ApplicationController
  ・・・
  def new
    @book = Book.new

    #Author の edit ページから遷移した時に
    #その Author がドロップダウンリスト上で選択されているようにするための処理
    if params[:id]
      @book.author = Author.find(params[:id])
    end
  end
  ・・・
end

実行

>ruby script/server