1

基本的に、いくつかのデフォルトの Rails ビューを 1 つに結合し、javascript (実際には coffeescript) を使用して、ページのリロードを行う必要がないようにしています。基本的に、標準で生成された新しい関数とインデックス関数に含まれるものを組み合わせて、新しいオブジェクトが作成されたときにページを更新せずにリストを更新したいと考えています。

チュートリアルは見つけられませんでしたが、これは多くのアプリケーションで一般的な手法だと思います。ここ StackOverflow などのヘルプから解決策をつなぎ合わせようとしましたが、すべてが機能するわけではありません。簡単な Rails プロジェクトを作成することにしました。これは、それを理解するための助けが必要であり、他の人が私のアプリケーションに固有のことで行き詰まることなく従うことができるようにするためです。

以下はコードです。たくさんありますが、そのほとんどは標準で、レールによって生成されます。Rails プロジェクト (rails 3.2) を作成し、タイトルと著者の 2 つの文字列を持つ Book のスキャフォールディング (モデル、コントローラー、ビュー) を生成しました。次に、以下のようにコードをさらに変更しました。

Gemfile含まれていることを確認しましたjquery-rails

gem 'rails', '3.2.7'

....

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'

次に、リストアクションの新しいルートを追加しましたRoutes.rb

...
match 'books/list' => 'books#list'
resources :books

続いて、アクションをコントローラーに追加しますbooks_controller.rb

...
def list
  @all_books = Book.all
  @book = Book.new

  respond_to do |format|
    format.html # new.html.erb
    format.js { render 'new_book_row', :format => :html, :layout => false }
    format.json { render json: @book }
  end
end

私は@book、新しい本を保持する@all_booksためと、すべての本を一覧表示するテーブルとして使用するための両方を用意するようにしています。

このformat.js行は、新しいテーブル行 (以下に示すファイル) を html としてレンダリングする必要があります (レイアウトを false に設定して、アプリケーション ビュー ラッパーではなく、部分のみをレンダリングします)。

対応するビューとパーシャルを作成しますviews/books/

list.html.erb含む

<h1>List Books</h1>

<h3>Add Book</h3>
<%= render 'new_book_form' %>

<h3>My Books</h3>
<%= render 'book_list' %>

<%= link_to 'Back', books_path %>

私はそれを 2 つのパーシャルに分割しましたが、明らかにパーシャルは上のビューに折りたたむことができます。

_new_book_form.html.erbパーシャルは以下の通り

<%= form_for @book, :remote => true, :html => { 'data-type' => :html } do |f| %>
  <% if @book.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>

      <ul>
      <% @book.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :author %><br />
    <%= f.text_field :author %>
  </div>
  <div class="add-button" id='add-button'>
    <%= f.submit %>
  </div>
<% end %>

form_for 呼び出しを除いて、すべて標準生成コードです。http://tech.thereq.com/post/18910961502/rails-3-using-form-remote-true-with-jquery-ujs:remote => trueで説明されているように設定して、ajax呼び出しにしました。応答がスクリプトではなくhtmlとして返されるように設定する必要がありました。'data-type' => :html

_book_list.html.erbパーシャルもすべて標準の生成コードです

<table id='book-list'>
  <tr>
    <th>Title</th>
    <th>Author</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @all_books.each do |book| %>
  <tr>
    <td><%= book.title %></td>
    <td><%= book.author %></td>
    <td><%= link_to 'Show', book %></td>
    <td><%= link_to 'Edit', edit_book_path(book) %></td>
    <td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
</table>

また、_new_book_row.html.erb簡単です

<tr>
  <td><%= new_book.title %></td>
  <td><%= new_book.author %></td>
  <td><%= link_to 'Show', new_book %></td>
  <td><%= link_to 'Edit', edit_book_path(new_book) %></td>
  <td><%= link_to 'Destroy', new_book, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>

魔法は入っていますbooks.js.coffee

# don't load javascript until the whole page is laid out
$(document).ready ->

  # To save the book without reloading the page
  $('#add-button').click ->
    $(this).parents("form").submit()


  $('form#new_book').on 'ajax:success',  (xhr, data, status) ->
    $('#book-list').append(data).show()

ページが読み込まれるまで、javascript の読み込みを追加するのを遅らせる必要があることがわかりました。


/books/list/books/<id>ページを正しく表示し、ボタンはデフォルトページをレンダリングせずに、フォーム フィールドを持つ Book モデルの新しいインスタンスを作成します。

でも

  1. テーブルをリフレッシュしていません。
  2. オブジェクトのインスタンスを 2 つ作成しているようです。
  3. それはパーシャルをレンダリングしていません(私も試みましたが、先頭のアンダースコアのない非パーシャルとしてです)。代わりに、/books/<id>以下に示すようにhtmlを返しています(ただし、2回実行しています)。

Dynamicdisplay ... ... ページをリロードしてソースを取得: /assets/books.css?body=1 ... ... 本が正常に作成されました。

タイトル: 老人と海

作者: ヘミングウェイ

編集 | 戻る Dynamicdisplay ... ... Book が正常に作成されました。

タイトル: 老人と海

作者: ヘミングウェイ

編集 | 戻る

私は近いと思います.javascriptを取得して適切な部分を取得し、適切な場所でDOMを更新するだけです。

ご協力いただきありがとうございます。

4

1 に答える 1

2

2: CoffeeScript でフォーム送信をトリガーしているため、2 つの本が作成されていると思います。

$('#add-button').click ->
  $(this).parents("form").submit()

Rails は自動的に同じことを行います (フォームに remote プロパティを設定しているため、Rails は Ajax によってフォームのコンテンツを投稿するために必要なクライアント側スクリプトを挿入します)。したがって、送信ボタンのクリックごとに 2 つの要求があります。

create3:新しいオブジェクトを渡したform_forので、listアクションが Ajax リクエストによって呼び出されないため、フォームはデフォルトでリクエストをアクションに送信します。生成されcreateたアクションは新しいオブジェクトを保存し、アクションにリダイレクトするshowため、/books/:id の html が返されます。フォームを別のアクションに投稿する必要がある場合は、urlオプション to を指定することで実行できますform_for。例えば:

<%= form_for @book, :remote => true, :html => { 'data-type' => :html }, :url => { :action => :list } do |f| %>

1: これはおそらく 3 に関連しています。Ajax リクエストが期待するテーブル行を返していません。3 を修正したら、問題の診断を開始して、このイベントが呼び出されているかどうかを確認できます。

$('form#new_book').on 'ajax:success',  (xhr, data, status) ->
  console.log xhr, data, status
  $('#book-list').append(data).show()

Rails ガイドは通常、チュートリアルを開始するのに適した場所ですが、Ajax ガイドは少し古くなっているように見えます。Rails で Ajax を行う方法は、少し混乱する可能性があります。Rails Ajax リクエストは、多くの場合、js.erb テンプレートをレンダリングして JavaScript を返します (CoffeeScript も機能します)。これは、応答がブラウザーに到着するとすぐに実行されます。そうすれば、jQuery Ajax イベントへのフックについて心配する必要がないため、その方法を検討することをお勧めします。Rails チュートリアルには例があります。

于 2012-08-13T19:35:26.720 に答える