案外簡単にできたよ。
User.nameをインクリメンタルサーチする想定。
まずroutesに一覧表示用のindex
とAjax用のajax_user_list
を設定
config/routes.rb
resources :users, only: [:index] do
collection do
get :ajax_user_list
end
end
controllerに各アクションのメソッドを定義
controllers/users_controller.rb
def index
@users = User.all
end
def ajax_user_list
# search_by_nameはmodelに定義してあると思ってください
@users = User.search_by_name(params[:q])
end
viewはこんな感じ。Ajaxを使うので一覧表示部分はpartialで。
views/users/inde.html.erb
<p>検索名<p>
<input id="inc_search" type="text">
<div id='user_list'>
<%= render partial: 'user_list' %>
</div>
views/users/_user_list.html.erb
<table>
<thead>
<tr>
<th>ユーザー名</th>
<th>住所</th>
<th>電話番号</th>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.address %></td>
<td><%= user.phone_number %></td>
</tr>
<% end %>
</tbody>
</table>
ajax_user_list
アクションからレンダーされるのはコチラ。
$("#user_list")
内を新しい@users
でもってレンダーした_user_list.html.erb
に置き換える。
views/users/ajax_user_list.js.erb
$("#user_list").html("<%= escape_javascript(render 'user_list', users: @users) %>");
そしてjavascript(jQuery)はこんな感じ。
keyupのタイミングで前回の入力内容と比較し、違っていればajax実行。
でもあまりに連打されすぎると良くないので、最低でも500msは実行間隔を空ける。
コチラを参考にさせて頂きました。-> memo-mode javacriptでインクリメンタルサーチとjQueryのchange
var
preFunc = null,
preInput = '',
input = '',
ajaxPost = function(input)
{
$.ajax({
url: "ajax_user_list",
type: "GET",
data: ("q=" + input)
});
};
$('#inc_search').on('keyup', function() {
input = $.trim($(this).val()); //前後の不要な空白を削除
if(preInput !== input){
clearTimeout(preFunc);
preFunc = setTimeout(ajaxPost(input), 500);
}
preInput = input;
});