Booksというリソースがあります。それは私のルートファイルに適切にリソースとしてリストされています。
新しいアクションがあり、新しいビューに標準が与えられます。
@book = Book.new
モデルには、存在によって検証されるいくつかの属性があるため、保存アクションが失敗すると、エラーが生成されます。
私のコントローラーでは:
@book = Book.create
... # some logic
if @book.save
redirect_to(@book)
else
render :new
end
これはかなり標準的です。 render:newを使用する根拠は、オブジェクトがビューに戻され、エラーが報告されたり、フォームのエントリが再入力されたりするためです。
これは機能しますが、(render:newを介して)フォームに送り返されるたびにエラーが表示されますが、URLはINDEX URLです。
/books
のではなく
/books/new
そもそも私が始めたところです。この問題に関する他の投稿をいくつか見ましたが、回答はありません。少なくとも、/ books/createに移動すると想定しますが、これにもビューファイルがあります(この場合は新規と同じです)。
私がすることができます:
# if the book isn't saved then
flash[:error] = "Errors!"
redirect_to new_book_path
ただし、@ bookデータはエラーメッセージとともに失われます。これは、フォームやアクションなどの重要なポイントです。
通常、そのURLがすべての本をリストするINDEXメソッドを呼び出すときに、render:newが私のインデックスアクションである/ booksに私をランディングするのはなぜですか?
実際にはisが作成パスに移動します。これはcreate
アクションにあり、そのパスは/books
であり、HTTPメソッドPOSTを使用しています。これはインデックスパス/books
と同じように見えますが、インデックスパスはHTTPメソッドGETを使用しています。 Railsルーティングコードは、呼び出すアクションを決定するときにメソッドを考慮に入れます。検証に失敗した後も、作成アクションのままですが、new
をレンダリングしています少し混乱しますが、render :new
のような行は実際には新しいアクションをまったく呼び出さず、まだcreateアクションを実行しており、Railsに新しいビュー。
Rails-Tutorial で始めたばかりで、同じ問題がありました。解決策は単純です。(エラーのある)フォームを送信した後で同じURLが必要な場合は、新しいアクションとcreateアクションを1つのアクションに組み合わせます。
これがこれを可能にする私のコードの一部です(誰かを助けることを願っています^^)
routes.rb(new-actionのポストルートを追加):
...
resources :books
post "books/new"
...
コントローラ:
...
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
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 %>
ちょうど同じ質問があったので、これはいつか誰かを助けるかもしれません。これを機能させるには、基本的に3つの調整を行う必要がありますが、私の解決策はまだ理想的ではありません。
1)作成アクション:
if @book.save
redirect_to(@book)
else
flash[:book] = @book
redirect_to new_book_path
end
2)新しいアクションでは:
@book = flash[:book] ? Book.new(flash[:book]): Book.new
3)フラッシュハッシュを解析する場合は、必ずflash [:book]を除外してください。
->正しいURLが表示され、フォームデータは保持されます。それでも、どういうわけかユーザーオブジェクトをフラッシュハッシュに入れるのは好きではありません。それが目的ではないと思います。誰もがそれを置くためのより良い場所を知っていますか?
着陸しない/books/new
に投稿してリソースを作成しているため、/books/
。作成が失敗した場合、新しいアクションにリダイレクトするのではなく、新しいアクションをレンダリングするだけです。 @MrYoshijiが上で述べたように、新しいアクションにリダイレクトすることができますが、URLを変更するだけで、別のHTTPリクエストとサーバーへのラウンドトリップを作成するので、これは本当に非効率的です。その時点で問題がある場合は、おそらくJavaScriptを使用して変更できます。
同じURLを使用することで修正できますが、新しいアクションと作成アクションのメソッドは異なります。
ルートファイルでは、次のコードを使用できます。
resources :books do
get :common_path_string, on: :collection, action: :new
post :common_path_string, on: :collection, action: :create
end
これで、新しいページがURLでレンダリングされます
books/common_path_string
検証後にエラーが発生した場合でも、URLは同じです。
また、代わりに使用する形で
books_path
使用する
url: common_path_string_books_path, method: :post
お好みのcommon_path_stringを選択してください。