2016-05-15 42 views
0

我想創建一個表單,其中可以輸入:外部模型實例的名稱,該實例應該轉換爲:要存儲爲該對象的id對象的名稱外鍵。在窗體中輸入名稱,但將ID保存爲外鍵

我發現了這樣做的不同方式,但它們都有很大的缺點。 例如:我有兩個型號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使用該字段,其中一個可以輸入字符串:

<%= form_for(@a) do |f| %> 
    ... 
    <div class="field"> 
    <%= f.label :b %><br> 
    <%= f.text_field :b %> 
    </div> 
    ... 
<% end %> 

而對於控制器看起來像這樣:

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對象關聯,但只顯示:name。然後控制器可以嘗試找到具有該名稱的數據庫對象,並用它替換佔位符。如果找不到正確的對象,則驗證失敗,但該值仍顯示(當然,驗證需要隨後進行更改)。

任何方式來實現這樣的事情在一個不錯的方式是讚賞。只要讓我知道,如果有什麼不清楚。

編輯:
什麼其實我是想實現:

表單字段,允許輸入一個字符串。應該將該字符串傳遞給控制器​​,在該控制器中執行搜索,將該字符串轉換爲對象(B)的id,以便將其用作外鍵。當類A的對象被保存時,驗證器應該檢查該ID是否被設置並存在。如果驗證失敗,則應該突出顯示字段(帶有字符串),並顯示錯誤消息。

主要的問題是,具有名稱的字符串不在模型中。只是身份證是。所以如果id被驗證(什麼是正確的方法),那麼錯誤消息就不會被作爲字符串關聯到包含該名稱的字段。

+1

您可以使用jquery [autocomplete](https://jqueryui.com/autocomplete/)來建議對象b的名稱,並且用戶可以從結果中選擇 – Dawcars

+0

謝謝@Dawcars,但這只是下一步它漂亮向上。主要問題是如何在輸入名稱的同時存儲該對象的ID並維護一個仍然與表單關聯的良好模型驗證。 – Klumbe

回答

1

更新:獲取完整圖片後:

您想要虛擬屬性。然後你可以這樣做,@a.set_b_name=它會執行查找並應用這個名稱,或者你可以將該名稱存儲在一個實例var中,並對其使用驗證。 看到這些鏈接,瞭解更多詳細信息:)

老的回答是:

如果B不能找到,iebnil?那麼你犯了一個新的'b'對象不在數據庫中; b = B.new(name: params[:name])

+0

謝謝,但那不會解決我的問題(我已經嘗試過)。驗證失敗後,會收到錯誤消息,但該字段未突出顯示,輸入的文本消失。這是因爲該字段本身與該類型的對象關聯,而不是該名稱的字符串。我已更正了錯字,並通過周圍的標記擴展了_form.htm.erb。 – Klumbe

+1

好了,在這種情況下,您可以使用虛擬屬性,在類A:def b_name =(name)和def b_name併爲b_name添加驗證 - 請參閱此rails cast http://railscasts.com/episodes/167-more-on - 虛擬屬性?視圖= asciicast或這個https://stackoverflow.com/questions/20729962/rails-looking-up-foreign-key-id-using-virtual-attribute-failing問題的一些提示! – court3nay

+0

非常感謝@ court3nay!這正是我需要的。我現在可以從我的控制器中刪除這個糟糕的回調,一切看起來更乾淨和可預測。如果驗證失敗,我使用一個實例變量來保持狀態。由於我沒有寫入遷移來包含該名稱,因此不會被存儲。你想改變你的答案,以便我可以接受嗎? – Klumbe

相關問題