回答の提案と私自身のさらなる調査に基づいて、関連するテーブルからフォーム内の多数のオプションを取得する最良の方法についての私の結論です。
オートコンプリートが最適なソリューションのようです。これは通常のテキスト フィールドですが、2 番目の文字を入力すると、最初に見つかった 10 個の一致が取り込まれ、以下にリストされます。文字を追加するたびに、検索が絞り込まれます。私は JavaScript にあまり熟練していないので、提案されたように独自の JS で補完されたプラグインを追加するのではなく、gem、特にrails-jquery-autocompleteを使用して JS コーディングを抽象化することにしました。
手順は次のとおりです。
設定
足場を生成します。
rails generate scaffold City name state
rails generate scaffold Business name address city:references state zip
rake db:migrate
ジェムをインストールします。jQuery-UI のオートコンプリート ウィジェットを使用するので、そのための rails gem もインストールします。
# gemfile
gem 'jquery-ui-rails'
gem 'rails-jquery-autocomplete'
これらを JavaScript およびスタイルシート アセットに追加します。
# app/assets/javascripts/application.js > put these after //= require jquery_ujs
//= require jquery-ui/autocomplete
//= require autocomplete-rails
# app/assets/stylesheets/application.css
*= require jquery-ui/autocomplete
モデル
最初に関連付けを作成します。
# app/model/city.rb
has_many :businesses
# app/model/business.rb
belongs_to :city
入力した都市が都市テーブルにあることを確認する場合は、検証を追加します。
# app/models/business.rb
validates :city, presence: true
ビジネス テーブルには、都市名ではなく、city_id のフィールドがあります。getter メソッドと setter メソッドを使用して、ビジネス モデル ファイルに仮想属性を作成できます。4歳のRailsCastから入手したので、これを行うにはおそらくもっと最新の方法がありますが、うまくいきます。
#getter method
def city_name
city.try(:name)
end
#setter method
def city_name=(name)
self.city = City.find_by(name: name) if name.present?
end
ルート
ここで、gem の魔法が働きます。autocomplete_model_attribute としてフォーマットされたビジネス REST リソースへのルートを追加します。
# config/routes.rb
resources :businesses do
get 'autocomplete_city_name' on: :collection
end
コントローラ
コントローラーの上部で、クラス名と属性を渡してオートコンプリート アクションを呼び出します。デフォルトでは、オートコンプリートは単語の先頭から始まるテキストと一致します。単語内の任意の場所を検索する場合は、'full' オプションを true に設定します。それ以外の場合は省略します。
# app/controllers/business_controller.rb
autocomplete :city, :name, full: true
ビジネス モデルで city_name 仮想属性を作成したので、それを許可されたパラメーター リストに追加する必要があります。
def business_params
params.require(:business).permit(:name, :address, :city_id, :state, :zip, :city_name)
end
ビュー
新しいビジネス インスタンスを作成または編集するフォームで、autocomplete_field ヘルパーを使用して、city_id フィールドを city_name 仮想属性に変更します。'data-auto-focus' オプションは、リストの最初の値を自動的に選択します。したくない場合はオフにしてください。
# app/views/businesses/_form.html.erb
<div class="field">
<%= f.label :city_name %><br>
<%= f.autocomplete_field :city_name, autocomplete_city_name_businesses_path, 'data-auto-focus' => true %>
</div>
終わり!