読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

Railsのモデルの作成、検索、更新、削除のよく使うメソッドのまとめ

Rails初級 Rails Model

Rails(Active Record)でのモデルの作成、検索、更新、削除でよく使うメソッドをまとめました。

動作確認

  • Rails 4.1

目次

  1. モデルの生成と保存
  2. モデルの検索
  3. モデルの更新
  4. モデルの削除

※モデルの検証や関連については、こちら
※モデルの挙動がわかりづらい場合は、rails c -sで、サンドボックスモードで下記のコマンドを実行してみてください。




1. モデルの生成と保存

属性を設定してモデルオブジェクトを生成する(newメソッド)

newメソッドにカラム名と値ををハッシュで渡すことで値を設定してモデルオブジェクトを生成することができる。

user = User.new(name: "田中", email: "tanaka@test.co.jp") 
ハッシュで値を設定する

モデルオブジェクトのattributes属性にカラム名と値をハッシュで渡すことで、モデルオブジェクトに一気に値を設定することができる。

user = User.new
user.attributes = {name: "田中", email: "tanaka@test.co.jp"}
モデルを保存する

saveメソッドで保存する。
バリデーションエラーが発生した場合は falseが返る。さらに、errors.full_messagesにエラーメッセージが設定される

user.save
# => true (ユーザーがDBに保存された)

user.save
# => false (バリデーションエラーが発生したため、DBに保存されなかった)
user.errors.full_messages
# => ["Name can't be blank", "Name is too short (minimum is 5 characters)"]


save!メソッドで保存すると、バリデーションエラーが発生した場合にActiveRecord::RecordInvalidが発生する。

# バリエーションエラーの場合
user.save!
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank, Name is too short (minimum is 5 characters)


また、validate: falseを引数で渡すことで、バリデーションの確認をスキップし、DBにレコードを保存することができる。

# Validateが行われない
user.save(validate: false)
user.save!(validate: false)
モデルを生成し、保存する(createメソッド)

createメソッドを使えば、newsaveメソッドを一度に実行できます。

# モデルの生成と保存
User.create(name: "田中", email: "tanaka@test.co.jp") 
# バリデーションエラーの発生有無にかかわらず、生成したモデルが返される
# バリデーションエラーが発生しなかった時
# => #<User id: 3, name: "aiueoss", password: nil, confirm_password: nil, created_at: "2014-11-23 11:29:47", updated_at: "2014-11-23 11:29:47", active: nil>

# バリデーションエラー発生時
# => #<User id: nil, name: nil, password: nil, confirm_password: nil, created_at: nil, updated_at: nil, active: nil>

## create!メソッドを使うと、validationエラー時に例外ActiveRecord::RecordInvalidが発生する


全てのレコードを取得する(allメソッド)
users = User.all # Userテーブルの全てのレコードを取得
最初のレコードと最後のレコードを取得する(first / lastメソッド)
first_user = User.first # 最初のレコードを返す
last_user = User.last # 最後のレコードを返す
IDで検索する(findメソッド)
user = User.find(1)  # "1"はidのことで、idで検索する
users = User.find([1,2,3]) # 配列を引数で渡すことも可能

## レコードが存在しない場合は以下のActiveRecord::RecordNotFoundが発生する
## ActiveRecord::RecordNotFound: Couldn't find User with 'id'=3
ID以外のカラムで検索する(find_byメソッド)
# emailで検索する
user = User.find_by(email: "text@example.com")
## レコードが存在しない場合は、nilを返す
検索条件を指定して検索する(whereメソッド)

SQLのwhereのように検索できる。SQLインジェクションに注意

user = User.where("name = ?", "test")
## 疑問符 ? があることで、適切にエスケープされることを保証してくれるためSQLインジェクションの防止に繋がる

# 可読性を上げるために、次のようにも記載できる
user = User.where("name = :name", name: "test")


whereメソッドをチェインすることも可能

user = User.where("name = :name", name: "test").where(active: true)

# もちろん、メソッドチェインしなくても記載可能
user = User.where("name = :name and active = :active", name: "test", active: true)
部分一致検索(LIKE句の使用)
users = User.where("email like ?",  "%" + "gmail.com")
検索順序を指定(orderメソッド)
# pay_typeの昇順(デフォルト)、shipped_atの降順(DESC)で取得する
orders = Order.where(name: 'Ruby on Rails Web book').order("pay_type, shipped_at DESC")
取得件数を指定(limitメソッド)
# 最新の5件の注文を取得する
orders = Order.order(:created_at).limit(5)
GROUP BY句の使用
summary = LineItem.select("sku, sum(amount as amount").group("sku")
取得する値を指定する(selectメソッド)

Railsはデフォルトでは"select * from ..."で検索をする。しかし、カラムに画像などの大容量のrawデータを含んでいるときなどに、全てのカラムを取得したくないときなどに利用できる。

videos = Video.select("title, speaker, created_at")
関連テーブルの結合(joinsメソッド)

joinsメソッドを使うことで、INNTER JOINが行われる。

Blog.joins(:entries)
# => SELECT blogs.* FROM blogs INNER JOIN entries ON entries.blog_id = blogs.id

また、関連テーブルの検索条件を追加することも可能。

entries = Entry.joins(:blog).where("blogs.name LIKE ?", "%me%")


さらに文字列で結合条件を自由に記述することも可能。

User.joins("LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id")
=> SELECT "users".* FROM "users" LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id
列の集計メソッド
average = Order.average(:amount)
max      = Order.maximum(:amount)
min       = Order.minimum(:amount)
total      = Order.sum(:amount)
number = Order.count


3. モデルの更新

インスタンスメソッド

カラムに直接代入して更新する
user.name = "やっぱり鈴木"
user.save
複数のカラムを更新する(updateメソッド)
user.update( name: "やっぱり鈴木", email: "suzuki@test.co.jp" )
# 更新成功時 => true、更新失敗時 => false
1つのカラムを更新する(update_attributeメソッド)

update_attributeメソッドは、バリデーションは行われないので注意してください。

user.update_attribute(:name, "やっぱり鈴木")
reloadメソッド

更新したカラムをDBと同じにする。
使用する箇所としては、ユニットテストぐらいしかほぼない。

user.email #=> tanaka@test.co.jp
user.update_attribute( {email: "Validatioエラーするemail"} ) # => false
user.email # =>  DBは更新されていないが、値は "Validatioエラーするemail"になってる
user.reload.email
user.email #=> tanaka@test.co.jp

クラスメソッド

複数のレコードを更新する - update(id, attributes)メソッド

指定したidかその配列に該当するレコードを、指定した属性のセット(ハッシュ)で更新する。
バリデーションは行われないので注意してください。

# idが1のレコードのsaleをtrueにdiscount_rateを0.2に更新する
# idが2のレコードのnameをproduct2に更新する
product = { 1 => { sale: true, discount_rate: 0.2 }, 2 => { name: 'product2' } }
Product.update(product.keys, product.values)
update_all(updates)メソッド

SQLのupdate文のset句とwhere句を指定して、更新する。
バリデーションは行われないので注意してください。

Product.update_all("price = 1.1*price", "title like '%水着'")


4. モデルの削除

インスタンスメソッド

レコードを削除する(destroyメソッド)
# ユーザーレコードをDBから削除する
user.destroy

クラスメソッド

すべてのレコードを削除する(delete_allメソッド)
User.delete_all
# => 10 (削除した件数を返す)


以上です。

参考文献