• WebCamp_インタビュー
    【WebCamp受講生インタビュー】起業準備中にCEOが気がついたプログラミングスキルの重要性とは?
    2017.12.25
  • WebCampPro_インタビュー
    自分で稼ぐ力をつけるため、新卒5年目の営業マンがエンジニアに転職!【WebCampPro転職者インタビュー】
    2018.02.02
  • WebCamp_インタビュー
    「自信の持てるスキルを得たい!」内定辞退した女子大生がプログラミングを学習したワケ。
    2018.04.28
  • WebCampPro_インタビュー
    未経験31歳からエンジニア転職を実現【実際に聞いてみた】
    2017.04.01
  • WebCamp_インタビュー
    【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
    2018.01.15
  • WebCampPro_インタビュー
    未経験でも寿司職人からWebデザイナーになった!ホスピタリティでスクールを支える宮脇トレーナー
    2017.05.26
  • WebCamp_インタビュー
    【卒業生インタビュー】台湾で月間100万UUの訪日旅行メディアを手掛けるCEOが、プログラミングを学んで得たものとは?
    2018.01.15
  • WebCamp_インタビュー
    時間や場所にとらわれず自由に働くために必要なスキルとは?【WebCamp卒業生インタビュー】
    2018.01.26
  • WebCamp_インタビュー
    “未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
    2017.10.04
  • WebCampPro_インタビュー
    未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
    2018.03.10
  • WebCamp_インタビュー
    「1カ月頑張ればこの先が見えてくる」地元メディアを立ち上げたママさん
    2017.07.20

◆当サイトで人気のプログラミング教室のおすすめランキングはこちら!
プログラミングは独学では非効率で、時間を無駄にするリスクがあります。効率的なカリキュラムで学べるスクールを受講しましょう。

WEBCAMP【マンツーマンサポート】1ヶ月短期集中でプログラミングを学ぶスクール
1ヶ月通い放題・メンター常駐の教室環境でプログラミングを学びたい方!
TechAcademyオンラインで開講しているプログラミングスクール
オンラインでどこでも学べる!/教室に行くのが忙しい人でも安心!
Tech Camp教養としてのITスキルを学べるスクール
Webデザイン/AI(人工知能)/IOS/Androidアプリ制作/VRを学びたい方!
WEBCAMP PRO転職保証付き!エンジニアとして転職したい人におすすめ!
未経験からプロのエンジニアへ3ヶ月で転職する為のスクールです!
12月生募集中!当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
11月生は満員となっております。12月生募集に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

はじめに

Railsアプリケーションは、ブラウザとデータベースとの間にあって、主に、ユーザーからの要求に沿ってデータベースにアクセスして、応答を返すという動きをしています。

つまり、データベースから適切なレコードを取得して出力するわけです。

そのため、必要なレコードを取り出す処理は、いろいろなところで使います。

そこで使われるのが、findメソッドやfind_byメソッドです。

ここでは、間違いやすいこれらのメソッドについて、動きや違い、使いどころを詳しく解説いたします。また、findに関連する他のメソッドも紹介しますので、ぜひ活用してください。

findメソッドとfind_byメソッド

findメソッドとfind_byメソッドは、ActiveRecordクラス(モデル)から利用できるメソッドで、指定した条件に合致するレコードを返します。
(※Rubyにも同名のメソッドがありますが、配列やハッシュ、範囲クラスのメソッドですので、どのクラスから利用されているかを意識して、間違えないようにしましょう)

findメソッドもfind_byメソッドも同じような動きをしますので、どんなときにどちらを使うのかが判断できないかもしれません。

ここでは、まず、それぞれの基本的な動きを説明します。

環境構築

具体的にプログラムコードを書いて確認していただくため、テスト用の環境を作りましょう。

コマンドプロンプトで以下のコマンドを順に実行して、環境構築してください。

rails new find_test
cd find_test
rails generate scaffold Item title:string price:integer
rake db:migrate

rails c
Item.create(title:"book", price:2500)
Item.create(title:"watch", price:5000)
Item.create(title:"computer", price:200000)
Item.create(title:"phone", price:15000)
Item.create(title:"bag", price:20000)
Item.create(title:"watch", price:15000)
Item.create(title:"pen", price:1000)
Item.create(title:"watch", price:18000)
Item.create(title:"computer", price:120000)
exit

一覧画面にidを表示するため、viewファイルに2行追加します。
(app/views/items/index.html.erb)

<p id="notice"><%= notice %></p>

<h1>Items</h1>

<table>
  <thead>
    <tr>
      <th>ID</th>                 <!-- (1) --->
      <th>Title</th>
      <th>Price</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @items.each do |item| %>
      <tr>
        <td><%= item.id %></td>   <!-- (2) --->
        <td><%= item.title %></td>
        <td><%= item.price %></td>
        <td><%= link_to 'Show', item %></td>
        <td><%= link_to 'Edit', edit_item_path(item) %></td>
        <td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Item', new_item_path %>

(1)と(2)のそれぞれを追加します。

また、コントローラに、テスト用のプログラムコードを実装するメソッドを準備しておきます。
(app/models/item.rb)

class Item < ApplicationRecord

  # findテスト用メソッド
  def self.find_test
    # テストコードが入る
  end

  # find_byテスト用メソッド
  def self.findby_test
    # テストコードが入る
  end
end

サーバーを起動し、ブラウザで「localhost:3000/items」にアクセスすると、以下のように表示されれば、環境構築完了です。

findメソッドの構文と動き

findメソッドは、引数として渡されたidをもとにテーブルを検索して、合致するidのレコードを返すメソッドです。

findメソッドは、次のような特徴を持っています。

・検索するカラムはidのみ(idは、システムが自動的に付与するカラムです)
・複数のidを指定して複数のレコードを取得できる
・合致するレコードが1つもない場合は、例外(ActiveRecord::RecordNotFound)が発生する
・出力されるレコードの順番は不定

構文は以下です。

モデル.find(引数)

引数には、以下の6種類を指定できます。

引数 説明 例=>結果
数値 引数のidのレコードを返す モデル.find(1)
=>idが1のレコードが返る
数字 引数の文字を値にした(to_iした)idのレコードを返す モデル.find("2")
=>idが2のレコードが返る
先頭に数字を含んだ文字列 引数の文字列の先頭にある数字を値にした(to_iした)idのレコードを返す モデル.find("3ban")
=>idが3のレコードが返る
タプル 複数の値を指定すると、それらと同じidのレコードの配列を返す モデル.find(2,4,6)
=>idが2、4、6のレコードの配列が返る
戻り値の配列順は不定
配列 配列に含まれるidのレコードの配列を返す モデル.find([2,4,6])
=>idが2、4、6のレコードの配列が返る
戻り値の配列順は不定
要素が1つの配列 配列に含まれるidのレコードの配列を返す モデル.find([5])
=>idが5のレコードの配列が返る

いくつかの引数の動きを試してみましょう。

まずは、コントローラのindexメソッドから、findのテスト用メソッド「find_test」を呼ぶように修正します。
(app/controllers/items_controller.rb)

  :
  def index
#    @items = Item.all
    @items = Item.find_test
  end
  :

次に、モデルに準備したテスト用メソッドfind_testにテストコードを追記します。

では、数値、数字、文字列での動きを見てみましょう。
(app/models/item.rb)

    :
  # findテスト用メソッド
  def self.find_test
    items = []
    items[0] = Item.find(1)      # 数値指定
    items[1] = Item.find("1")    # 数字指定
    items[2] = Item.find("1ban") # 先頭が数字の文字列指定
    return items
  end
    :

※Viewファイルのeachメソッドで一覧表示しますので、戻り値は必ず配列などに収めなければいけません

すべて、ID=1のレコードを取得しますので、以下のように表示されます。(分かりやすくするために、左に全出力した結果、右に今回の出力結果を表示しています。以降も同じです)

複数のidでの検索は、次のようになるでしょう。
(app/models/item.rb)

    :
  # findテスト用メソッド
  def self.find_test
#    items = []
#    items[0] = Item.find(1)      # 数値指定
#    items[1] = Item.find("1")    # 数字指定
#    items[2] = Item.find("1ban") # 先頭が数字の文字列指定
#    return items
    items_tuples = Item.find(1,3,1)      # タプル指定
    items_array =  Item.find([7,8,5,8])  # 配列指定
    items_s_arr =  Item.find([6])        # 配列1要素指定
    return items_tuples + items_array + items_s_arr  # ※(1)
  end
    :

※(1) 3パターンを1度に表示するため、配列を連結しています。
タプルや配列を渡すことで、複数のレコードを取得できます。このとき、同じIDを指定しても、重複して表示されることはありません。

最後に、指定したidが見つからなかった場合の動作です。
(app/models/item.rb)

    :
  # findテスト用メソッド
  def self.find_test
#    items = []
#    items[0] = Item.find(1)      # 数値指定
#    items[1] = Item.find("1")    # 数字指定
#    items[2] = Item.find("1ban") # 先頭が数字の文字列指定
#    return items
#    items_tuples = Item.find(1,3,1)      # タプル指定
#    items_array =  Item.find([7,8,5,8])  # 配列指定
#    items_s_arr =  Item.find([6])        # 配列1要素指定
#    return items_tuples + items_array + items_s_arr  # ※(1)
    Item.find([10])
  end
    :


例外(ActiveRecord::RecordNotFound)が発生しました。そのため、「レコードが見つからない可能性がある」シーンには、findメソッドを使わないのが一般的です。(例外が発生することは、プログラム上ありえないようにすべきなのです)

ただし、どうしてもfindメソッドを使う必要がある場合もあるでしょう。そのときは、例外をキャッチして処理する仕組み(エラー画面を表示するなど)を入れておかなければいけません。

コツコツ独学×スクールで実践。未経験からエンジニアに転職!【WebCamp卒業生インタビュー】
2018-03-22 23:28
今回の記事では、独学でPHPを1年半学習し、その後WebCampを受講して未経験からエンジニアへと転職された佐々木さんにお話を伺いました。 <プロフィール> 佐々木 祐樹 さん(2...

find_byメソッドの構文と動き

find_byメソッドも、引数に渡されたidをもとに検索して、一致したレコードを返すメソッドです。

しかし、以下のようにfindメソッドとは少し違う動きをします。

・検索するカラムは任意
・最初に見つかったレコードを返す(複数レコードの取得はできない)
・合致するレコードが1つもない場合は、nilを返す
・出力されるレコードの順番は不定

構文は以下です。

モデル.find(引数)

引数には、検索したい「カラム名と値の組み合わせ」を指定します。不等式による条件指定も可能です。

具体例を見ていくため、コントローラのindexメソッドから、find_byのテスト用メソッド「findby_test」を呼ぶように改めて修正します。
(app/controllers/items_controller.rb)

  :
  def index
#    @items = Item.all
#    @items = Item.find_test
    @items = Item.findby_test
  end
  :

次に、findby_testメソッドにテストコードを追記しましょう。
(app/models/item.rb)

    :
  # find_byテスト用メソッド
  def self.findby_test
    items = []
    items[0] = Item.find_by(id:7)                                   # id指定
    items[1] = Item.find_by(title:"watch")                          # id以外のカラム指定
    items[2] = Item.find_by(title:"watch", price:15000)             # 複数条件指定
    items[3] = Item.find_by("price > ?", 5000)                      # 範囲指定
    return items
  end
    :


このように、id以外の条件でも検索することができますので、find_byメソッドの方が応用範囲が広いかもしれません。

ただし、最初に見つかった1件しか取得できませんので、複数レコードを取得する必要がある場合は、whereメソッドを使用する必要があります。(whereメソッドについては、

【Rails入門説明書】whereについて解説
2018-10-31 17:27
はじめに Railsアプリケーションはデータベースに大量のデータを保持するのが一般的です。 そのため、大量なデータの中から必要なデータを効率よく取り出して処理できるようにしなければ...

">「【Ruby入門説明書】whereについて解説」を参照してください)

また、見つからなかった場合はnilが返ってきますので、find同様にレコードが見つからない可能性のある検索の場合は、分岐処理が必要です。

ただし、findメソッドと違って例外ではありませんので、想定内の処理であり、ifなど通常の分岐で処理することになるでしょう。

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
2017-10-04 10:26
今回の記事では、未経験からWebCampを1ヶ月受講し、その後エンジニアとして転職をした喜田さんにお話を伺いました。 <プロフィール> 喜田 大介 さん (28歳) 大学時代はプ...

findメソッドとfind_byメソッドの違いと使いどころ

ここまでの説明で、findメソッドとfind_byメソッドの違いは見えてきたかもしれませんが、改めてまとめておきましょう。

findメソッド find_byメソッド
検索対象 idのみ 任意のカラム
取得レコード 複数idで複数取得可能 最初に見つかった1つのみ
見つからない場合 例外発生(ActiveRecord::RecordNotFound) nilが返る
取得レコードの順番 不定 不定

つまり、ほとんどの場合、idで検索するかどうか、テーブルに必ず存在する検索条件かどうかで使い分けることになるでしょう。

find_or_initialize_byメソッドとfind_or_create_byメソッドを知っていますか?

find_byメソッドはレコードを検索して最初に見つかった1件を返すメソッドです。

それと同じく、find_or_initialize_byメソッドとfind_or_create_byメソッドも、レコードを検索するメソッドですが、ただ検索するだけではありません。

もし、検索条件に合致するレコードがなかった場合、検索条件で初期化したレコードを新規で作成してくれるのです。

そのため、find_byメソッドで、戻り値がnilかどうかで分岐させて作成するような場合には、find_or_initialize_byメソッドやfind_or_create_byメソッドを使うことで、プログラムコードをシンプルにできます。

ただし、find_or_initialize_byメソッドはテーブルへの登録までは行いません(別途、saveメソッドでテーブルに登録する必要があります)。

そのため、自動的にテーブルへの登録まで行いたい場合は、find_or_create_byメソッドを使用してください。

今回のテスト環境では、find_or_initialize_byメソッドでは下準備が足りませんので、find_or_create_byメソッドを使った動作を確認してみましょう。

新たに、find_or_create_byメソッドのテスト用メソッドを追加し、呼び出すようにします。
(app/models/item.rb)

    :
  # find_or_create_byテスト用メソッド
  def self.findorcreateby_test
    items = []
    items[0] = Item.find_or_initialize_by(title:"watch", price:15000) # 見つかる
    items[1] = Item.find_or_initialize_by(title:"ring", price:50000)  # 見つからない
    return items
  end
    :

(app/controllers/items_controller.rb)

  :
  def index
#    @items = Item.all
#    @items = Item.find_test
#    @items = Item.findby_test
    @items = Item.findorcreateby_test
  end
  :


存在しなかったID:10のデータが表示されているところがポイントです。

改めて全件表示してみると、レコードが追加されていることが分かるでしょう。
(app/models/item.rb)

    :
  # find_or_create_byテスト用メソッド
  def self.findorcreateby_test
#    items = []
#    items[0] = Item.find_or_initialize_by(title:"watch", price:15000) # 見つかる
#    items[1] = Item.find_or_initialize_by(title:"ring", price:50000)  # 見つからない
#    return items
    Item.all
  end
    :

未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】
2018-03-10 14:42
今回の記事では、たまたま見たテレビ番組がきっかけでエンジニアに興味を持ち、WebCampProを受講して見事転職を決めた中村さんにインタビューしました。 <プロフィール> 中村 駿...

「find_eachメソッド」とは?

「find」という単語で検索しているけれど、じつは「find_eachメソッド」が知りたい人もいるかもしれません。

本記事の内容とは少しずれますが、find_eachメソッドについても簡単に説明しておきます。

find_eachメソッドは、findメソッドやfind_byメソッドとは違って、検索するメソッドではなく、繰り返しを行うメソッドです。(findではなくeachがメインです)

では、なぜ「find_each」などという紛らわしい名称がついているかというと、find_eachメソッドは、繰り返しの処理を「特定件数ずつ読み込みながら」行うからです。

eachメソッドは、全レコードをメモリ上に読み込み、メモリ上で処理を行います。そのため、もし数万件、数百万件などのレコードを持つテーブルに対して処理を行おうとすると、システムのメモリが不足してフリーズするなどの問題が発生します。

そういったことが懸念される場合に、find_eachメソッドを使用して繰り返し処理を行います。

find_eachメソッドを使用すれば、デフォルトで1,000件ずつメモリ上に読み込みながら処理を行いますので、ほとんどの場合、問題が起こることはないでしょう。

もし、それでも心配であれば、batch_sizeオプションを指定することで、処理件数を1件以上の任意の件数に指定できます。

構文のオプションを紹介しておきましょう。

モデル.find_each(オプション) do |ブロック引数|
  繰り返し処理
end

※ブロック引数には、レコードのデータ(AcriveRecordオブジェクト)が格納されます

オプション 説明
:start 処理開始する位置(id)
:batch_size 1度にメモリに読み込む件数

【Rails入門説明書】whereについて解説

まとめ

findメソッドとfind_byメソッドについて、解説しました。

テーブルから必要なレコードを取得するこれらのメソッドは、データの一覧の表示や編集などで使うことの多いメソッドで、同じような動きをしているだけに、適切な使い方をしなければ思わぬ落とし穴にはまってしまいます。

また、同じようなことが実現できる他のメソッドもありますので、実現したい動きに合わせた最適なメソッドを使うことで、プログラムコードをシンプルにして、可読性をあげることもできます。

本記事を参考にして、しっかりと使い分けをしていきましょう。

・findメソッドは、idで検索してレコードを返す
・findメソッドは、複数のidを渡すことで複数のレコードを返してくれる
・find_byメソッドは、id以外のカラムでも検索できる
・find_byメソッドは、最初に見つかった1件めのレコードしか取得できない
・任意のカラムの条件に一致する複数のレコードを取得したい場合は、whereメソッドが便利
・find_or_initialize_byメソッドと、find_or_create_byメソッドは、検索してなかった場合にレコードを新規生成する
・find_or_initialize_byメソッドは、新規生成したレコードがテーブルに登録されない
・find_or_create_byメソッドは、新規生成したレコードがテーブルに登録される

WebCamp・WebCamp Proについて

WebCampは1ヶ月でプログラミング・Webデザインスキルを学ぶ通い放題のプログラミングスクールです。WebCamp Proは3ヶ月間で未経験から即戦力エンジニアを育成するプログラミングスクールです。

2つのサービスを運営するインフラトップでは、「学びと仕事を通して人生を最高の物語にする」という理念で会社を経営しています。

キャリアアップを目指す方は、この機会に私達と一緒にプログラミングを学んでみませんか?

12月枠も残りわずか当社人気の転職保証コース
プログラミング学習から転職成功まで導く、当社人気のWebCamp Proコース。
11月受入枠は満員となっております。12月枠に向け、お早めの申込みをオススメします。
プログラミング未経験でもエンジニア転職を絶対成功させたい
スキルを身に着けて人生を自ら切り開きたい
上記にあてはまる方は、ぜひご検討ください!

▼未経験から1ヶ月でWebデザイン・プログラミングを学びたい方はこちら!

▼ついに開講!オンラインでWebデザインを学びたい方はこちら!

 

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

【WebCamp卒業生インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
2018-01-15 13:23
今回の記事では、WebCampで1ヶ月間Rubyを学習し、Webエンジニアとして転職した卒業生の田中さんにお話を伺いました。 <プロフィール> 田中 デニス 昭彦さん(...
関連キーワード
学習の関連記事
  • 【誰でもわかる!】エンジニアの仕事内容を徹底解説
  • 初心者でも一瞬でわかるプログラミングの考え方・思考法
  • エンジニア必見!エンジニアが成長できるブログ紹介
  • エンジニアとは?仕事内容、年収、将来性を徹底解説
  • 【Rails入門説明書】find、find_byについて解説
  • プログラミング未経験者でも出来る開発環境構築