Default scopeの被害報告

  • View
    1.249

  • Download
    0

  • Category

    Software

Preview:

Citation preview

default_scope の 被害報告

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

無量井 健(@muryoimpl)

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

自己紹介

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

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

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

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

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

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

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

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

何もしなくても 勝手に

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

便利ですね

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

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

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

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]]

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]]

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]]

外れましたね?

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

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

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

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

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

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

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

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"]]

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"]]

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

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"]]

そもそも ON句だし…

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

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"]]

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.

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"]]

別の関連つくって…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

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"]]

やはり 外れない!

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

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

マ”マ”ーーー

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

ということで…

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

泣きながら こうした…

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

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

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

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

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

Recommended