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

そのため、大量なデータの中から必要なデータを効率よく取り出して処理できるようにしなければいけません。

毎回すべてのデータの内容を確認して処理をするのは、データの量が多くなると、パフォーマンスに影響します。特に商用のRailsアプリケーションでは、パフォーマンスの悪さは死活問題になりますので、とても重要です。

そんなときに活用できるのが、whereメソッドです。

whereメソッドを使って必要なデータだけを抽出することで、データベースから不要な分岐処理をなくして高速化し、プログラムコードもシンプルで分かりやすいものにすることができます。

今回は、そんなwhereメソッドの詳しい使い方をお伝えいたします。

Railsでデータベースを検索するwhere

Railsのwhereメソッドは、指定した条件に当てはまるレコードを抽出するメソッドです。データベースとやりとりをするモデルクラスに属しています。

allメソッドやjoinsメソッド、includesメソッドなどは原則として全レコードを取得します。しかし、すべてのレコードに対して処理を行うことは、それほど多くないでしょう。

実際の処理については、特定の条件に合致するレコードだけを選別して行うことが多いのではないでしょうか。

一覧表示するという単純な動作でも、全件表示よりも条件を指定して絞り込んで表示できる方が、ユーザーにとって使いやすい場合がほとんどです。

また、そういった絞り込みを行うことで、事前に必要な(処理すべき)レコードだけになっていますので、プログラムの中で余計な分岐などを必要とせず、プログラムコードがシンプルになる利点もあります。

それに加えて、必要なレコードを取得する部分と、レコードを使って処理をする部分とが明確に棲み分けられ、メンテナンス性も向上します。

設計思想

ある程度の規模以上のプログラムを作るとき、「設計思想」というのが非常に重要になります。

プログラムというのは、特定の処理を実現する方法がいくつも存在しており、どれが正解というものはありません。しかし、基本の考え方となる「設計思想」があれば、そのいくつもの実現方法の中から、設計思想に則った方法を選択することができるわけです。

そして、「設計思想」に準じたプログラムを作っておくことで、プログラムを理解するときに迷いが少なく可読性が上がります。また、調査や変更するときも目安を付けることが容易になり、メンテナンス性が高くなるのです。

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

whereの使い方

では、whereメソッドについて、詳しく説明していきましょう。

ただ、文章を読むだけよりも、実際に動かしながらの方がスムーズに理解できますので、まずは環境を作ります。

環境構築

まずは、コマンドプロンプトで以下のコマンドを順に入力して、Rails環境を作成してください。(where_testという名称にします)

rails new where_test
cd where_test
rails generate scaffold Item title:string category:string price:integer number:integer
rake db:migrate

次にテスト用のデータを準備します。数が多いので、rails consoleを利用しましょう。
(こちらも、コマンドプロンプトで順に入力してください)

rails c
Item.create(title:"Wagyu",category:"meat",price:2000,number:10)
Item.create(title:"Maguro",category:"fish",price:5000,number:10)
Item.create(title:"Iwashi",category:"fish",price:100,number:50)
Item.create(title:"Kurobuta",category:"meat",price:500,number:30)
Item.create(title:"Nasu",category:"vegetable",price:300,number:20)
Item.create(title:"Tomato",category:"vegetable",price:100,number:100)
Item.create(title:"Jidori",category:"meat",price:800,number:30)
Item.create(title:"OGbeef",category:"meat",price:200,number:100)
Item.create(title:"Hirame",category:"fish",price:2000,number:10)
exit

以上で、テスト環境が整いました。

念のため、サーバーを起動して一覧を表示してみましょう。

rails s

ブラウザから「localhost:3000/items」にアクセスします。

構文

whereの構文から紹介します。

モデル.where(条件)

構文自体は非常にシンプルです。しかし、「条件」の記載方法は、同じ条件でも複数の記載方法があり、少し混乱しますので、例を挙げて説明しましょう。(Rails(Ruby)はプログラマーの自由度(ある記載をすれば動くであろうというプログラマーの期待に添うこと)を尊重しているためです)

例えば、以下の方法はすべて同じ「numberが30のもの」という条件です。

    @items = Item.where("number = 30")      # 1.文字列での条件指定
    @items = Item.where(number: 30)         # 2.ハッシュでの条件指定
    @items = Item.where(["number = ?", 30]) # 3.配列での条件指定

1.文字列での条件指定

    @items = Item.where("number = 30")

条件式をすべて文字列で記載する方法です。文字列内に記載した条件そのままですので、簡単な記法と言えるかもしれません。

2.ハッシュでの条件指定

    @items = Item.where(number: 30)

カラム名と値のハッシュで指定する方法です。もっともRailsらしいシンプルな記法と言えるかもしれません。

残念ながら大小比較条件の場合には利用できませんが、以下のような範囲指定は可能ですので、ケースバイケースで使っていくのが良いでしょう。

    @items = Item.where(number: 30..50)

3.配列での条件指定

    @items = Item.where(["number = ?", 30])

配列の第1要素の文字列内にある「?」に、第2要素以降の値を当てはめた条件を指定してくれる記法で、文字列の記載の可読性を上げたものとも言えます。もっとも汎用性が高い記法がこの方法になります。

動作確認

念のため、前述の3つの指定方法で同じ検索結果になるのかどうか、動作確認をしておきましょう。

一覧表示するレコードを読み込んでいるのは、コントロールの以下の部分です。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.all
  end
  :

scaffoldが自動生成しているプログラムコードでは、「@items = Item.all」で、インスタンス変数@itemsにすべてのレコードを読み込んでいます。つまり、この部分を修正することで、一覧表示されるレコードを変えることができるわけです。

文字列、ハッシュ、配列のそれぞれと差し替えて、動きを試してみましょう。例えば、文字列で条件指定する場合は、以下のようなプログラムコードになります。
(app/controllers/items_controller.rb)

  :
  def index
    @items = Item.where("number = 30")
  end
  :

ブラウザを再読込すると、以下のようにnumberが30のものだけに絞り込んだ一覧になります。

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

whereの詳しい使い方

基本的な構文と条件設定の方法を説明しましたので、ここからもう少し詳細な使い方を解説していきましょう。

一致と範囲、比較

条件設定には、一致と範囲、大小比較があります。ifやwhileなどと同様に、whereの条件指定でも、これらの組み合わせで条件を作るわけです。

一致はすでに紹介していますが、文字列、ハッシュ、配列のそれぞれプログラムコードを紹介します。すべて、前述のように(app/controllers/items_controller.rb)の該当箇所を差し替えることで、実際に絞り込むことができますので、試しておきましょう。

一致

numberが30のものを絞り込む場合、以下のようになります。

    @items = Item.where("number = 30")      # 1.文字列での条件指定
    @items = Item.where(number: 30)         # 2.ハッシュでの条件指定
    @items = Item.where(["number = ?", 30]) # 3.配列での条件指定

範囲

numberが10から30のものを絞り込む場合、以下のように範囲オブジェクトを利用することができます。ただし、範囲オブジェクトはハッシュの場合だけ利用できる方法です。

#    @items = Item.where("number = 10..30")      # 1.文字列での条件指定(エラー)
    @items = Item.where(number: 10..30)         # 2.ハッシュでの条件指定
#    @items = Item.where(["number = ?", 10..30]) # 3.配列での条件指定(エラー)

大小比較

numberが50以上のものを絞り込む場合、以下のようになります。大小比較については、残念ながらハッシュで利用することができません。

    @items = Item.where("number >= 50")      # 1.文字列での条件指定
#    @items = Item.where(number: >=50)        # 2.ハッシュでの条件指定(エラー)
    @items = Item.where(["number >= ?", 50]) # 3.配列での条件指定

andとor

複数の条件をandやorで組み合わせることも可能です。これも具体的な例で紹介しましょう。

and

categoryが"meat"、かつpriceが100から1000のものを絞り込む場合、以下のようになります。

    @items = Item.where("category = 'meat' and price >= 100 and price <= 1000")            # 1.文字列での条件指定
    @items = Item.where(category:'meat', price:100..1000)                                  # 2.ハッシュでの条件指定
    @items = Item.where(["category = ? and price >= ? and price <= ?", 'meat', 100, 1000]) # 3.配列での条件指定

範囲指定が絡むと、範囲オブジェクトを利用できるハッシュのシンプルさが際立ちます。

or

categoryが"vegetable"、もしくはpriceが100のものを絞り込む場合、以下のようになります。

    @items = Item.where("category = 'vegetable' or price = 100")         # 1.文字列での条件指定
#    @items = Item.where(category:'vegetable', price:100)                # 2.ハッシュでの条件指定(表現できず)
    @items = Item.where(["category = ? or price = ?", 'vegetable', 100]) # 3.配列での条件指定

今回の条件については、ハッシュでは実現できません。

しかし、条件対象となるカラムが1つだけだった場合は、ハッシュも利用可能です。例えば、categoryが"meat"もしくは"fish"のものを絞り込む場合は、次のようになります。

    @items = Item.where("category = 'vegetable' or category = 'meat'")         # 1.文字列での条件指定
    @items = Item.where(category:['vegetable','meat'])                         # 2.ハッシュでの条件指定(配列をハッシュの値にする)
    @items = Item.where(["category = ? or category = ?", 'vegetable', 'meat']) # 3.配列での条件指定

ハッシュの値を配列にすることで、orとして解釈されるのです。

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

否定

条件を反転させる否定についても、知っておいた方が良いでしょう。

numberが30ではないものを絞り込む場合は、以下のように記載します。

    @items = Item.where.not("number = 30")      # 1.文字列での条件指定
    @items = Item.where.not(number: 30)         # 2.ハッシュでの条件指定
    @items = Item.where.not(["number = ?", 30]) # 3.配列での条件指定


このように、notメソッドを使うことで、条件を反転することができます。

もちろん、基本的には、notメソッドを使わずに「=」を「!=」にしてしまえば良いだけですが、ハッシュではこの方法を使う以外に否定を表現できません。

なお、否定表現は頻繁に使うと可読性が落ちてしまいます。場合によっては、逆に可読性を上げることもありますので、しっかりと考えてから使うようにしましょう。

変数の使用

ここまでの例では、比較する値が30や"meat"のような固定の値になっています。

もちろん、間違いではありませんが、固定の値では、汎用性に欠けており、再利用することが難しくなってしまいます。そこで、汎用的なプログラムコードにするため、比較値に変数を使用しましょう。

こちらも、具体的なプログラムコードを紹介します。

以下は、numberが30のものを絞り込む場合のプログラムコードですが、30を変数numに格納しています。

    num = 30
    @items = Item.where("number = #{num}")   # 1.文字列での条件指定
    @items = Item.where(number: num)         # 2.ハッシュでの条件指定
    @items = Item.where(["number = ?", num]) # 3.配列での条件指定

このnumを代入ではなく、ユーザーから入力させた値や、別のテーブルから取得する値にすることで、汎用的な絞り込み機能を実現できるでしょう。

SQLインジェクションに注意

ここで、1点、注意していただきたいセキュリティリスクを紹介しておきます。

それは「SQLインジェクション」と呼ばれているものです。

SQLインジェクションというのは、意図しないSQLが実行され、データベースからデータが流出してしまうセキュリティリスクのことです。

じつは、whereの条件で変数を利用するとき、その方法や条件によってSQLインジェクションのリスクが発生し、脆弱性(セキュリティ的な脆さ)を生み出してしまうことがあるのです。

例えば、前述している変数numを使っているプログラムコードで、文字列を利用しているプログラムコードには、問題があります。

numをユーザーが入力するようにしていて、「30 or 30 = 30」という文字列を入力されてしまった場合を想定してみましょう。

    num = "30 or 30 = 30"
    @items = Item.where("number = #{num}")   # 1.文字列での条件指定

結果は、以下のように全件表示されてしまっています。

もちろん、今回のアプリケーションのように、全件表示されて問題なければリスクはないと言えますが、このリスクについて知らなければ、ユーザーのアカウント情報などを容易に流出させてしまうことになるでしょう。

ただし、幸いにも、この問題は、ほとんどの場合、ハッシュや配列を利用して条件指定することで回避できます。

そのため、whereの条件指定は、できる限りハッシュか配列を利用するようにすべきでしょう。

配列での条件指定でSQLインジェクションのリスクがない理由

配列の条件指定の場合も、「?」に値が埋め込まれるため、同様の結果になるように考えてしまいまうかもしれません。しかし、安心してください。

文字列と配列の指定では、SQLを生成する処理の順番が違っているため、同様の結果にはならないのです。

少し詳しく説明しましょう。

文字列の条件指定の場合の動作

文字列での条件指定の場合、SQLの元になる文字列を作成し、その後文字列をSQLの条件式へと変換しています。

    num = "30 or 30 = 30"
    @items = Item.where("number = #{num}")   # 1.文字列での条件指定

上記の場合、まず"number = #{num}"が、"number = 30 or 30 = 30"という文字列になり、それがwhereメソッドへ渡されます。その結果、以下のようなSQLが作られます。

SELECT "items".* FROM "items" WHERE (number = 30 or 30 = 30)

「30 = 30」は常にtrueですので、WHERER区の中は常にtrueとなり、すべてのレコードがマッチして出力されたわけです。

配列の条件指定の場合の動作

配列を使用した場合のプログラムコードは以下のようになります。

    num = "30 or 30 = 30"
    @items = Item.where(["number = ?", num])   # 1.文字列での条件指定

この場合、まず配列の第1要素を使って以下のようなSQLが生成されます。

SELECT "items".* FROM "items" WHERE (number = ?)

その後、第2要素以降が順に「?」と置換されていくわけです。その結果が以下です。

SELECT "items".* FROM "items" WHERE (number = '30 or 30 = 30')

この場合、numberが'30 or 30 = 30'という文字列と一致するかどうかが条件となりますので、一致するものがあるわけもなく、空のリストが表示されることになるでしょう。

まとめ

今回は、whereメソッドについて説明しました。

whereを利用することで、一覧表示の絞り込みを容易に実現でき、データの処理についても必要なレコードだけを取得するため、余計な分岐処理を実装する必要がなくなります。

つまり、実処理部分のプログラムコードをすっきりと見やすくできるということです。

また、データ取得部分と実処理部分の責任範囲を明確にすることができるため、メンテナンス性もとても上がります。

プログラムコードの見やすさ(可読性)やメンテナンス性は、プログラムを作る上で常に意識しておくべきことですので、ここで紹介したwhereメソッドの使用例がお役に立てれば幸いです。

ただし、SQLインジェクションの対策なども考慮する必要があり、その場その場で柔軟な対応が必要になってきます。そういったものはサイトのような固定されたものでは説明することが難しいものです。プログラムスクールなど、対面で経験者の話を聞ける環境があれば、ぜひ活用していきましょう。

・whereメソッドは、条件に合ったものだけをデータベースから取得する
・whereメソッドの条件指定の方法には、文字列とハッシュと配列がある
・条件指定の配列は、第1要素が条件を指定する文字列で、第2要素以降に、文字列の「?」部分に埋め込む値を設定する
・範囲オブジェクトによる条件指定はハッシュの場合だけ可能
・大小比較はハッシュでは指定できない
・文字列での条件指定は、SQLインジェクションのリスクがある

 

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エンジニアとして転職した卒業生の田中さんにお話を伺いました。 <プロフィール> 田中 デニス 昭彦さん(...
関連キーワード
Ruby on Railsの関連記事
  • 【Rails入門説明書】includesについて解説
  • 【Rails入門説明書】RubyとRailsの初心者/中級以上用の厳選本8選
  • 【Rails入門説明書】joinsについて解説
  • 【Rails入門説明書】 jQueryの導入方法について解説
  • 【Rails入門説明書】scopeについて解説
  • 【Rails入門説明書】has_manyについて解説
おすすめの記事