キーワードテーブルを追加して、キーワードで分類したい!
MySQLはリレーショナルデータベースと呼ばれている。リレーショナルデータベースでは、テーブル(単純な表)同士を関連付けして、複雑なことを扱えるようにするらしい。ちょうど表計算ソフトのlookup関数の使い方に似ているな...。それならリレーショナルデータベース風の使い方もしてみたいもんだ。
そこでまずは、登録したソフトウェアにキーワードを設定して分類しようと考えた。はてなブログ(このブログ)のカテゴリーみたいなものだ。だけど、とりあえず今は、一つのソフトウェアに複数のキーワードは設定できない仕様とする。
例えば、Ruby on Railsの環境を作るためのソフトウェアのキーワードは、みな「Ruby on Rails」にするのだ。キーワードには好きな単語を随時追加できるようにしたい。キーワードにはリンクを設定し、クリックするとそのキーワードに絞り込んだ一覧表示を行うようにしたい。
-
-
- Ruby on Railsでのリレーショナルデータベースの取り扱いについては、日本語訳の素晴らしいページがこちらに。感謝です。
- 満足せる豚。眠たげなポチ。:Rolling on Ruby on Rails - Japanese Translation - p1
- Rolling with Ruby on Rails, Part 2 日本語訳
-
必要なこと(順不同)
- データベースにキーワードテーブルを追加する。
- キーワードテーブルを管理するモデル、コントローラも追加する。
- キーワードテーブルを操作するコード。
- ソフトウェアテーブルと、キーワードテーブルを関連付け。
- ソフトウェアテーブルを操作する時にキーワードを表示するコード。
- キーワードをクリックした時にそのキーワードに絞り込むコード。
マイグレーションを利用して、キーワードテーブルを追加
マイグレーションを利用するには script/generate model を実行しておいた方が無駄が無い。モデル作成時にマイグレーションファイルも自動生成してくれるから。よって、以下の手順で作業した。
- まずはモデルの作成。Generatorsタブを選択して、modelを選択、その右項目にkeywordと入力して、Goボタン。
- app/models/keyword.rbが作成される。
- db/migrate/003_create_keywords.rbが作成される。
- ついでなのでコントローラの作成。Generatorsタブのまま、controllerを選択、右項目はkeywordのまま、Goボタン。
- app/controllers/keyword_controller.rbが作成される。
- マイグレーションファイル 003_create_keywords.rb にテーブルの追加と削除をコーディング。追加したのは以下のように2行だけ。
class CreateKeywords < ActiveRecord::Migration def self.up create_table :keywords do |t| t.column :name, :string end end def self.down drop_table :keywords end end
- 上記を保存したら、マイグレーションの実行。Rake Tasksタブで、db:migrateを選択、Goボタン。
- keywordテーブルが追加された履歴が、Consoleタブに表示される。
以上で、keywordのモデル、コントローラ、テーブルの追加は完了。
ソフトウェアテーブルとキーワードテーブルの関連付け
ソフトウェアテーブルにkeyword_idフィールドを追加
ソフトウェアテーブルには、関連するテーブル名_id、というフィールドが必要になる。
- マイグレーションファイルの作成。Generatorsタブで、migrationを選択、その右項目にadd_column_keyword_idと入力、Goボタン。
- db/migrate/004_add_column_keyword_id.rbが作成される。
- マイグレーションファイル 004_add_column_keyword_id.rb を以下のようにコーディング。
class AddColumnKeywordId < ActiveRecord::Migration def self.up add_column :softwares, :keyword_id, :integer end def self.down remove_column :softwares, :keyword_id end end
- 上記を保存したら、マイグレーションの実行。Rake Tasksタブで、db:migrateを選択、Goボタン。
- keyword_idが設定された履歴が、Consoleタブに表示される。
それぞれのモデルに関連付けをコーディング
コーディングと言っても、それぞれ1行ずつだ。1行コーディングはシンプルで分かりやすい!
- モデル keyword.rb
- app/models/keyword.rb
class Keyword < ActiveRecord::Base has_many :softwares endsoftwaresと複数形なので注意。
キーワードで分類するということは、キーワード中心に見ると、いくつものソフトウェアを保持すると考えるらしく、このように書く。
- モデル software.rb
- app/models/software.rb
class Software < ActiveRecord::Base validates_presence_of :title, :description, :url validates_format_of :url, :with => URI.regexp(['http', 'https', 'ftp']) belongs_to :keyword endこちらはkeywordと単数系。
今度はソフトウェア中心に見ると、キーワードに属すると考えるらしいので、このように書く。
キーワードテーブルを操作するコード、もう一つのscaffold
キーワードテーブルへデータを追加、削除、表示するコードが必要だ。これまでのようにscript/generate scaffoldで、コードを自動生成する方法が思い浮かぶが、scaffoldにはもう一つの使い方がある。今回は、その方法でやってみる。
- コントローラ keyword_controller.rb
- app/controllers/keyword_controller.rb
class KeywordController < ApplicationController scaffold :keyword end
何と、ここでもコントローラに1行書くだけ。
まだ、ソフトウェアの操作画面から、キーワードの操作画面にはリンクしてないので、URLを直接入力して操作を試してみる。
http://0.0.0.0:3000/keywords
すると、こんなエラーが出てしまった。
どこかで間違ったのかと思い、コードを見直したが(といっても1行だけなので間違いようが無い)問題なく、しばし悩んでしまった。
問題は、URLアドレスだった。「s」が余分だったのだ。これでアクセスできた。
http://0.0.0.0:3000/keyword
-
-
- script/generate scaffoldでコードを自動作成した場合は、http://0.0.0.0:3000/softwaresと複数形でアクセスできたのだが、メソッド呼び出しでscaffoldを使った場合は、単数系でアクセスすることになるようだ。
- いや、これは正確な認識ではなかった...。script/generate model keywordでモデルを作った後、すぐにscript/generate controller keywordでコントローラを作ったが、ここでコントローラ名の指定をkeywordsと複数形で指定すれば、URLも複数形でアクセスできるようになった。コントローラは複数形で指定するのが正しいのかもしれない...。
- それにしても、script/generate modelも、script/generate scaffoldも単数系で指定するのに、script/generate controllerだけ複数形にしなくちゃいけないのは何か理由があるのだろうか?複数形が必須条件なら、scaffoldのように自動的に複数形に変換してくれればいいに...。
- 複数形なのか、単数系なのか、英語の苦手な人にとっては理解し難い感覚だ。
-
ちょっと悩んでしまったが、どうにかここまで終了。
残る課題は二つだけになった。
- ソフトウェアテーブルを操作する時にキーワードを表示するコード。
- キーワードをクリックした時にそのキーワードに絞り込むコード。