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 身份验证器未正确验证身份验证器在重定向后不会保留用户

在重定向期间将令牌从 API 传递到前端

必看|springmvc中的Model对象在重定向中的数据传递

Laravel 表单请求动态字段在重定向时消失

Instagram 客户端身份验证在重定向后缺少#access_token

ruby em-http-request在重定向上捕获和传递cookie