2017-01-09 84 views
1

我想創建一個嵌套的窗體,其中有選項和子選項,都來自同一個模型稱爲選項。這裏是文件的內容:Rails嵌套窗體與繭。使用模型的屬性

型號:

class Option < ApplicationRecord 
    belongs_to :activity 
    has_many :option_students 
    has_many :students, through: :option_students 

    has_many :suboptions, 
    class_name: "Option", 
    foreign_key: "option_id" 

    belongs_to :parent, 
    class_name: "Option", 
    optional: true, 
    foreign_key: "option_id" 

    accepts_nested_attributes_for :suboptions, 

    reject_if: ->(attrs) { attrs['name'].blank? } 

    validates :name, presence: true 
end 

控制器:

class OptionsController < ApplicationController 
    include StrongParamsHolder 

    def index 
    @options = Option.where(option_id: nil) 
    end 

    def show 
    @option = Option.find(params[:id]) 
    end 

    def new 
    @option = Option.new() 
    1.times { @option.suboptions.build} 
    end 

    def create 
    @option = Option.new(option_params) 
    if @option.save 
     redirect_to options_path 
    else 
     render :new 
    end 
    end 

    def edit 
    @option = Option.find(params[:id]) 
    end 

    def update 
    @option = Option.find(params[:id]) 
    if @option.update_attributes(option_params) 
     redirect_to options_path(@option.id) 
    else 
     render :edit 
    end 
    end 

    def destroy 
    @option = Option.find(params[:id]) 
    @option.destroy 
    redirect_to options_path 
    end 

end 

_form.html.erb:

<%= form_for @option do |f| %> 

    <p> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %><br> 
    <%= f.label :activity %><br> 
    <%= select_tag "option[activity_id]", options_for_select(activity_array) %><br> 
    </p> 

    <div> 
    <div id="suboptions"> 
     <%= f.fields_for :suboptions do |suboption| %> 
     <%= render 'suboption_fields', f: suboption %> 
     <% end %> 

     <div class="links"> 
     <%= link_to_add_association 'add suboption', f, :suboptions %> 
     </div> 
    </div> 
    </div> 

    <p> 
    <%= f.submit "Send" %> 
    </p> 
<% end %> 

_suboption_fields.html.erb

<div class="nested-fields"> 
    <%= f.label :suboption %><br> 
    <%= f.text_field :name %> 
    <%= link_to_remove_association "X", f %> 
</div> 

StrongParamsHolder:

def option_params 
    params.require(:option).permit(:name, :activity_id, :students_ids => [], suboptions_attributes: [:id, :name]) 
end 

的視圖創建正確,但不節能。它轉到創建控制器上的「render:new」。我認爲這應該是params的問題,但我不確定是什麼。

回答

3

由於驗證失敗可能未保存。如果您正在使用rails 5,則belongs_to現在更加嚴格,並且爲了能夠保存嵌套參數,您需要使關聯之間的連接/關係顯式化。

所以恕我直言,如果添加inverse_of到您的關係如下它將工作:

has_many :suboptions, 
    class_name: "Option", 
    foreign_key: "option_id", 
    inverse_of: :parent 

belongs_to :parent, 
    class_name: "Option", 
    optional: true, 
    foreign_key: "option_id" 
    inverse_of: :suboptions 

如果另一個驗證失敗,它也可以幫助列出表單中的錯誤(例如像@option.errors.full_messages.inspect會幫助:)

另一方面:我將數據庫中的option_id字段重命名爲parent_id,因爲這更清楚地表達了它的含義。