0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

基礎Ruby on Rails Chapter4 データの保存

Last updated at Posted at 2018-09-21

基礎Ruby on Rails Chapter4 データベースとモデル
基礎Ruby on Rails Chapter5 RESTとルーティング

レコードの作成と更新

Railsコンソール

  • Railsコンソールを起動するには、bin/rails cコマンドを実行する。
  • Member.countで、membersテーブルの件数をカウントする。
$ bin/rails c
Loading development environment (Rails 5.2.1)
irb(main):001:0> Member.count
   (0.2ms)  SELECT COUNT(*) FROM "members"
=> 0
irb(main):002:0>

レコードの作成

  • member = Member.newでインスタンス作成、属性を設定して、saveメソッドでレコードを保存する。
irb(main):002:0> member = Member.new
=> #<Member id: nil, number: nil, name: nil, full_name: nil, email: nil, birthday: nil, sex: 1, administrator: false, created_at: nil, updated_at: nil>
irb(main):003:0> member.number=1
=> 1
irb(main):004:0> member.name="Taro"
=> "Taro"
irb(main):005:0> member.save
   (0.0ms)  begin transaction
  Member Create (6.1ms)  INSERT INTO "members" ("number", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["number", 1], ["name", "Taro"], ["created_at", "2018-09-20 12:03:44.207546"], ["updated_at", "2018-09-20 12:03:44.207546"]]
   (14.4ms)  commit transaction
=> true
irb(main):006:0>
  • レコードの作成方法は以下のいずれかが考えられる。
    • member = Member.newmember.number = 1member.name = "Taro"member.save
    • member = Member.new(number: 1, name: "Taro")member.save
    • member = Member.newmember.assign_attributes(number: 1, name: "Taro")member.save
    • member = Member.create(number: 1, name: "Taro")
  • saveメソッドはバリデーションが失敗した場合はfalseを返す。
  • save!メソッドは、バリデーションに失敗した場合は例外が発生する。

レコードの更新

  • レコードの更新方法は以下のいずれかが考えられる。
    • member = Member.firstmember.number = 41member.save
    • member = Member.firstmember.assign_attributes(number: 51, name: "Ichiro")member.save
    • member = Member.firstMember.update_attributes(number: 55, name: "Hideki")
irb(main):006:0> member = Member.first
  Member Load (5.4ms)  SELECT  "members".* FROM "members" ORDER BY "members"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Member id: 1, number: 1, name: "Taro", full_name: nil, email: nil, birthday: nil, sex: 1, administrator: false, created_at: "2018-09-20 12:03:44", updated_at: "2018-09-20 12:03:44">
irb(main):007:0> member.assign_attributes(number: 51, name: "Ichiro")
=> nil
irb(main):008:0> member.save
   (0.1ms)  begin transaction
  Member Update (1.5ms)  UPDATE "members" SET "number" = ?, "name" = ?, "updated_at" = ? WHERE "members"."id" = ?  [["number", 51], ["name", "Ichiro"], ["updated_at", "2018-09-20 12:16:35.031549"], ["id", 1]]
   (11.1ms)  commit transaction
=> true

シードデータの投入

シードデータの使い方

  • db/seeds.rbに、シードデータを作成するスクリプトを書いて、bin/rails db:seedコマンドを実行すれば、シードデータが保存される。
  • 本番環境の場合は、bin/rails db:seed RAILS_ENV=productionのように、環境変数を付加する。
db/seeds.rb
Member.create(number: 1, name: "Taro", administrator: true)
$ bin/rails db:seed

モード別のシードデータ

  • db/seeds/developmentディレクトリの下に、members.rbがあれば、それをrequireメソッドで実行する。
db/seeds.rb
table_names = %w(members) # ほかに入れたいテーブルがあれば、ここに空白区切りで追加して、rbファイルも作る
table_names.each do |table_name|
  path = Rails.root.join("db/seeds", Rails.env, table_name + ".rb")
  if File.exist?(path)
    puts "Creating #{table_name}..."
    require path
  end
end
  • memberにデータを投入するプログラム
db/seeds/development/members.rb
names = %w(Taro Jiro Hana John Mike Sophy Bill Alex Mary Tom)
fnames = ["佐藤", "鈴木", "高橋", "田中"]
gnames = ["太郎", "次郎", "花子"]
0.upto(9) do |idx|
  Member.create(
    number: idx + 10,
    name: names[idx],
    full_name: "#{fnames[idx % 4]} #{gnames[idx % 3]}",
    email: "#{names[idx]}@example.com",
    birthday: "1981-12-01",
    sex: [1, 1, 2][idx % 3],
    administrator: (idx == 0)
  )
end

シードデータの再投入

# データベースを破棄→db/schema.rbを実行→シードデータの投入
$ bin/rails db:reset
# データベースを破棄→最初からマイグレーションをやり直す→シードデータの投入
$ bin/rails db:migrate:reset db:seed
  • db:rebuildタスク
lib/tasks/database.rake
namespace :db do
  desc "Rebuild the development database from scratch"
  task :rebuild => :environment do
    sh "rm -f db/development.sqlite3"
    Rake::Task["db:migrate"].invoke
    Rake::Task["db:seed"].invoke
  end
end
  • 上記コマンドを使って、シードデータの再投入をする。
$ bin/rails db:rebuild

findとfind_by

findメソッド

  • find(キーの値)で、レコードを1件取得する。
  • 該当データが無い場合、例外ActiveRecord::RecordNotFount発生。

find_byメソッド

  • find_by(項目名1: 値1, 項目名2: 値2, ・・・)で、最初に一致したレコードを1件取得する。
  • 該当データが無い場合、nilが返る。

クエリーメソッドとリレーションオブジェクト

クエリーメソッドとリレーションオブジェクト

  • whereメソッドは、条件に一致する複数のレコードを取り出す。
  • 実際に返すのは、配列ではなくActiveRecord::Relationクラスのオブジェクト。
  • Member.where(name: "Taro")Member.where("number < 20")のように書ける。

検索が実行されるタイミング

  • whereメソッドは、呼び出しただけでは検索は実行されない。検索が実行されるのはデータが必要になった時。
  • @members = Member.where(sex: 2).load のようにloadメソッドを使うと、即座に実行される。
  • lengthメソッドは検索を実行して、配列を作ったうえで配列の長さを返す。必ず結果を使うのなら、こちらがいい。
  • sizeメソッドはcountメソッド呼び出して、SQLで件数をカウントする。件数によって結果を取得しないのなら、こちらがいい。

クエリーメソッドの重ね合わせ

  • whereをAND条件で結びつける。
# 2つの検索条件をANDで結びつける
members = Member.where(name: "Taro")
members = members.where("number < 20")
# 1行でまとめる
members = Member.where(name: "Taro").where("number < 20")
  • whereとorderに組み合わせ
# ソート順を指定する。
members = Member.where(sex: 2).order("number")
# 引数をハッシュにする書き方
members = Member.where(sex: 2).order(number: :desc)

ファインダーメソッドとの組み合わせ

  • firstメソッドは先頭から1つだけ取り出す。
  • lastメソッドは最後から1つ取り出す。
  • firstとlastはソート順をつけること。付けないと結果が不定になる。
  • そのほか、find(1)、find_by(id:1)。
members = Member.where(sex: 2).order("number").first

whereメソッドの便利な使い方

  • カラム値:配列というハッシュを渡すと、どれかと同じという検索条件を指定できる。
# 配列で取り出す。
members = Member.where(number: [15,17,19])
members.map(&:name)
# = ["Sophy","Alex","Tom"]
  • カラム値:範囲オブジェクトというハッシュを渡すと、その範囲という検索条件を指定できる。
# 範囲で取り出す。
members = Member.where(number: 12..14)
members.map(&:name)
  • notメソッドは、〇〇でないという検索条件を指定できる。
# 範囲で取り出す。
members = Member.where.not(name: "Taro")

プレースホルダー

  • ?に、変数の値を埋め込む。SQLインジェクション対策。
name = "Taro"
members = Member.where("name = ?", name)

集計用のメソッド

  • average(カラム名)countmaximum(カラム名)minimum(カラム名)sum(カラム名)で集計をすることができる。
Member.maximum("number") 
# = 19
Member.where(sex: 1).count
# = 7
  • SQLを直接書くには、find_by_sqlメソッドを使う
members = Member.find_by_sql("SELECT * FROM members WHERE number = 11")
# プレースホルダーを使うには、配列で指定する
members = Member.find_by_sql(["SELECT * FROM members WHERE name = ?", "Taro"])

参考
改訂4版 基礎 Ruby on Rails (IMPRESS KISO SERIES)

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?