Rails でドロップダウンリストの選択肢を、別テーブルに収めておいて使用するものを試作してみた。
●si01:外部参照版
- テーブル構造:
-
- メインのテーブル
- テーブル名:mains
- テーブル要素:
- moji:string
- sentakushi_id:reference ←FKとするものは、元のテーブル名に_idをつけたものになる。
- メインのテーブル
-
- 選択肢のテーブル
- テーブル名:sentakushis
- テーブル要素:
- sentakushi:string
- 選択肢のテーブル
(*)最初は maines/sentakushies と思っていたのだが、生成したものを見てみると上記のようなテーブル名称になった。
★01:生成
C:\rails_app\work>rails new si01
★02:sentakushi アプリの生成
C:\rails_app\work>cd si01
C:\rails_app\work\si01>rails generate scaffold sentakushi sentakushi:string
★03:main アプリの生成
C:\rails_app\work\si01>rails generate scaffold main moji:string sentakushi:references
★06:マイグレーションによるテーブルの生成
C:\rails_app\work\si01>rake db:migrate
★07:シードによるテストデータの準備
これは db/seeds.rb ファイルを編集。
★08:作成したシードファイルを実行
C:\rails_app\work\si01>rake db:seed
★11:.\si01\app\views\mains\_form.html.erb を編集し、ドロップダウンが表示されるようにする。
<%= f.label :moji %>
<%= f.text_field :moji %>
<%= f.label :sentakushi %>
<%= f.text_field :sentakushi %> ←★ここ★
次のように編集。
<%# <%= f.text_field :sentakushi %>
<%= f.collection_select :sentakushi_id, Sentakushi.all, :id, :sentakushi %>
これで選択されるのは sentakushis.id で、これはテーブル定義からして正しい。
しかし、見た目も id が表示というのは判らないので文字列を表示したい。
★
ふむ、C:\rails_app\work\si01\app\views\mains\index.html.erbを
以下のようにいじったら表示された。
viewで取得するのはMVCに反するのでは?
<% @mains.each do |main| %>
<% @sentakushi=Sentakushi.find(main.sentakushi_id) %> ←★
<%= main.moji %>
<%= @sentakushi.sentakushi %> ←★
<%= link_to 'Show', main %>
<%= link_to 'Edit', edit_main_path(main) %>
<%= link_to 'Destroy', main, confirm: 'Are you sure?', method: :delete %>
<% end %>
★モデルの中身
外部参照を示す belong to はモデルの中。
★C★
app\models\main.rb
class Main < ActiveRecord::Base
belongs_to :sentakushi ←sentakushi クラスに属するものを持つという意味。外部キーでは、こういう記述をする。
end
★D★
app\models\sentakushi.rb
class Sentakushi < ActiveRecord::Base
end
以上
●si01a:外部参照ではない版
si01と同様だが、テーブル間に関連無しでも表示出来るらしいので試してみる。
- テーブル構造:
-
- メインのテーブル
- テーブル名:mains
- テーブル要素:
- moji:string
- sentakushi:string ←ここがsi01と異なる。
- メインのテーブル
-
- 選択肢のテーブル
- テーブル名:sentakushis
- テーブル要素:
- sentakushi:string
- 選択肢のテーブル
★01:生成
C:\rails_app\work>rails new si01a
★02:sentakushi アプリの生成
C:\rails_app\work>cd si01a
C:\rails_app\work\si01a>rails generate scaffold sentakushi sentakushi:string
★03:main アプリの生成
C:\rails_app\work\si01a>rails generate scaffold main moji:string sentakushi:string
★06:マイグレーションによるテーブルの生成
C:\rails_app\work\si01a>rake db:migrate
★07:シードによるテストデータの準備
これは db/seeds.rb ファイルを以下のように編集した。
#coding: utf-8
Sentakushi.create(:id => 1, :sentakushi => '1番目の選択肢')
Sentakushi.create(:id => 2, :sentakushi => '2番目の選択肢')
Sentakushi.create(:id => 3, :sentakushi => '3番目の選択肢')
Sentakushi.create(:id => 4, :sentakushi => '4番目の選択肢')
Sentakushi.create(:id => 5, :sentakushi => '5番目の選択肢')
Sentakushi.create(:id => 6, :sentakushi => '6番目の選択肢')
★08:作成したシードファイルを実行
C:\rails_app\work\si01a>rake db:seed
★11:ドロップダウンを表示するためのテンプレートファイルの編集。
C:\rails_app\work\si01a\app\views\mains\_form.html.erb を編集する。
<%= f.collection_select :sentakushi, Sentakushi.all, :id, :sentakushi %>
とすると、sentaushiテーブルの中のidが選択される。 ↑これがidだからだ。
代わりに
<%= f.collection_select :sentakushi, Sentakushi.all, :sentakushi, :sentakushi %>
とすると、sentaushiテーブルの中の選択肢文字列が選択される。 ↑これは文字列だから。
★belong to の有無
モデルファイルを開いて覗いてみたが、記述は生成されていなかった。
←正しい生成である。
以上