Active Recordでデータベースの操作をしてみよう②【select・group編】


Active Recordでデータベースの操作をしてみよう②【select・group編】

Ruby on Rails(以下Railsと呼ぶ)には、データの操作を簡単にする『Active Record』という便利な機能があります。プログラミング初心者の中には、Active Record特有のfindやwhereメソッドの扱いに苦手意識を感じている方もいるかもしれません。

本記事は、簡単なアプリケーションを作成しながら、Active Recordやデータベースの操作を学べるようになっていますので、ぜひこの機会に理解を深めていただければと思います。

目次
  1. 準備編
  2. Active Recordのメソッド① select編
  3. Active Recordのメソッド② group編
  4. コントローラーでgroupメソッドを使ってみよう
  5. まとめ

『Active Record』は、Rubyとデータベースの言語であるSQLを繋ぐ翻訳機のような役割をします。本来データベースからデータの取得や削除などをおこなうには、SQLのコマンドの実行が必要がです。

しかしSQLのコマンドは複雑である場合が多く、どうしてもSQLの知識が必要となります。そこで生まれたのが『Active Record』です。

Active Recordにより、SQLのコードを書かずに、Rubyのコードだけでデータベースの操作が可能になりました。本記事では、データの集計や特定のカラムのみ抽出するのを可能にする「select」と「group」メソッドについて解説していきます。

また「find」や「where」メソッドに関しても別記事で解説しておりますので、ぜひこちらも参考にしてみてください。

準備編

まずはActive Recordについて学ぶ準備をしましょう。

ターミナル(コマンドプロンプト)を開き、下記コマンドを上から実行してください。今回は簡単にアプリケーションの雛形を作成する『Scaffold』を使用して、解説していきます。

//作業ディレクトリを作成
mkdir active_record_practice
//作業ディレクトリに移動
cd active_record_practice/
//Railsの新規プロジェクト作成
rails new Active_Record_app2
cd Active_Record_app2
// Bookに関する必要なフォルダを自動で作成
rails g scaffold Book lang:string title:string price:integer
//データベースを作成
rails db:create
//マイグレーションを実行
rails db:migrate
rails s

rails sコマンドまで実行できたら、ブラウザで「localhost:3000」を開いてください。下画像のようになれば準備は完了です。

image

次にBookのサンプルデータを作成していきます。ターミナルやブラウザでも新規データの作成は可能ですが、今回はseedファイルを使って進めましょう。

dbフォルダ配下の「seed.rb」を開き、下記コードを貼り付けてください。

Book.create([
    {id:1,lang:"ruby",title:"Rubyは楽しいぞ!",price:1200},
    {id:2,lang:"python",title:"Pythonで自動化しよう!",price:1100},
    {id:3,lang:"javascript",title:"Javascriptでサイトに動きをつけよう!",price:1200},
    {id:4,lang:"ruby",title:"RubyでWebアプリを作ろう",price:1500},
    {id:5,lang:"python",title:"Pythonでデータ分析",price:2000},
    {id:6,lang:"javascript",title:"入門Javascript",price:1500},
    {id:7,lang:"javascript",title:"jQuery入門",price:1300},
    {id:8,lang:"ruby",title:"Rubyのクラスを学ぼう",price:1400},
    {id:9,lang:"python",title:"pythonでスクレイピング",price:1600},
    {id:10,lang:"php",title:"楽しいPHP",price:2000}
])

これらのサンプルデータをデータベースに反映させるために、下記コマンドをターミナルで実行してください。

rails db:seed

これでseed.rbの内容がデータベースに保存されたはずです。確認のため、ブラウザのURLに「localhost:3000/books」を入力してください。

そうすると先程作成したseed.rbのファイルの内容が反映されているのが分かります。これでActive Recordのメソッドを実行する環境が整いました。

image

Active Recordのメソッド① select編

この章ではActive Recordの「select」メソッドについてみていきましょう。selectはデータベースから特定のカラムに入っているデータのみ抽出する際に使用するメソッドです。

まずはターミナルでrails cを実行して、コンソールを立ち上げます。「irb(main):001:0>」のようにコマンドを入力できる状態になっていればOKです。

それでは下記コマンドを実行して結果を確認してみましょう。

Book.all

//実行結果
=> #<ActiveRecord::Relation [#<Book id: 1, lang: "ruby", title: "Rubyは楽しいぞ!", price: 1200, created_at: "2021-03-09 03:12:33.202691000 +0000", updated_at: "2021-03-09 03:12:33.202691000 +0000">, #<Book id: 2, lang: "python", title: "Pythonで自動化しよう!", price: 1100, created_at: "2021-03-09 03:12:33.209837000 +0000", updated_at: "2021-03-09 03:12:33.209837000 +0000">, #<Book id: 3, lang: "javascript", title: "Javascriptでサイトに動きをつけよう!", price: 1200, created_at: "2021-03-09 03:12:33.214840000 +0000", updated_at: "2021-03-09 03:12:33.214840000 +0000">,.......(以下省略)

モデル名に対して、allメソッドを実行すると全てのデータを取得できます。しかしid・lang・titleのデータのみ抜き出したい場合には、allメソッドを使うのは適切でありません。

なぜなら不必要な情報を取得すると、それだけメモリのリソースを圧迫するからです。今回はデータが10件なので、allを使っても問題ないですが、何万件という大量のデータの場合パフォーマンスが大幅に落ちるでしょう。

そこで「select」メソッドが役に立ちます。コンソールで下記コマンドを実行して、結果を確認してみましょう。

Book.select(:id,:lang,:title)

//実行結果
=> #<ActiveRecord::Relation [#<Book id: 1, lang: "ruby", title: "Rubyは楽しいぞ!">, #<Book id: 2, lang: "python", title: "Pythonで自動化しよう!">, #<Book id: 3, lang: "javascript", title: "Javascriptでサイトに動きをつけよう!">, #<Book id: 4, lang: "ruby", title: "RubyでWebアプリを作ろう">, #<Book id: 5, lang: "python", title: "Pythonでデータ分析">, #<Book id: 6, lang: "javascript", title: "入門Javascript">, #<Book id: 7, lang: "javascript", title: "jQuery入門">, #<Book id: 8, lang: "ruby", title: "Rubyのクラスを学ぼう">, #<Book id: 9, lang: "python", title: "pythonでスクレイピング">, #<Book id: 10, lang: "php", title: "楽しいPHP">]>

このようにselectメソッドを実行することで、無駄な情報を省きメモリのリソースを節約できます。

またselectメソッドは、whereやfindメソッドと組み合わせて使用することも可能です。コンソールで下記コマンドを実行してください。

Book.where(price:1200).select(:id,:lang,:title,:price)

//実行結果
=> #<ActiveRecord::Relation [#<Book id: 1, lang: "ruby", title: "Rubyは楽しいぞ!", price: 1200>, #<Book id: 3, lang: "javascript", title: "Javascriptでサイトに動きをつけよう!", price: 1200>]>

先程実行したコマンドは、①priceが1200のデータのみ抽出 ②①で取得したデータから、id・lang・title・priceのみ抽出をおこなっています。selectメソッドに限らず、Active Recordのメソッド同士を組み合わせることで、より複雑な条件の検索が可能です。

Active Recordのメソッド② group編

次はgroupメソッドについてみていきましょう。groupメソッドは、特定のキーで結果をグループ化できます。

Bookモデルのlangカラムには、「ruby」「python」「javascript」「php」の4つが存在します。例えば、langの種類毎の価格の合計値を出したい場合に、「group」メソッドは有効です。

コンソールで下記コマンドを実行して、結果を確認してみましょう。

Book.group(:lang).sum(:price)

//実行結果
=> {"javascript"=>4000, "php"=>2000, "python"=>4700, "ruby"=>4100}

言語毎の価格の合計値を算出できました。このようにgroupメソッドは、sum(カラムの合計値を表示)などの集計関数と使います。

合計値だけでなく、最大値や平均値を求めることも可能です。

Book.group(:lang).maximum(:price)
=> {"javascript"=>1500, "php"=>2000, "python"=>2000, "ruby"=>1500}

Book.group(:lang).minimum(:price)
=> {"javascript"=>1200, "php"=>2000, "python"=>1100, "ruby"=>1200}

Book.group(:lang).ave(:price)

注)eは10を指し、e4であれば10の4乗という意味になります。
=> {"javascript"=>0.133333333333333e4, "php"=>0.2e4, "python"=>0.156666666666667e4, "ruby"=>0.136666666666667e4}

またgroupとcountメソッドを組み合わせることで、同じ種類のデータが何個あるのか算出可能です。

Book.group(:lang).count
=> {"javascript"=>3, "php"=>1, "python"=>3, "ruby"=>3}

このようにgroupメソッドは、複雑なデータの処理を簡単にできる強力な機能です。

コントローラーでgroupメソッドを使ってみよう

この章では、Active Recordのメソッドをコントローラーで使用する方法について解説していきます。この章のゴールは、「localhost:3000/books」で下画像のように、価格の平均値と合計値を表示させることです。

まずは、app / controllers /books_controller.rbを開き、indexアクションを下記コードのように変更してください。

 def index
    @books = Book.all
    @ave_books = Book.group(:lang).average(:price)
    @sum_books = Book.group(:lang).sum(:price)
  end

次にapp / views /books / index.html.erbを開き、下記コードを貼り付けてください。コードの中にある「round」は数値を四捨五入するメソッドです。

<%# 平均価格 %>
<h1>Average Books</h1>

<table>
  <thead>
    <tr>
      <th>Lang</th>
      <th>Average Price</th>
      <th colspan="2"></th>
    </tr>
  </thead>

  <tbody>
    <% @ave_books.each do |key,value| %>
      <tr>
        <td><%= key %></td>
        <td><%= value.round %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<%# 合計価格 %>
<h1>Sum Books</h1>

<table>
  <thead>
    <tr>
      <th>Lang</th>
      <th>Sum Price</th>
      <th colspan="2"></th>
    </tr>
  </thead>

  <tbody>
    <% @sum_books.each do |key,value| %>
      <tr>
        <td><%= key %></td>
        <td><%= value.round %></td>
      </tr>
    <% end %>
  </tbody>
</table>

「localhost:3000/books」にアクセスして、下画像が表示されれば成功です。

image

Webサイト担当者としてのスキルが身に付く

無料カウンセリングはこちら

まとめ

Active Recordのselectとgroupメソッドについて、学習してきました。selectやgroupは、データベースの言語であるSQLのコードを書かなくても、複雑なデータ処理ができる便利なメソッドです。

他にもorderメソッドなどと組み合わせると、ランキング機能などの実装も可能になります。ぜひ本記事で学んだ内容を復習してみてはいかがでしょうか。


関連記事

ヤマモト
この記事を書いた人
ヤマモト
まずは7日間お試し!人気プログラミング講座を無料公開中
オンライン・プログラミングレッスンNo.1のCodeCamp