私は、次のものを入力できるフォームを作成しようとしています。外部キー。名前をフォームに入力しますが、外部キーとしてIDを保存します。
私はこれを行うさまざまな方法を見つけましたが、すべて大きな欠点があります。 Aのためのコントローラは、このように見えますが
<%= form_for(@a) do |f| %>
...
<div class="field">
<%= f.label :b %><br>
<%= f.text_field :b %>
</div>
...
<% end %>
: は、たとえば:私は2つのモデルAとBがあります。
class A < ActiveRecord::Base
belongs_to :b
validates :b_id, presence: true, inclusion: {in: B.all.map(&:id)}
end
class B < ActiveRecord::Base
end
を_form.html.erbは、1つの文字列を入力することができます。このフィールドを使用しています:
class AController < ApplicationController
...
before_action :get_a_id, only: [:create, :update]
...
private
def page_params
params.require(:a).permit(:name, :b_id, :content)
end
def get_a_id
b_name = params[:a][:b]
b = B.find_by(name: b_name)
b_id = b.id unless b.nil?
params[:a][:b_id] = b_id
end
end
これは、テキストフィールドに入力された:名前がデータベース内に見つかった場合はどういうわけか機能します。見つからない場合は、検証エラーが表示されますが、text_fieldはハイライトされておらず、(以前に入力された文字列を含む代わりに)空です。 これは、フィールドには名前の代わりにBのオブジェクトが含まれている必要があり、間違った文字列の場合には存在しないためだと思います。 このように操作するのは良い考えではないと思います。
これを実現する良い方法はありますか?私はドロップダウンを望んでいません。なぜなら、そこには多くの価値があるからです。もちろん、次のステップは何らかの自動補完を実装することですが、ここでは数えません。
理論的には、text_fieldを新しいB-objectに関連付ける方法がありますが、:nameを表示するだけです。コントローラは、その名前のデータベースオブジェクトを見つけようとし、プレースホルダをそのオブジェクトに置き換えようとする可能性があります。適切なオブジェクトが見つからない場合、検証は失敗しますが、値は引き続き表示されます(もちろん、検証を変更する必要があります)。
いい方法でこのようなことを達成する方法はありがたいです。不明な点があれば教えてください。
EDIT:
私が実際に達成したいこと:
フォームフィールドの文字列を入力することができます。この文字列は、この文字列をオブジェクトのID(B)に変換する検索が実行されるコントローラに渡され、外部キーとして使用できます。クラスAのオブジェクトが保存されると、バリデーターはIDが設定され、存在するかどうかを確認する必要があります。検証が失敗した場合は、フィールド(文字列付き)を強調表示し、エラーメッセージを表示する必要があります。
主な問題は、名前の文字列がモデルにないことです。ちょうどイドです。したがって、idが検証された場合(適切なアプローチは何か)、エラーメッセージは文字列として名前を含むフィールドに関連付けられません。
オブジェクトbの名前を示唆するためにjquery [autocomplete](https://jqueryui.com/autocomplete/)を使うことができ、ユーザーは結果から選択できます – Dawcars
Thanks @Dawcars、それはちょっとしたステップですアップ。主な問題は、そのオブジェクトのIDを格納する際に名前を入力し、フォームに関連付けられた素晴らしいモデル検証を維持する方法です。 – Klumbe