基本的に、いくつかのデフォルトの 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 モデルの新しいインスタンスを作成します。
でも
- テーブルをリフレッシュしていません。
- オブジェクトのインスタンスを 2 つ作成しているようです。
- それはパーシャルをレンダリングしていません(私も試みましたが、先頭のアンダースコアのない非パーシャルとしてです)。代わりに、
/books/<id>
以下に示すようにhtmlを返しています(ただし、2回実行しています)。
Dynamicdisplay ... ... ページをリロードしてソースを取得: /assets/books.css?body=1 ... ... 本が正常に作成されました。
タイトル: 老人と海
作者: ヘミングウェイ
編集 | 戻る Dynamicdisplay ... ... Book が正常に作成されました。タイトル: 老人と海
作者: ヘミングウェイ
編集 | 戻る私は近いと思います.javascriptを取得して適切な部分を取得し、適切な場所でDOMを更新するだけです。
ご協力いただきありがとうございます。