rails - CRUDのまとめ
新規作成
レコードを新規作成する。
create
Entry.create title: "タイトル", body: "本文"
INSERT INTO "entries" ("body", "created_at", "title", "updated_at") VALUES (?, ?, ?, ?) [["body", "本文"], ["created_at", Wed, 05 Mar 2014 19:40:52 UTC +00:00], ["title", "タイトル"], ["updated_at", Wed, 05 Mar 2014 19:40:52 UTC +00:00]]
new & save
以下のように、インスタンスを作成後保存する方法でも可能
@entry = Entry.new title: "タイトル", body: "本文" @entry.save
INSERT INTO "entries" ("body", "created_at", "title", "updated_at") VALUES (?, ?, ?, ?) [["body", "本文"], ["created_at", Wed, 05 Mar 2014 19:41:27 UTC +00:00], ["title", "タイトル"], ["updated_at", Wed, 05 Mar 2014 19:41:27 UTC +00:00]]
更新
特定のレコードを更新する
update
クラスメソッド
Entry.update 7, title: "別のタイトル"
UPDATE "entries" SET "title" = ?, "updated_at" = ? WHERE "entries"."id" = 7 [["title", "別のタイトルです"], ["updated_at", Wed, 05 Mar 2014 19:25:53 UTC +00:00]]
インスタンスメソッド
@entry = Entry.find 7 @entry.update title: "別のタイトル"
UPDATE "entries" SET "title" = ?, "updated_at" = ? WHERE "entries"."id" = 7 [["title", "別のタイトル"], ["updated_at", Wed, 05 Mar 2014 19:24:58 UTC +00:00]]
find & update
レコードの属性を作成して更新してもよい
@entry = Entry.find 1 @entry.title = "新しいタイトル" @entry.save
UPDATE "entries" SET "title" = ?, "updated_at" = ? WHERE "entries"."id" = 11 [["title", "新しいタイトル"], ["updated_at", Wed, 05 Mar 2014 19:47:20 UTC +00:00]]
new & update
まだ保存されていないオブジェクトの場合は、新規作成される
@entry = Entry.new @entry.update title: "タイトル3"
INSERT INTO "entries" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Wed, 05 Mar 2014 19:29:09 UTC +00:00], ["title", "タイトル3"], ["updated_at", Wed, 05 Mar 2014 19:29:09 UTC +00:00]]
削除(destroy,delete)
destroy
before_destroy コールバックが呼び出される。
トランザクション内で実行される。
削除したオブジェクトを返す。
オブジェクトはfreezeされるため、再度保存することはできない。
(destroyed? メソッドで確認可能)
クラスメソッド
Entry.destroy 8
DELETE FROM "entries" WHERE "entries"."id" = ? [["id", 8]]
全レコードを1レコードずつ削除する。
1レコードずつトランザクション内で実行される。
Entry.destroy_all
DELETE FROM "entries" WHERE "entries"."id" = ? [["id", 9]] DELETE FROM "entries" WHERE "entries"."id" = ? [["id", 10]]
インスタンスメソッド
@entry = Entry.find 1 @entry.destroy @entry.destroyed? #=> true
DELETE FROM "entries" WHERE "entries"."id" = ? [["id", 12]]
delete
レコードの削除。
コールバックは呼び出されない。
クラスメソッド
削除したレコード数を返す。
Entry.delete 1
DELETE FROM "entries" WHERE "entries"."id" = 11
全レコードを削除する。
Entry.delete_all
DELETE FROM "entries"
インスタンスメソッド
削除したインスタンスを返す。freezeされるので新規保存は不可能。
@entry = Entfy.find 7 @entry.delete @entry.destroyed? #=> true
DELETE FROM "entries" WHERE "entries"."id" = 7
- 作者: 青木峰郎,後藤裕蔵,高橋征義
- 出版社/メーカー: SBクリエイティブ株式会社
- 発売日: 2013/07/24
- メディア: Kindle版
- この商品を含むブログを見る
rails - クエリの基本(2)
特定のフィールドを取得する
select を使う
User.select(:name)
SELECT name FROM "users"
複数のフィールド名を指定できる
User.select(:id, :name)
SELECT id, name FROM "users"
フィールド名は,区切りの文字列でもよい。
そのまま渡されるので max や minなども使える(てしまう)。
User.select("id,name")
SELECT id,name FROM "users"
ソートする
order を使う。
User.order(:created_at)
レコードの取得数と取得開始位置を制御する
limit と offset を使う。
主キー(id)のソートは無くなるので、orderで明示しないと
結果が異なる。
次の例は先頭5件目から30件ずつ表示する。
User.limit(30).offset(5)
SELECT "users".* FROM "users" LIMIT 30 OFFSET 5
なお、limit と offset は逆にしても同じ結果が得られる。
User.offset(5).limit(30)
グループ化する
group と having を使う。
必要な部分や集計結果を取得する用途には select とあわせて
使うことが多いだろう。
結果は呼び出し元のモデルクラスのインスタンスとして返される。
result = User.select("sex,count(sex) as sex_count").group(:sex).having("age < 20").order(:sex) result[0] # Userのインスタンス result[0].sex # 1 result[0].sex_count # 4
SELECT sex,count(sex) as sex_count FROM "users" GROUP BY sex HAVING age < 20 ORDER BY "users"."sex" ASC
- 作者: Rubyサポーターズ,すがわらまさのり,寺田玄太郎,三村益隆,近藤宇智朗,橋立友宏,関口亮一
- 出版社/メーカー: 技術評論社
- 発売日: 2013/08/10
- メディア: 大型本
- この商品を含むブログ (14件) を見る
rails - クエリの基本
クエリを行うメソッド
Model.take(limit)
レコードに格納されている最初の値を取得する。
limit省略時は 1。
Blog.take
SELECT "blogs".* FROM "blogs" LIMIT 1
Model.first(limit)
主キーでソートした最初の値を取得する
limit省略時は 1。
Blog.first
SELECT "blogs".* FROM "blogs" ORDER BY "blogs"."id" ASC LIMIT 1
Model.last(limit)
主キーでソートした最後の値を取得する
limit省略時は 1。
Blog.last
SELECT "blogs".* FROM "blogs" ORDER BY "blogs"."id" DESC LIMIT 1
Model.find
引数に primary_key (デフォルトは id) を指定する
Blog.find 5
SELECT "blogs".* FROM "blogs" WHERE "blogs"."id" = ? LIMIT 1 [["id", 5]]
キーに配列を指定すると複数のデータを取得できる
Blog.find [5,6]
SELECT "blogs".* FROM "blogs" WHERE "blogs"."id" IN (5, 6)
Model.find_by
引数に 検索条件を属性名:値 を渡すと、合致したレコードを取得できる
Blog.find_by user_id: 3
SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = 3 LIMIT 1
引数を複数渡すと、AND条件で結んだ条件と合致したレコードを取得できる
Blog.find_by user_id: 3, title: "タイトル"
SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = 3 AND "blogs"."title" = 'タイトル' LIMIT 1
複雑な条件を指定する
where を使う。
条件を直接SQLで指定する
SQLのwhere句を直接渡すことができる。
SQLインジェクション防止のため、変数を渡す際はプレースホルダを使うこと。
Blog.where "user_id = ?", params[:user_id]
SELECT "blogs".* FROM "blogs" WHERE (user_id = 3)
params[:user_id] = "1 OR 1" の場合。
プレースホルダを使わないと、
Blog.where "user_id = #{params[:user_id]}"
SELECT "blogs".* FROM "blogs" WHERE (user_id = 1 OR 1)
のように、全レコードを取得可能になってしまう。
プレースホルダを使うと、
Blog.where "user_id = ?", params[:user_id]
SELECT "blogs".* FROM "blogs" WHERE (user_id = '1 OR 1')
のように、適切にクオートされるので安全。
複数の条件を使う(1)
複数条件する場合は、プレースホルダの順番に値を渡す
Blog.where "user_id = ? AND created_at >= ?", params[:user_id], params[:created_at]
SELECT "blogs".* FROM "blogs" WHERE (user_id = 3 AND created_at >= '2014-02-17 19:15:35.523440')
複数の条件を使う(2)
? のかわりに Keyを指定し、値を Key/Value 型のHash を渡してもよい。
Blog.where "user_id = :user_id AND created_at >= :created_at", { user_id: params[:user_id], created_at: params[:created_at]}
SELECT "blogs".* FROM "blogs" WHERE (user_id = 3 AND created_at >= '2014-02-17 19:15:35.523440')