k01ken’s b10g

He110 W0r1d!

Railsでデータベースとのやりとりをするメソッドのまとめ

開発環境は、Windows 7 Professional(32bit) + ruby 2.3.3p222 + Rails 4.2.1。

■データを追加する
・postsテーブル(モデル名はpost)のname,ageカラムにデータ(nameカラムにはTaro、ageカラムには20)を入れるとする。今回は以下に4つの方法を書いておく。

post = Post.new
post.name = "Taro"
post.age = 20
post.save

post = Post.new
post.assign_attributes(name: "Taro", age: 20)
post.save

post = Post.new(name: "Taro", age: 20)
post.save

Post.create(name: "Taro", age: 20)


■データを更新する
・idが3のデータのname,ageカラムにデータが入っているとして、新たなデータ(nameカラムには、Hanako、ageカラムには30)を入れて、データを上書きします。以下に3つの方法を書いておきます。

post = Post.find(3)
post.name = "Hanako"
post.age = 30
post.save

post = Post.find(3)
post.assign_attributes(name: "Hanako", age: 30)
post.save

# update_attributesは、assign_attributesとsaveを合わせたようなもの
post = Post.find(3)
post.update_attributes(name: "Hanako", age: 30)

# 取得した複数のレコードを一気に変更する
# urlカラムがhttp://k01ken.hatenablog.com/で始まっているレコードすべてのmobile_friendlyカラムをtrueに変更する
Post.where("url LIKE 'http://k01ken.hatenablog.com/%'").update_all(mobile_friendly: true)

参考リンク
ActiveRecord の attribute 更新方法まとめ



■データを削除する

post = Post.find(1)
post.destroy


■データを取得する

post = Post.first

# allは、Rails 3.2まではすべてのレコードをモデルオブジェクトの配列にして返していた
# Rails 4からは検索条件のないリレーショナルオブジェクトを返すようになった
posts = Post.all

# idが3のデータを取得する。存在しない数字を入力すると例外が発生
post = Post.find(3)

# 任意のカラムを使ってレコードを検索する
# 以下の場合は、nameカラムがTaroのデータを取得する
# なければnilを返す
posts = Post.find_by(name: "Taro")
# カラムは複数指定することができる
posts = Post.find_by(name: "Taro", age: 20)

# where句を使ってデータを取得する
posts = Post.where(name: "Taro")
# whereメソッドを複数つなげることで複数の条件を指定できる。
posts = Post.where(name: "Taro").where(age: 30)
# 文字列で検索条件を指定することもできる。ageが30より小さいものを取得。
posts = Post.where("age < 30")
# WHEREの否定も使える。以下はnameカラムがTaro『でない』データを取得。
posts = Post.where.not(name: "Taro")
# ハッシュの値を配列にすると、複数の候補のどれかと同じなら取得。
posts = Post.where(id: [2,7,13])
# ハッシュの値を範囲オブジェクトにすると、その範囲の値があれば取得。
posts = Post.where(id: 5..10)

whereメソッドでは、条件に文字列などを入力しますが、外部から受け取る場合、文字列中にシングルクォテーションなどを挿入して、SQLインジェクションを起こそうとする人がいるため、その対策として、プレースホルダーというものを使います。SQL文に書かれた?を文字列に置き換えます。

name = "Taro"
posts = Post.where("name = ?", name)

# プレースホルダーは複数指定できます。
posts = Post.where("name = ? AND member = ?", "Taro", true)


whereメソッドなどのリレーショナルオブジェクトは、書いた時点では実行されず、Rubyと同名の配列に関するメソッドである、eachやmapやlengthを用いることで始めて実行され、モデルオブジェクトの配列が得られる。もし、すぐにモデルオブジェクトを得たければ、

posts = Post.where(name: "Taro").load

上記のように、loadメソッドを用います。


Railsのメソッドを用いたSQLのSELECT文の書き方

メソッドはメソッドチェーンでつなげることができます。SQLと違って、つなげる順番は自由です。
select(文字列) - SELECT
from(文字列) - FROM
joins(シンボル/文字列) - JOIN - テーブルの結合
includes(シンボル) - データベースによる - 関連付けの名前を指定することで関連するモデルオブジェクトをロード。
where(ハッシュ/文字列/配列) - WHERE - 検索条件の指定
group(文字列) - GROUP
having(文字列) - HAVING
limit(整数) - LIMIT - 取得するレコード数の上限
offset(整数) - OFFSET - 何行目のレコードから取得するか指定
order(文字列/シンボル/ハッシュ) - ORDER BY - ソート対象のカラム名

# カラム名をシンボルで指定
posts = Post.where(age: 30).order(:id)
# カラム名をハッシュのキーとして、降順/昇順を :desc or :ascでハッシュの値に指定
posts = Post.where(age: 30).order(id: :desc)

reorder(文字列) - ORDER BY - ORDER BY句の上書き
reverse_order - ORDER BY - ORDER BY句の降順/昇順を逆にする
lock(文字列) - データーベースによる - MySQLのロック機能をつかう
readonly - レコードを読み込み専用にする
distinct - 検索結果の重複をなくす
none - 何も検索しないリレーショナルオブジェクトを返す


■発行されたSQL文を知る

posts = Post.all
puts posts.to_sql


SQL文を直接書く

posts = post.find_by_sql("select * from posts where name = 'Taro'")

# SQL文でプレースホルダーを用いる場合、全体を配列で指定しないといけない。
posts = post.find_by_sql(["select * from posts where name = ?", "Taro"])