Rails:我无法在重定向中传递验证错误

Axl*_*Max 10 redirect routes ruby-on-rails

所以这是一个简单的项目,有产品,你可以竞标它们.想想eBay.

我按如下方式构建了项目:

$ rails new routetest
$ rails g scaffold product productname reserveprice:integer
$ rails g scaffold bid bidprice:integer product_id
Run Code Online (Sandbox Code Playgroud)

在我所包含的每个产品的"展示"视图中

  • 产品详情(由脚手架产生)
  • 到目前为止的出价列表
  • 使用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 %>
Run Code Online (Sandbox Code Playgroud)

单击"提交"时,将调用出价控制器#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
Run Code Online (Sandbox Code Playgroud)

因此,成功的出价会将用户返回到产品展示视图,并将记录添加到页面的出价部分.

我在出价模型中有validates_presence_of验证.因此,如果用户将出价字段留空,则验证将失败,并且出价控制器条件操作会将出价设置为新视图.包括错误消息.出价新视图包括脚手架生成的代码"<%if @ bid.errors.any?%> etc"

我实际想要做的不是渲染新操作,而是将用户带回产品展示页面,就像成功出价只是为了在产品展示页面上显示错误消息一样.基本上,这给用户留下了产品展示页面的感觉,而不是将它们扔到出价新页面.

我遇到的问题是如何将错误消息传回产品展示页面?如果我编辑上面的出价控制器创建操作代码并替换"渲染操作:'新''行

redirect_to "/products/#{@bid.product_id}"
Run Code Online (Sandbox Code Playgroud)

然后用户返回到页面,但不传递错误消息.我认为这是因为错误消息存储为新动作(出价控制器)的呈现的一部分

所以我的问题是如何实现我想做的事情?返回到产品show view并显示验证失败的错误消息.谢谢.

PS - 我叩头我需要添加脚手架生成的代码"<%@如果bid.errors.any%?> ..."代码产品展示的看法,但我还没有在代码中这样做上述,因为它会导致NilMethod错误,因为错误不是为方法存在而创建的.

Seb*_*ian 19

你想要这样的东西

redirect_to product_path(@bid.product_id), :flash => { :error => @bid.errors.full_messages.join(', ') }
Run Code Online (Sandbox Code Playgroud)

这将重定向到产品页面,但将错误作为Flash消息传递.


csc*_*oed 5

一个快速选项是showbids#create操作中呈现产品视图:

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'
Run Code Online (Sandbox Code Playgroud)

这将显示您想要的内容,但URL仍将显示为create可能令人困惑的出价路径.它可能有点难以阅读,因为我们必须在两个控制器之间反弹才能完成这一任务.

更好的选择可能是将出价创建操作移动到产品控制器中.要做到这一点,你可以......

/products/:id/create_bidin 添加新路由routes.rb:

resources :products do
  member do
    post 'create_bid'
  end
end
Run Code Online (Sandbox Code Playgroud)

在出价创建表单中使用此路线:

<h4>Make a Bid</h4>
<%= form_for(@bid, url: create_bid_product_path(@product)) do |b| %>
Run Code Online (Sandbox Code Playgroud)

在产品控制器中定义此操作:

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
Run Code Online (Sandbox Code Playgroud)

并将bid_params方法从出价控制器复制到产品控制器中.