2016-01-24 32 views
1

我看了一下堆棧溢出的相關問題,但我不知道該如何解決這個問題。如何在Rails中使用一種形式創建相同模型的非嵌套多個記錄?

爲了闡明,

  1. 有三種型號:UserAB
  2. A包含3個記錄,每個記錄的字段爲p1_name,p1_score,p2_namep2_score。所以,A看起來像

-----------------------------------------------------------
id|p1_name|p1_score|p2_name|p2_score
id|p1_name|p1_score|p2_name|p2_score
id|p1_name|p1_score|p2_name|p2_score
-----------------------------------------------------------

  • B是其中的User提交他猜測什麼p1_name和從Ap2_name打進模型。所以,B樣子:
  • ---------------------------------------------------------------------------------
    id|user|a_id|p1_name|p1_score_guess|p2_name|p2_score_guess
    id|user|a_id|p1_name|p1_score_guess|p2_name|p2_score_guess
    id|user|a_id|p1_name|p1_score_guess|p2_name|p2_score_guess
    ---------------------------------------------------------------------------------

  • Bbelongs_toA如每個記錄由usera_id放在一起唯一確定。
  • 我需要爲模型B形式,由new行動的控制器處理,使用視圖views/B/new.html.erb

    這需要一個單一的形式表示3行,每行包含:

    • p1_name從模型A(如文本)
    • p1_score_guess用於從模型模型B(如號字段)
    • p2_nameB(as text)
    • p2_score_guess for model B(as number field)

    使用一個提交按鈕提交後,需要將3條記錄中每條記錄的上述數據提交給控制器,並創建多條記錄B

    我以前沒有在Rails 4.2.5中遇到過這種要求,也不知道該怎麼去做。自兩天以來,我一直在嘗試這樣做,首先使用simple_form,但似乎並不支持這一點(或者我無法創建一個),然後使用Rails Forms。

    它已經成爲棘手的我,因爲我必須展示從視圖模型Ap1_namep2_name形式下以及也使用它,來填充模型BB s控制器需要同時採取p1_name,p2_namep1_score_guess,p2_score_guess。由於a_id對於每一行都是不同的,因此需要考慮這一點(進一步使我無法確定這一點)。

    +1

    可能需要'form_tag',而不是'form_for',因爲後者對與一個單一的定製工作目的。在控制器中,您需要創建不同對象的代碼,並且每個這樣的對象都會從'params'中提取相關信息。 – tillmo

    +1

    你爲什麼要在'A'和'B'中存儲'p1_name'? –

    回答

    1

    怎麼樣:

    <%= form_for :bs, url: bs_path do |f| %> 
        <% @as.each do |a| %> 
        <%= f.fields_for "[#{a.id}]", B.new do |afields| %> 
         <%= a.p1_name %> 
         <%= afields.text_field :p1_score_guess %> 
         <%= a.p2_name %> 
         <%= afields.text_field :p2_score_guess %> 
        <% end -%> 
        <% end -%> 
        <%= f.submit 'save' %> 
    <% end -%> 
    

    而且在控制你通過PARAMS迭代[:A_S]

    def create 
        bs_params.each do |a_id, b_attributes| 
        B.create b_attributes.merge(a_id: a_id, user: current_user) 
        end 
    end 
    

    def bs_params 
        params.require(:bs).permit(allowed_a_s) 
    end 
    
    def allowed_a_s 
        Hash[a_ids.map {|id| [id.to_s, [:p1_score_guess, :p2_score_guess]]}] 
    end 
    
    def a_ids 
        A.pluck(:id) 
    end 
    

    只是爲了顯示你我的測試用例 - 我分配給@as:

    @as = [A.new(id: 1, p1_name: 'p11', p2_name: 'p12'), A.new(id: 2, p1_name: 'p21', p2_name: 'p22'), A.new(id: 3, p1_name: 'p31', p2_name: 'p32')] 
    

    ,並設定爲a_ids靜:

    def a_ids 
        %w[1 2 3] 
    end 
    

    ,並獲得關於用於與輸入1,2,3,4,5,6 bs_params一個調試器猜測:

    => { 
        "1"=>{"p1_score_guess"=>"1", "p2_score_guess"=>"2"}, 
        "2"=>{"p1_score_guess"=>"3", "p2_score_guess"=>"4"}, 
        "3"=>{"p1_score_guess"=>"5", "p2_score_guess"=>"6"} 
    } 
    

    更新:由於上面的代碼不檢查驗證,我再試一次(此時未測試 - 對不起):

    <%= form_for :bs, url: bs_path do |f| %> 
        <% @bs.each do |a, b| %> 
        <%= f.fields_for "[#{a.id}]", b do |afields| %> 
         <%= a.p1_name %> 
         <%= afields.text_field :p1_score_guess %> 
         <%= a.p2_name %> 
         <%= afields.text_field :p2_score_guess %> 
        <% end -%> 
        <% end -%> 
        <%= f.submit 'save' %> 
    <% end -%> 
    

    並在控制器做:

    def new 
        @bs = Hash[a_ids.map { |a_id| [a_id, B.new] }] 
    end 
    
    def create 
        @bs = {} 
        bs_params.each do |a_id, b_attributes| 
        @bs[a_id] = B.new b_attributes.merge(a_id: a_id, user: current_user) 
        end 
        @bs.values.each(&:valid?) # to ensure, all errors are assigned - and not finding one will stop to check for any other 
        if @bs.values.all?(&:valid?) 
        @bs.values.each &:save 
        redirect_to root_path 
        else 
        render :new 
        end 
    end 
    

    和bs_params,allowod_a_s和a_ids如上

    +0

    謝謝@bpieck,輝煌的回答,非常明確。我正在尋找類似的東西,只是稍微改變了它對我的工作。 – agusgambina

    +0

    唯一不適合我的是對類的字段進行原始驗證,例如,如果一個字段需要存在,則忽略該驗證。我犯了一個錯誤嗎? – agusgambina

    +1

    你的意思是,它沒有顯示?或者他們真的被忽略並創建實例,但它們應該是無效的? 自從創建檢查驗證以來,最後發出聲音。如果你的意思是第一個:是的,你是對的。這段代碼甚至沒有檢查無效的bs,知道要再次渲染:new。當然,這是可能的 - 一些更多的努力。我可以嘗試在當天晚些時候更新我的答案。 – bpieck

    相關問題