我在我的两个模型中建立了一个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
感谢您的帮助。
答案 0 :(得分:2)
您的出价对象需要user_id
,因为您在类定义中有validates :user_id, presence: true
。
但是,当您在控制器中调用@bid.save
时,@bid
没有user_id
值,因此由于验证失败而导致事务回滚。
在调用@bid.errors.full_messages
后,您应该可以通过查看创建操作中的@bid.save
来查看此内容。 (如果您还不熟悉它,请查看撬宝石......这将是一个让您进行此检查的完美工具。)
尝试用以下方法替换您的创建操作:
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
。设计和其他流行的auth解决方案提供此功能,或者您可以自己提供。
另请注意,您的原始代码会尝试将@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
行没有做任何有用的事情。我修改它以将错误消息存储在您的flash哈希中,然后您可以在视图中使用它来向用户显示错误。