Rails

Rails4上でRailsチュートリアルの「簡単な検索フォーム」を実装する

More than 3 years have passed since last update.
  1. RailsってCRUD自動生成してくれるけど検索は作ってくれない。
  2. Railsチュートリアルに「検索機能」について解説が…!
  3. これでコピペ実装できるよー\(^o^)/
  4. って、このサンプルコードってRails3用だからコピペできないじゃないですかー()

ということでチュートリアルからリンクで紹介されている「簡単な検索フォーム(Simple searh form)」のサンプルコードを改良します。

Ruby on Rails チュートリアル
http://railstutorial.jp/chapters/following-users?version=4.0#sec-search

RAILSCAST.COM - #37 Simple Search Form
http://railscasts.com/episodes/37-simple-search-form

※通常の検索フォームを実装したい方はRansack Gemを使えば簡単に実装可能です。

activerecord-hackery/ransack · GitHub
https://github.com/activerecord-hackery/ransack
Ransackのススメ
http://qiita.com/nysalor/items/9a95d91f2b97a08b96b0


Precondition

Productなど Versionなど
Rails 4.1.0
Model project
Modelのカラム nameカラムが存在
route.rb Scaffolding、resources :projects状態

Procedure

#37 Simple Search Formのコメント欄でも既にRails4の場合を議論済みですが、(Ruby、Rails歴1週間程度の)自分の実装とは異なりました。
詳細は上記サイトのコメント欄を参照してください。
http://railscasts.com/episodes/37-simple-search-form?view=comments

Rails4用コード

Model

models/project.rb
class Project < ActiveRecord::Base
  def self.search(search) #self.でクラスメソッドとしている
    if search # Controllerから渡されたパラメータが!= nilの場合は、titleカラムを部分一致検索
      Project.where(['name LIKE ?', "%#{search}%"])
    else
      Project.all #全て表示。
    end
  end
end

View

project/index.html.erb
<%# 以下をScaffoldingしたindex.html.erbに追記する %>
<%= form_tag projects_path, :method => 'get' do %> <%# projects_pathはモデル名で読みかえること %>
  <p>
    <%= text_field_tag :search, params[:search] %>
    <%= submit_tag "Search", :name => nil %>
  </p>
<% end %>

Controller

projects_controller.rb
class ProjectsController < ApplicationController
  def index
    #ViewのFormで取得したパラメータをモデルに渡す
    @projects = Project.search(params[:search])
  end
end

サンプルコードとの差分概要

実際に変更が必要だった部分の概要です。

models/project.rb
def self.search(search)
  if search
    find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
  else
    find(:all)
  end
end

Rails4ではModel.findの仕様が大きく変更されているので、:all:conditionsは使えません。
それぞれ、Model.allModel.whereに置き換えました。
self.searchはRubyの仕様でクラスメソッド(JavaやC/C++でいうstaticメソッドみたいなもの)を宣言しています。
form_tagからメソッドを呼ぶので、インスタンスを渡さずとも検索ができるようにしています。

projects/index.rhtml
<% form_tag projects_path, :method => 'get' do %>
  <p>
    <%= text_field_tag :search, params[:search] %>
    <%= submit_tag "Search", :name => nil %>
  </p>
<% end %>

projects_pathはルート定義によって生成される自動ヘルパーなので、実際に利用するときはモデル名で置き換えてください。(例:モデル名Bookのときはbooks_path
その他、@projectなども同様です。

Note

Rails4上で動くことが確認できただけなので最適解ではないと思われます。
フォーム内の複数のビューヘルパーから引数を受けて、複数条件で検索する拡張は近日更新します。

Appendix

冒頭で記載済みですが、もう一度
今回は以下のサイトを参考にさせていただきました!!

Ruby on Rails チュートリアル
http://railstutorial.jp/chapters/following-users?version=4.0#sec-search

RAILSCAST.COM - #37 Simple Search Form
http://railscasts.com/episodes/37-simple-search-form

※通常の検索フォームを実装したい方はRansack Gemを使えば簡単に実装可能です。

activerecord-hackery/ransack · GitHub
https://github.com/activerecord-hackery/ransack
Ransackのススメ
http://qiita.com/nysalor/items/9a95d91f2b97a08b96b0