Scaffold で作成した View では、
外部キー参照(references) のデータは、
ID の数値をそのまま扱う状態になっています。
例えば、Cabinet 編集画面の Floor が 1 になっている感じ。
これだと 1 が何者か分からないので、
“1F” と表示されるように修正しましょう。
参考リポジトリ: https://github.com/Bonv-dev/book_mgmt/commit/289fb87
references データの編集は複数のモデルで行うため、
共通で使用できるコードを書きましょう。
\app\models\concerns フォルダに common_scopes.rb というファイルを追加します。
中身は、
module CommonScopes
extend ActiveSupport::Concern
included do
scope :enabled_only, -> { where(enabled: true) }
end
class_methods do
# データ表示用 (全データを持つ)
def name_list
self.pluck(:id, :name).to_h
end
# データ編集用 (有効なデータのみ)
def name_options
self.enabled_only.pluck(:name, :id).to_h
end
end
end
とします。
中身を順に説明します。
モデルクラス側に埋め込む際には、
class Book < ApplicationRecord
include CommonScopes
end
のようにします。
module は Ruby の機能で、クラスに追加できる機能のかたまりです。
new はできず、クラスに埋め込んで使います。
クラスに新しい機能を追加する働きを持ちます。
具体的な埋め込み方は、後述します。
\app\models\concerns フォルダは Rails 標準で用意されています。
モデル用 module の定義ファイルを置く場所です。
モデルクラスの定義ファイルを置く \app\models フォルダと分けて、
module を管理しやすくします。
ActiveSupport::Concern は、
module をクラスに埋め込みやすくする、ActiveSupport のライブラリです。
これを、extend で該当モジュール (今回なら CommonScopes) に組み込みます。
使用する際には、
クラス側、例えば Book クラス内で、
include CommonScopes
のようにして該当モジュールを追加します。
このブロック内にメソッドを入れておくと、
メソッドがインクルード先に埋め込まれた状態で動作します。
extend ActiveSupport::Concern 必須です。
ActiveRecord の機能の一つです。
モデルの条件式 (クエリ) に名前を付け、
その名前をメソッドのように使用できるようにします。
scope :enabled_only, -> { where(enabled: true) } なら、
where(enabled: true) に enabled_only という名前を付け、
Book.enabled_only のように使えます。
(Book データから、enabled カラムの値が true のものだけを抽出します。)
引数を渡したい場合は、
例えば、
scope :enabled_only, -> (flag){ where(enabled: flag) }
のようにします。
Book.enabled_only(true) のように使えます。
このブロック内にメソッドを入れておくと、
メソッドがインクルード先に埋め込まれた状態でクラスメソッドとして使用できます。
CommonScopes モジュールに書いた name_list メソッドを使います。
CommonScopes を include したモデル、
例えば、Category なら、Category.name_list になります。
name_list の中身が self.pluck(:id, :name).to_h なので、
Category データから id と name カラムのペアを抽出し、
to_h で {id=>name} の hash が生成されます。
表示画面 \app\views\books\_book.html.erb 内で
@category_list[book.category_id] としているので、
該当 @book の category_id に該当する name が表示されることになります。
CommonScopes モジュールの name_options も、
name_list と同様の流れで View に適用します。
こちらは編集画面 \app\views\books\_form.html.erb 内、
form.select で使うため {:name=>:id} と name_list からキー・値が入れ替わっています。
Category には enabled (有効・無効)カラムがあります。
編集画面で無効なデータを選択されては困るので、
name_options は enabled_only で絞っています。
表示画面では、過去の無効なデータも表示できないと困るので、
name_list は enabled_only を通しません。

注意すべきは、
同じ name が複数ある場合です。
Step には、1F にも 2F にも “S00” があります。
name_options で name をキーにしてしまうと、
後で出てきた name だけが残ってしまいます。
重複を避けるには、
form.select :step_id, @step_options を、
form.collection_select :step_id, Step.enabled_only, :id, :name
に変えるなどの工夫が必要です。
これで重複する項目も消えずにリストアップされはしますが、
どれがどの ID なのか分からないので、根本解決にはなりません。
サンプルプログラムでは、全く別の方法 ( Stimulus と Turbo Stream ) を使って解決します。