在parent中提交accepts_nested_attributes和验证失败

时间:2015-05-28 17:01:09

标签: ruby-on-rails ruby activerecord

提前感谢您的帮助。

这可能会有点长。

设置 型号:

class Collection < ActiveRecord::Base

    has_many    :collection_ownerships
    has_many    :items
    has_many    :users, :through => :collection_ownerships


    validates :title, presence: true, length: { maximum: 25 }
    validates :description, length: { maximum: 100 }
end

class Item < ActiveRecord::Base

    belongs_to :collection
    has_many :item_ownerships, :dependent => :destroy
    accepts_nested_attributes_for :item_ownerships

    validates :name, :presence => true, length: { maximum: 50 }
    validates :collection, :presence => true

end

class ItemOwnership < ActiveRecord::Base

    belongs_to  :item
    belongs_to  :user

    validates :user, :presence => true
    validates :item, :presence => true
end

控制器

class ItemsController < ApplicationController

    before_action :authenticate_user!
    before_filter(:except => :toggle_item_owned_state) do
        @collection = current_user.collections.find(params[:collection_id])
        @item_list = @collection.items
    end

    def toggle_item_owned_state

        @item = Item.find_by_id(params[:item_id])
        @io = @item.item_ownerships.find_by_user_id(current_user)

        @result = @io.update_attributes(:owned => @io.owned? ? false : true)

        respond_to do |format|
            if @result
                format.html { }
                format.js {} 
            else
                format.html { }
                format.js {} 
            end
        end
    end

    def index
    end

    def new
        @item = @collection.items.new
        @item_ownership = @item.item_ownerships.build(:owned => true, :user => current_user, :item => @item)
    end

    def create

        @item ||= @collection.items.new(item_params)
        @item_ownership ||= @item.item_ownerships.build(:user => current_user, :item => item)

        if @item.save
            redirect_to collection_items_path(@collection)
        else
            flash.now[:alert] = "There was a problem saving this item."
            render "new"
        end
    end

    def edit
        @item = @collection.items.find_by_id(params[:id])
    end

    def update
        @item = @collection.items.find_by_id(params[:id])


        if @item.update_attributes(item_params)
            redirect_to collection_items_path(@collection)
        else
            flash.now[:alert] = "There was a problem saving this item."
            render "edit"
        end
    end

    def item_params
        params.require(:item).permit(:name,
            item_ownerships_attributes: [:id, :owned ])
    end
end

视图

<div class="row">
    <span class="col-sm-12">
        <div id="add_item">
            <%= form_for [@collection, @item] do |f| %>
            <div class="form-group <%= 'has-error has-feedback' if @item.errors[:name].present? %>">
                <label class="sr-only" for="item_name">Item Name</label>
                <%= f.text_field :name, :autofocus => true, :placeholder => "Item Name", :class => "form-control", :'aria-describedBy' => "itemNameBlock" %>
                <% if @item.errors[:name].present? %>
                        <span id="itemNameBlock" class="error">Item <%= @item.errors[:name].first %></span>
                <% end %>
                <%= f.fields_for :item_ownerships do |io| %>
                    <%= io.check_box :owned %> Owned
                <% end %>
            </div>
            <div id="signin_button_row">
                <%= f.submit "Save", :class => "form-control green_button" %>
                <span id="forgot_my_password" class="right-justify">
                    <%= link_to "cancel", collection_items_path(@collection), :class => "new_colors terms" %>
                </span>
            </div>
            <% end %>
        </div>
    </span>
</div>

问题的症状: 当我在失败的情况下提交表单(即没有提供名称)时,表单当前检测到验证并显示错误,但是,我现在在表单中出现两个名为“own”的复选框。每个失败的提交都会添加一个附加复选框(根据附加图像)。enter image description here

有人可以帮忙吗?

更新
这个问题转向了奇怪的问题。我没有改变任何东西(我知道,我知道,你不相信)除了重新启动服务器,但现在即使有效数据也没有保存。我收到验证错误说:

验证失败:项目所有权用户不能为空,项目所有权项目不能为空

2 个答案:

答案 0 :(得分:2)

在您的控制器create操作中

def create
    @item ||= @collection.items.new(item_params)
    @item_ownership ||= @item.item_ownerships.build(:user => current_user)

    if @item.save
        redirect_to collection_items_path(@collection)
    else
        flash.now[:alert] = "There was a problem saving this item."
        render "new"
    end
end

分配@item_ownership时,问题出在第三行,此变量此时始终为空,因此执行=之后的代码。 @item.item_ownerships.build(:user => current_user)始终构建新的item_ownership并将其存储到@item实例中。所以在第一次调用create之后,你将有两个item_ownerships首先来自表单,第二个是新创建的。如果验证失败并且您再次发送表单,则您将从新创建的表单中有三个item_ownerships两个实例等。

答案 1 :(得分:0)

@edariedl在解决初始响应方面处于正确的轨道上。第二行完全没必要。

我在另一个问题中提到的更新中提到的第二个问题:Losing mind over validation failure saving nested models