【问题标题】:One to Many Association Object Will Not Save一对多关联对象不会保存
【发布时间】:2014-12-01 00:47:10
【问题描述】:

我在我的两个模型中设置了 has_many belongs_to 关系,并按照 Ryan Bates 的截屏视频了解如何设置控制器。当我提交表单以创建新对象时,嵌套对象由于某种原因没有保存。这是我的模型:

class Auction < ActiveRecord::Base
  has_many :bids, dependent: :destroy
end

class Bid < ActiveRecord::Base
  belongs_to :auction
  belongs_to :user
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :auction_id, presence: true
end 

还有我的嵌套对象控制器:

  class BidsController < ApplicationController
  def index
    @auction = Auction.find(params[:auction_id])
    @bids = @auction.bids
  end

  def new
    @auction = Auction.find(params[:auction_id])
    @bid = @auction.bids.build
  end

  def create
     @auction = Auction.find(params[:auction_id])
    @bid = @auction.bids.create(params[:bid])
    @bid.save
    if @bid.save
      flash[:success] = "Bid has been successfully placed."
    else
      @bid.errors
      render 'new'
    end
  end

  def destroy
     @auction = Auction.find(params[:auction_id])
     @bid = @auction.bids.find
    @bid.destroy
    flash[:notice] = "Successfully destroyed Bid."
    redirect_to auction_url(@bid.article_id)
  end
end

我的表格:

<h1>Create a New Bid</h1>
<%= form_for ([@auction, @bid]) do |f|%>
<p>
<%= f.submit %>
</p>
<%end%>

和我的终端输出:

Started POST "/auctions/1/bids" for 127.0.0.1 at 2014-11-30 17:59:13 -0600
Processing by BidsController#create as HTML
  Parameters: {"utf8"=>"✓",   "authenticity_token"=>"dkZBcab1rgZjtJGF3LAJ//exK6liglZ0Fy4mg7HWEt0=", "commit"=>"Create Bid", "auction_id"=>"1"}
  Auction Load (0.1ms)  SELECT  "auctions".* FROM "auctions"  WHERE "auctions"."id" = ? LIMIT 1  [["id", 1]]
  (0.0ms)  begin transaction
  (0.0ms)  commit transaction
  (0.0ms)  begin transaction
  (0.0ms)  rollback transaction
  (0.0ms)  begin transaction
  (0.0ms)  rollback transaction

感谢您的帮助。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    您的出价对象需要user_id,因为您在类定义中有validates :user_id, presence: true

    但是,当您在控制器中调用 @bid.save 时,@bid 没有 user_id 值,因此事务会因为验证失败而回滚。

    在调用@bid.save 之后,您应该能够通过查看创建操作中的@bid.errors.full_messages 来看到这一点。 (如果您还不熟悉 pry gem,请查看它……这将是让您进行此检查的完美工具。)

    尝试用这个替换您的创建操作:

    def create
      @auction = Auction.find(params[:auction_id])
      @bid = @auction.bids.new params[:bid].merge(user_id: current_user.id)
      if @bid.save
        flash[:success] = "Bid has been successfully placed."
      else
        flash[:error] = @bid.errors.full_messages.join('. ')
        render 'new'
      end
    end
    

    这假设您可以访问控制器中的当前用户current_user。设计和其他流行的身份验证解决方案提供此功能,或者您可以自己这样做。

    另请注意,您的原始代码尝试将@bid 写入数据库 3 次,这比您需要的多两倍。以下是违规行:

    def create 
      ...
      @bid = @auction.bids.create(params[:bid])
      @bid.save
      if @bid.save
      ...
    

    #create 实例化一个对象并尝试将其写入数据库。在我上面的代码中,我将@auction.bids.create(params...) 替换为@auction.bids.new(params...)。这会初始化 @bid 而不会尝试将其持久化到数据库中。

    我还删除了第一个 @bid.save,因为它下面的行 if @bid.save 将完成同样的事情。

    最后,你的@bid.errors 行没有做任何有用的事情。我对其进行了修改以将错误消息存储在您的闪存哈希中,然后您可以在视图中使用它向用户显示错误。

    【讨论】:

    • 很好的回应,约翰。谢谢你的帮助!是的,我确实看到没有必要将这些额外的时间写入数据库。感谢您指出这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    相关资源
    最近更新 更多