失去了对验证失败的关注,保存了嵌套模型

时间:2015-05-29 03:48:13

标签: ruby-on-rails

失去理智。一直在阅读文档和示例,并且已经能够解决这个问题。我可能遗漏了一些非常明显的东西。

模型

class Item < ActiveRecord::Base

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

    validates :collection, :presence => true
end

class ItemOwnership < ActiveRecord::Base
    belongs_to  :item
    belongs_to  :user

    validates :user_id, :presence => true
    validates :item_id, :presence => true
end

class User < ActiveRecord::Base
    has_many :item_ownerships
end

控制器

class ItemsController < ApplicationController

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

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

    def create
        @item = @collection.items.build(item_params)
        @item_ownership = @item.item_ownerships.build(:user => current_user, :item => @item)
        #byebug

        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 item_params
        params.require(:item).permit(:name,
            item_ownerships_attributes: [:id, :owned, :user, :item])
    end
end

查看

<%= 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" %>
                    <span id="forgot_my_password" class="right-justify">
                        <%= link_to "cancel", collection_items_path(@collection) %>
                    </span>
                </div>
            <% end %>

当我提交表单时,它失败并出现以下错误:

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

使用调试器,我在保存之前查看了@item和@item_ownerships中的值,它们如下:

(byebug) @item
#<Item id: nil, name: "test", created_at: nil, updated_at: nil, collection_id: 71>
(byebug) @item_ownership
#<ItemOwnership id: nil, user_id: 52, item_id: nil, owned: nil, created_at: nil, updated_at: nil>

我假设在提交表单时,实例化@item,将填充并保存关联中的所有值。

我将继续尝试找到类似的问题或文章,但任何帮助将不胜感激。

更新

值得注意的是,如果我删除了复选框视图中的fields_for,则会保存两个模型而不会出现验证错误。

Post Parameters provided as requested:
{"utf8"=>"✓",
 "authenticity_token"=>"TMPET9Oq9eH8vbk7REVnmKEB5X8BqycSkio5XXdwsLSVqs8/Soz+uMyGJJZCnpOQgbwBESnkKmLts8oQKKiG/Q==",
 "item"=>{"name"=>"testg",
 "item_ownerships_attributes"=>{"0"=>{"owned"=>"1"}}},
 "commit"=>"Save",
 "collection_id"=>"71"}

1 个答案:

答案 0 :(得分:0)

我花了一段时间,但我终于明白了。我完全误解了嵌套模型是如何工作的。

在'create'中,两个模型(items和item_ownerships_都是使用行中的item_params构建的:

@item = @collection.items.build(item_params)

结果,实例化@item_ownerships的以下行是不必要的。验证失败有两种方式:

1)用户失败,因为没有通过item_params传递的用户信息 2)项目失败,因为我应该使用:inverse_of执行验证(参考这篇文章:http://michaelwelburn.com/2014/02/10/rails-4-nested-object-creation-and-parent-presence-validation-error/

无论如何,感谢任何回复并正在考虑回应的人。