60

Booksというリソースがあります。ルートファイルに適切にリソースとしてリストされています。

新しいビューに標準を与える新しいアクションがあります。

@book = Book.new

モデルには、プレゼンスによって検証される属性がいくつかあるため、保存アクションが失敗すると、エラーが生成されます。

私のコントローラーでは:

@book = Book.create
...  # some logic
if @book.save
  redirect_to(@book)
else
  render :new
end

これはかなり標準的です。また、render:newを使用する理由は、オブジェクトがビューに戻され、エラーが報告されたり、フォームエントリが再入力されたりするためです。

これは機能しますが、(render:newを介して)フォームに返送されるたびにエラーが表示されますが、私のURLはINDEXURLです。

/books

それよりも

/books/new

そもそもそこから始めました。私はこの問題について他のいくつかの投稿を見ましたが、答えはありません。少なくとも、/ books / createにアクセスすると想定されます。これには、ビューファイルもあります(この場合はnewと同じです)。

私がすることができます:

# if the book isn't saved then
flash[:error] = "Errors!"
redirect_to new_book_path

ただし、@ bookデータは、フォームやアクションなどを保持するための全体的なポイントであるエラーメッセージとともに失われます。

通常、そのURLがすべての本を一覧表示するINDEXメソッドを呼び出すのに、render:newがインデックスアクションである/ booksに到達するのはなぜですか?

4

5 に答える 5

30

実際に、作成パスに移動します。これは、HTTPメソッドPOSTを使用しcreateて、パスがであるアクションにあります。/booksこれはインデックスパスと同じように見えます/booksが、インデックスパスはHTTPメソッドGETを使用しています。Railsルーティングコードは、呼び出すアクションを決定するときにメソッドを考慮に入れます。検証が失敗した後も、作成アクションは実行されていますが、newビューをレンダリングしています。少し紛らわしいですが、のような行render :newは実際には新しいアクションをまったく呼び出しません。まだ作成アクションを実行しており、Railsに新しいビューをレンダリングするように指示します。

于 2013-01-23T23:20:24.590 に答える
7

Rails-Tutorialから始めたばかりで、同じ問題が発生しました。解決策は単純です。フォームの送信後に同じURLが必要な場合(エラーあり)、新しいアクションと作成アクションを1つのアクションに組み合わせるだけです。

これが私のコードの一部であり、これを可能にします(誰かに役立つことを願っています^^)

ルート.rb(新しいアクションのポストルートを追加):

...
    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 %>
于 2014-01-02T11:27:10.987 に答える
3

まったく同じ質問があったので、これはいつか誰かを助けるかもしれません。私の解決策はまだ理想的ではありませんが、これが機能するためには基本的に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が表示され、フォームデータが保持されます。それでも、私はどういうわけかユーザーオブジェクトをフラッシュハッシュに入れるのが好きではありません。それが目的だとは思いません。誰かがそれを置くためのより良い場所を知っていますか?

于 2013-11-28T15:32:17.533 に答える
2

/books/newに投稿してリソースを作成しているので、そこにたどり着きません/books/。作成が失敗した場合、それは新しいアクションをレンダリングするだけであり、新しいアクションにリダイレクトすることはありません。@MrYoshijiが上で述べたように、新しいアクションにリダイレクトしてみることができますが、URLを変更するだけで、別のHTTPリクエストを作成してサーバーにラウンドトリップするため、これは実際には非効率的です。その時点で、それが重要な場合は、おそらくjavascriptを使用して変更することができます。

于 2013-01-24T03:43:01.393 に答える
1

これは、同じURLを使用することで修正できますが、newアクションとcreateアクションのメソッドが異なります。

ルートファイルでは、次のコードを使用できます。

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を選択してください。

于 2016-09-22T13:21:30.770 に答える