default scopeの被害報告

32
default_scope の 被害報告 2015/03/28 minami.rb 最初で最後のLT大会 無量井 健(@muryoimpl) https://www.flickr.com/photos/jakerust/16827350035

Upload: ken-muryoi

Post on 15-Jul-2015

1.252 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Default scopeの被害報告

default_scope の 被害報告

2015/03/28 minami.rb 最初で最後のLT大会

無量井 健(@muryoimpl)

https://www.flickr.com/photos/jakerust/16827350035

Page 2: Default scopeの被害報告

自己紹介

• 無量井 健(むりょうい けん)

• 永和システムマネジメント 7ヶ月目

• Ruby関西, 関西Ruby会議04・05, るびま etc

• 休日は、低機動型寝たきり二時間サスペンス廃人

Page 3: Default scopeの被害報告

皆さんご存知だと おもいますが

https://www.flickr.com/photos/aruarian/2626408619

Page 4: Default scopeの被害報告

https://www.flickr.com/photos/aruarian/2626408619

default_scope

Page 5: Default scopeの被害報告

default_scopeclass Item < ActiveRecord::Base default_scope -> { order(:order_no) } end

irb(main)> Item.find(1) SELECT "items".* FROM “items" WHERE "items"."id" = ? ORDER BY “items"."order_no" DESC LIMIT 1 [["id", 1]]

https://www.flickr.com/photos/lintmachine/3652702115

Page 6: Default scopeの被害報告

何もしなくても 勝手に

条件がつきますねhttps://www.flickr.com/photos/aruarian/2626408619

Page 7: Default scopeの被害報告

便利ですね

https://www.flickr.com/photos/aruarian/2626408619

Page 8: Default scopeの被害報告

default_scope の条件外す方法 ありますね

https://www.flickr.com/photos/aruarian/2626408619

Page 9: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

unscopedirb(main)> Item.unscoped.find(1) SELECT "items".* FROM “items" WHERE "items"."id" = ? DESC LIMIT 1 [["id", 1]]

irb(main)> Item.unscoped { Item.find(1) } SELECT "items".* FROM “items" WHERE "items"."id" = ? LIMIT 1 [["id", 1]]

Page 10: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

exceptirb(main)> Item.except(:order).find(1) SELECT "items".* FROM “items" WHERE "items"."id" = ? DESC LIMIT 1 [["id", 1]]

Page 11: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

unscopeirb(main)> Item.unscope(:order).find(1) SELECT "items".* FROM “items" WHERE "items"."id" = ? DESC LIMIT 1 [["id", 1]]

Page 12: Default scopeの被害報告

外れましたね?

https://www.flickr.com/photos/aruarian/2626408619

Page 13: Default scopeの被害報告

調べると だいたいこういう例が

載っていますhttps://www.flickr.com/photos/aruarian/2626408619

Page 14: Default scopeの被害報告

さてhttps://www.flickr.com/photos/aruarian/2626408619

Page 15: Default scopeの被害報告

結合とかしてたら どうですかね?

https://www.flickr.com/photos/aruarian/2626408619

Page 16: Default scopeの被害報告

includesしてみるぞ

class Author < ActiveRecord::Base has_many :posts

default_scope -> { where(status: :ok) } end

class Post < ActiveRecord::Base belongs_to :author end

https://www.flickr.com/photos/lintmachine/3652702115

Page 17: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

includesしてみるぞirb(main)> Post.includes(:author) .where(status: :ok) .where(authors: {name: ‘a’}) SELECT "posts"."id" AS t0_r0, … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = “posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 18: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

unscopedirb(main)> Author.unscoped { Post.includes(:author) .where(status: :ok) .where(authors: {name: ‘a’}) } SELECT "posts"."id" AS t0_r0, … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = “posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 19: Default scopeの被害報告

外れない!https://www.flickr.com/photos/aruarian/2626408619

Page 20: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

exceptirb(main)> Post.includes(:author).except(:where) .where(status: :ok) .where(authors: {name: ‘a’}) SELECT "posts"."id" AS t0_r0, … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = “posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 21: Default scopeの被害報告

そもそも ON句だし…

https://www.flickr.com/photos/aruarian/2626408619

Page 22: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

exceptirb(main)> Post.includes(:author) .except(on: :status) #ないよね…無視される .where(status: :ok) .where(authors: {name: ‘a’}) SELECT "posts"."id" AS t0_r0, … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = “posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 23: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

unscopeirb(main)> Post.includes(:author) .unscope(on: :status) #ないよね… .where(status: :ok) .where(authors: {name: ‘a’})

ArgumentError: Hash arguments in .unscope(*args) must have :where as the key.

Page 24: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

unscopeirb(main)> Post.includes(:author) .unscope(where: :status) .where(status: :ok) .where(authors: {name: ‘a’}) SELECT "posts"."id" AS t0_r0 … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 25: Default scopeの被害報告

別の関連つくって…class Author < ActiveRecord::Base has_many :posts

default_scope -> { where(status: :ok) } end

class Post < ActiveRecord::Base belongs_to :author belongs_to :unscoped_author, -> { unscope(where: :status) }, foreign_key: :author_id, class_name: ‘Author’ end https://www.flickr.com/photos/lintmachine/3652702115

Page 26: Default scopeの被害報告

https://www.flickr.com/photos/lintmachine/3652702115

別の関連つくって…irb(main)> Post.includes(:unscoped_author) .where(status: :ok) .where(authors: {name: ‘a’}) SELECT "posts"."id" AS t0_r0, … FROM "posts" LEFT OUTER JOIN "authors" ON "authors"."id" = “posts"."author_id" AND "authors"."status" = ? WHERE "authors"."name" = ? [["status", 1], ["name", "a"]]

Page 27: Default scopeの被害報告

やはり 外れない!

https://www.flickr.com/photos/aruarian/2626408619

Page 28: Default scopeの被害報告

https://www.flickr.com/photos/alvarez-tostado/363243449

マ”マ”ーーー

Page 29: Default scopeの被害報告

https://www.flickr.com/photos/alvarez-tostado/363243449

ということで…

Page 30: Default scopeの被害報告

https://www.flickr.com/photos/alvarez-tostado/363243449

泣きながら こうした…

Page 31: Default scopeの被害報告

default_scopes =[]class Author < ActiveRecord::Base has_many :posts

default_scope -> { where(status: :ok) } end

class UnscopedAuthor < Author # ↓ここがポイント self.default_scopes = [] end

class Post < ActiveRecord::Base belongs_to :author belongs_to :unscoped_author, foreign_key :author_id end https://www.flickr.com/photos/lintmachine/3652702115

Page 32: Default scopeの被害報告

default_scopeさん…• こんな罠がありました… • 単一モデルしか検索しない間は便利さしか感じないかもしれませんが…SQL的にJOINすることになると面倒なことになります(なりました)

• 少し面倒なクエリを考えるときに直面するのですよ…この問題

• 後悔しないように、scopeを毎回つけるか設計を見直すほうが良いと思います

https://www.flickr.com/photos/71508688@N00/5139944772