Rails:我无法在重定向中传递验证错误
Posted
技术标签:
【中文标题】Rails:我无法在重定向中传递验证错误【英文标题】:Rails: I cant pass a validation error in a redirect 【发布时间】:2013-12-20 13:07:45 【问题描述】:所以这是一个简单的项目,其中有产品,您可以竞标。想想 eBay。
我构建的项目如下:
$ rails new routetest
$ rails g scaffold product productname reserveprice:integer
$ rails g scaffold bid bidprice:integer product_id
在我包含的每个产品的“显示”视图中
产品详细信息(由脚手架生成) 到目前为止的出价清单 使用 form_for 助手提交新出价的表单<p id="notice"><%= notice %></p>
<h2>Normal Products\Show Part</h2>
<p>
<strong>Productname:</strong>
<%= @product.productname %>
</p>
<p>
<strong>Reserveprice:</strong>
<%= @product.reserveprice %>
</p>
<%= link_to 'Back', products_path %>
<br /><br />
<h2>List of bids</h2>
<table>
<thead>
<tr>
<th>Product ID</th>
<th>Bid Price</th>
</tr>
</thead>
<tbody>
<% @bids.each do |bid| %>
<tr>
<td><%= bid.product_id %></td>
<td><%= bid.bidprice %></td>
</tr>
<% end %>
</tbody>
</table>
<br /><br />
<h2>Form For Bids</h2>
<h4>Make a Bid</h4>
<%= form_for(@bid) do |b| %>
<div class="field">
<%= b.number_field :bidprice %>
</div>
<div>
<%= b.hidden_field :product_id, :value => (params[:id]) %>
</div>
<div class="actions">
<%= b.submit %>
</div>
<% end %>
点击“提交”后,将调用出价控制器#create 操作。
def create
@bid = Bid.new(bid_params)
if @bid.save
redirect_to "/products/#@bid.product_id", notice: 'Bid was successfully created.'
else
render action: 'new'
end
end
因此,成功的出价会将用户返回到产品展示视图,并将记录添加到页面的出价部分。
我在出价模型中有一个 validates_presence_of 验证。因此,如果用户将 bids 字段留空,则验证失败,并且 bids 控制器 crate 操作会呈现 bids 新视图。包括错误消息。出价新视图包括脚手架生成的代码“ etc”
我真正想做的不是呈现新操作,而是让用户回到产品展示页面,就像在成功出价时所做的那样,只是为了在产品展示页面上显示错误消息。基本上,这让用户有一种留在产品展示页面上的感觉,而不是把它们扔到新的出价页面。
我遇到的问题是如何将错误消息传递回产品展示页面?如果我在上面编辑出价控制器创建操作代码并将“渲染操作:'new'”行替换为
redirect_to "/products/#@bid.product_id"
然后用户返回到页面但错误消息没有传递。我认为这是因为错误消息被存储为(投标控制器的)新操作呈现的一部分
所以我的问题是如何实现我想做的事情?返回产品显示视图并显示来自失败验证的错误消息。谢谢。
PS - 我知道我需要将脚手架生成的代码“ ...”代码添加到产品显示视图中,但我在上面的代码中没有这样做,因为它将导致 NilMethod 错误,因为该错误不是为存在于其上的方法而创建的。
【问题讨论】:
【参考方案1】:你想要这样的东西
redirect_to product_path(@bid.product_id), :flash => :error => @bid.errors.full_messages.join(', ')
这将重定向到产品页面,但将错误作为 Flash 消息传递。
【讨论】:
谢谢。这个答案确实让我得到了我需要的东西。我认为 cschroed 的答案也是一个很好的答案,并且引发了关于我的架构的更广泛的辩论,特别是我是否使用了正确的控制器,因为我正在使用的页面的 URL 对用户来说可能不是不直观的。这个答案更简单地解决了眼前的问题,在这种情况下更适合我。因此,请大家回复。 :-)【参考方案2】:一个快速的选择是在bids#create
操作中呈现show
产品视图:
if @bid.save
redirect_to "/products/#@bid.product_id", notice: 'Bid was successfully created.'
else
@product = Product.find(params[:bid][:product_id])
render template: 'products/show'
这将显示您想要的内容,但 URL 仍将显示为 create
出价路径,这可能会造成混淆。而且它可能有点难以阅读,因为我们必须在两个控制器之间弹跳才能完成这项任务。
更好的选择可能是将出价创建操作移至您的产品控制器中。为此,您可以...
在routes.rb
中为/products/:id/create_bid
添加新路由:
resources :products do
member do
post 'create_bid'
end
end
在您的出价创建表单中使用此路由:
<h4>Make a Bid</h4>
<%= form_for(@bid, url: create_bid_product_path(@product)) do |b| %>
在您的产品控制器中定义此操作:
def create_bid
@bid = Bid.new(bid_params)
if @bid.save
redirect_to product_url(params[:id]), notice: 'Bid was successfully created.'
else
@product = Product.find(params[:id])
render action: 'show'
end
end
然后将bid_params
方法从bids 控制器复制到products 控制器中。
【讨论】:
感谢您的回答。对此,我真的非常感激。它看起来是一个很好的解决方案,但我对 Rails 还是很陌生,而且它处于我理解的边缘。我会在周末测试解决方案,然后给你应有的信用。再次感谢您抽出宝贵时间回复。 我正在考虑实现这一点,但也许最好的选择是form_for [@product, @bid] do |bid|
并使用像这样的路由resources :products do resource :bid end
以上是关于Rails:我无法在重定向中传递验证错误的主要内容,如果未能解决你的问题,请参考以下文章
Symfony 身份验证器未正确验证身份验证器在重定向后不会保留用户
必看|springmvc中的Model对象在重定向中的数据传递