- 公開日: 2021年03月23日
Active Recordでデータベースの操作をしてみよう【find・where編】
Ruby on Rails(以下Railsと呼ぶ)には、データの操作を簡単にする『Active Record』という便利な機能があります。プログラミング初心者の中には、Active Record特有のfindやwhereメソッドの扱いに苦手意識を感じている方もいるかもしれません。
本記事は、簡単なアプリケーションを作成しながら、Active Recordやデータベースの操作を学べるようになっています。ぜひこの機会に理解を深めていただければと思います。
Active Recordとは
『Active Record』は、Rubyとデータベースの言語であるSQLを繋ぐ翻訳機のような役割をします。本来データベースからデータの取得や削除などをおこなうには、SQLのコマンドの実行が必要がです。
しかしSQLのコマンドは複雑である場合が多く、どうしてもSQLの知識が必要となります。そこで生まれたのが『Active Record』です。
Active Recordにより、SQLのコードを書かずに、Rubyのコードだけでデータベースの操作が可能になりました。本記事では特に使用頻度の高い、「find」「find_by」「where」メソッドについて解説していきます。
準備編
まずはActive Recordについて学ぶ準備をしましょう。
ターミナル(コマンドプロンプト)を開き、下記コマンドを上から実行してください。今回は簡単にアプリケーションの雛形を作成する『Scaffold』を使用して、解説していきます。
//作業ディレクトリを作成
mkdir active_record_practice
//作業ディレクトリに移動
cd active_record_practice/
//Railsの新規プロジェクト作成
rails new Active_Record_app
cd Active_Record_app
// Menuに関する必要なフォルダを自動で作成
rails g scaffold Menu name:string price:integer
//データベースを作成
rails db:create
//マイグレーションを実行
rails db:migrate
rails s
rails sコマンドまで実行できたら、ブラウザで「localhost:3000」を開きます。下画像のようになれば準備は完了です。
次にMenuのサンプルデータを作成していきます。ターミナルやブラウザでも新規データの作成は可能ですが、今回はseedファイルを使って進めましょう。
dbフォルダ配下の「seed.rb」を開き、下記コードを貼り付けてください。
Menu.create([
{ id: 1, name: 'ハンバーグ', price: '1200' },
{ id: 2, name: 'カルボナーラ', price: '850' },
{ id: 3, name: 'ステーキ', price: '1500' },
{ id: 4, name: '生ビール', price: '380' },
{ id: 5, name: 'オレンジジュース', price: '250' },
])
これらのサンプルデータをデータベースに反映させるために、下記コマンドをターミナルで実行してください。
rails db:seed
これでseed.rbの内容が保存されました。念のため、コンソールで確認してみましょう。ターミナルで下記コマンドを実行してください。
rails c
>Menu.all
//実行結果
=> #<ActiveRecord::Relation [#<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">, #<Menu id: 2, name: "カルボナーラ", price: 850, created_at: "2021-03-06 11:24:01.225481000 +0000", updated_at: "2021-03-06 11:24:01.225481000 +0000">,(以下省略)
seed.rbの内容が表示されれば成功です。これで、Active Recordのメソッドを実行できる準備が整いました。
Active Recordのメソッド① find&find_by編
この章からActive Recordで用意されているメソッドについて解説していきます。その中でも使用頻度が高い「find」と「find_by」メソッドから学んでいきましょう。
主キーをもとにデータを取得するfind
ターミナルでコンソールを起動した状態(rails c)で、下記コマンドを実行してください。
>Menu.find(1)
//実行結果
=> #<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">
Menuのidが1のデータが表示されました。このようにfindの引数に主キーを指定すると、それに対応するデータのみ抽出することができます。idが2ならfind(2)、idが100ならfind(100)といった感じです。
findの引数に複数の主キーを持たせることも可能です。例えばidが1と2のデータを抽出したい場合は下記のようにコマンドを実行します。
> Menu.find(1,2)
=> [#<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">, #<Menu id: 2, name: "カルボナーラ", price: 850, created_at: "2021-03-06 11:24:01.225481000 +0000", updated_at: "2021-03-06 11:24:01.225481000 +0000">]
また存在しないidを検索するとどうなるのかも見てみましょう。コンソールで下記コマンドを実行してください。
>Menu.find(100)
ActiveRecord::RecordNotFound (Couldn't find Menu with 'id'=100)
seed.rbで作成したデータにidが100のものがないので、エラーが発生します。
該当する最初のデータを取得するfind_by
次は主キー以外でデータを取得する方法についてみていきましょう。例えば「ハンバーグ」という文字を含んだデータのみ取得したいとします。では、コンソールで下記コマンドを実行してみましょう。
>Menu.find(“ハンバーグ”)
ActiveRecord::RecordNotFound (Couldn't find Menu with 'id'=ハンバーグ)
エラーが出てしまいました。エラー文を訳すと「idがハンバーグであるデータを見つけられません」となります。
findメソッドは主キー(この場合はidを指す)をもとデータを取得することができないため、このようなエラーが発生したのです。nameなどid以外の情報で検索するには、「find_by」メソッドを使用します。
再びコンソールで下記コマンドを実行してください。
>Menu.find_by(name:"ハンバーグ")
=> #<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">
これでnameにハンバーグを持つデータのみ取得できました。find_byは便利ですが、最初に見つけたデータしか取得できないという注意点があります。
該当する全てのデータを取得したい場合は、後述する「where」メソッドを使用してください。
またfind_byメソッドはより複雑な条件にも対応可能です。コンソールで下記コマンドを実行してください。
Menu.find_by(name:"ハンバーグ",price:1200)
=> #<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">
irb(main):015:0> Menu.find_by(name:"ハンバーグ",price:1000)
仮に下記コマンドのように存在しないデータを抽出しようとすると、結果は「nil(=該当するものがない)」が返ってきます。
Menu.find_by(name:"ハンバーグ",price:1000)
=> nil
該当するデータを全て取得するwhere
この章では、該当するデータ全てを取得する「where」メソッドについてみていきましょう。whereの引数には、カラム名と検索したい値を指定します。
例えば、価格が380円のメニューを取得したい場合は下記のようにコマンドを実行してください。価格が380円のデータが複数あれば、全て表示されます。
>Menu.where(price:380)
=> #<ActiveRecord::Relation [#<Menu id: 4, name: "生ビール", price: 380, created_at: "2021-03-06 11:24:01.238184000 +0000", updated_at: "2021-03-06 11:24:01.238184000 +0000">]>
whereメソッドの引数には、不等号も使用可能です。例えば、価格が1000円以上のメニューを取得したい場合は、下記のようになります。
>Menu.where('price>=1000')
=> #<ActiveRecord::Relation [#<Menu id: 1, name: "ハンバーグ", price: 1200, created_at: "2021-03-06 11:24:01.212271000 +0000", updated_at: "2021-03-06 11:24:01.212271000 +0000">, #<Menu id: 3, name: "ステーキ", price: 1500, created_at: "2021-03-06 11:24:01.231746000 +0000", updated_at: "2021-03-06 11:24:01.231746000 +0000">]>
またwhereメソッドは、条件に該当しないものを抽出することもできます。例えば、コンソールで下記コマンドを実行してください。
> Menu.where.not(name:"ハンバーグ")
=> #<ActiveRecord::Relation [#<Menu id: 2, name: "カルボナーラ", price: 850, created_at: "2021-03-06 11:24:01.225481000 +0000", updated_at: "2021-03-06 11:24:01.225481000 +0000">, #<Menu id: 3, name: "ステーキ", price: 1500, created_at: "2021-03-06 11:24:01.231746000 +0000", updated_at: "2021-03-06 11:24:01.231746000 +0000">, #<Menu id: 4, name: "生ビール", price: 380, created_at: "2021-03-06 11:24:01.238184000 +0000", updated_at: "2021-03-06 11:24:01.238184000 +0000">, #<Menu id: 5, name: "オレンジジュース", price: 250, created_at: "2021-03-06 11:24:01.244734000 +0000", updated_at: "2021-03-06 11:24:01.244734000 +0000">]>
nameが「ハンバーグ」以外のデータ全てが抽出できました。このようにwhereは否定条件を用いいたデータの検索が可能です。
コントローラーでfindやwhereを使ってみよう
ここまででfindやwhereメソッドを使って、データの取得をできるようになりました。しかし、実際にどのように取得したデータを表示させるのか分からない方もいるかと思います。
本章でコントローラーでfindやwhereを使用して、より理解を深めていきましょう。まずは、ブラウザで「http://localhost:3000/menus」にアクセスしてください。
seed.rbで作成した10個のデータが表示されているはずです。
次にapp / controller / menus_controller.rbを開いてください。ここで書かれているコードは全て、Scaffoldにより作成されたものです。
indexアクションは下記のようになっています。ちなみにコードの「all」メソッドは全てのデータを取得するという意味です。
def index
@menus = Menu.all
end
この時点でブラウザには、下画像のように全てのデータが表示されます。
仮にidが1と2のデータのみ取得する場合は、indexのアクションを下記のように変更する必要があります。
def index
@menus = Menu.find(1,2)
end
ブラウザをリロードして、idが1と2のデータのみ表示されていれば成功です。このようにfindやwhereメソッドはコントローラー内でも使用可能です。
次はコントローラーの記載を下記のように変更して、価格が1000円以上のデータを表示させてみます。
def index
@menus = Menu.where(‘price>=1000’)
end
下画像のようになればデータの抽出は完了です。
\Webサイト担当者としてのスキルが身に付く/
まとめ
Scaffoldで作成したアプリを使いながら、Active Recordのメソッドを使用してきました。findやwhereメソッドを応用すれば、複雑な検索条件も実装することができます。
ぜひ本記事で学んだメソッドについて復習してみてはいかがでしょうか。
- この記事を書いた人
- ヤマモト