rcd*_*rcd 57 forms controller routes ruby-on-rails view
我有一个名为Books的资源.它在我的路线文件中正确列为资源.
我有一个新动作,它给新视图标准:
@book = Book.new
Run Code Online (Sandbox Code Playgroud)
在模型上,有一些属性通过在线验证,因此如果保存操作失败,将生成错误.
在我的控制器中:
@book = Book.create
...  # some logic
if @book.save
  redirect_to(@book)
else
  render :new
end
Run Code Online (Sandbox Code Playgroud)
这是非常标准的; 以及使用render的基本原理:new是为了将对象传递回视图,并且可以报告错误,重新填充表单,等等.
这是有效的,除了每次我发送回表单(通过渲染:新),我的错误显示,但我的URL是INDEX URL,这是
/books
Run Code Online (Sandbox Code Playgroud)
而不是
/books/new
Run Code Online (Sandbox Code Playgroud)
这是我从一开始就开始的地方.我看过其他几个关于这个问题的帖子,但没有答案.至少,人们会认为它会落在/ books/create,我也有一个视图文件(在这种情况下与new相同).
我可以做这个:
# if the book isn't saved then
flash[:error] = "Errors!"
redirect_to new_book_path
Run Code Online (Sandbox Code Playgroud)
但随后@book数据以及错误消息将丢失,这是表单和操作等的全部要点.
为什么渲染:新的登陆我的/ books,我的索引动作,通常该URL调用INDEX方法,列出所有书籍?
Jim*_*art 27
它实际上是将您发送到创建路径.它位于create动作中,其路径是/books使用HTTP方法POST.这看起来与索引路径相同/books,但索引路径使用HTTP方法GET.在确定要调用的操作时,rails路由代码会考虑该方法.验证失败后,您仍处于创建操作中,但您正在渲染new视图.这有点令人困惑,但是一条线路render :new根本就没有实际调用新的动作; 它仍在运行create动作,它告诉Rails渲染新视图.
我刚开始使用Rails-Tutorial并遇到了同样的问题.解决方案很简单:如果在提交表单(有错误)后需要相同的URL,只需在一个操作中组合new和create操作即可.
这是我的代码的一部分,这使得这成为可能(希望它有助于某人^^)
routes.rb(为new-action添加post-route):
...
    resources :books
    post "books/new"
...
Run Code Online (Sandbox Code Playgroud)
控制器:
...
def create
    @book = Book.new(book_params)
    if @book.save
        # save was successful
        print "Book saved!"
        else
        # If we have errors render the form again   
        render 'new'
    end
end
def new 
    if book_params
        # If data submitted already by the form we call the create method
        create
        return
    end
    @book = Book.new
    render 'new' # call it explicit
end
private
def book_params
    if params[:book].nil?  || params[:book].empty?
        return false
    else
        return params.require(:book).permit(:title, :isbn, :price)
    end
end
Run Code Online (Sandbox Code Playgroud)
new.html.erb:
<%= form_for @book, :url => {:action => :new} do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title %>
  <%= f.label :isbn %>
  <%= f.text_field :isbn %>
  <%= f.label :price %>
  <%= f.password_field :price %>
  <%= f.submit "Save book" %>
<% end %>
Run Code Online (Sandbox Code Playgroud)