2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

STIとポリモーフォック関連は相容れない

Posted at

はじめに

TECH::CAMPで仕事をしている時に、STIとポリモーフォック関連を同時に使える場面があった。設計段階では2つとも使おうと思っていたけれども、実際に実装しようと思ったらポリモーフィズム関連が必要ないことがわかった。

例えば、以下のように User モデルを継承している、 AdminNormalUser があるとする。そして、全てのユーザーが画像をいくつか持っているとする。そうすれば、STIとポリモーフォック関連を使用すると以下のようなコードが出来る。

class User < ActiveRecord::Base
end

class Admin < User
  has_many :images, as: :imageable
end

class NormalUser < User
  has_many :images, as: :imageable
end

class Image < ActiveRecord::Base
  belongs_to :imageable, polymorphic: true
end

だがしかし、ここで問題なのは image.imageable_type に本来なら、 AdminNormalUser をいれたいはずなのだが、Railsは親クラスの User を使う。

そもそもの役割

ポリモーフィック関連

http://qiita.com/itkrt2y/items/32ad1512fce1bf90c20b
こちらのQiitaの記事が非常によく、ポリモーフィックの利点・目的を説明していると思います。結論的にいうと、ポリモーフィック関連は、名前の通り ポリモーフィズム を実装するために使われるものです。

STI

http://qiita.com/yebihara/items/9ecb838893ad99be0561
こちらも非常にいい記事で、この中に 「STIは「継承」の実装、ポリモーフィック関連は「関連」の実装なので、両者を比較するのは不適切です。」という文言がありますが、僕は2つでかぶっている役割があると思います。

理由

ではなぜ、この2つは相容れないのでしょうか。それは、STIがポリモーフィズムも含めて実装してしまえるからです。突き詰めれば、STIはクラスの継承でしかなく、クラスの継承というものの利点の一つにポリモーフィズムが含まれています。つまりは、上記の例のように、STIとポリモーフィック関連を一緒に使ってしまうと、役割が重複してしまうのです。上記の例だと、ポリモーフィズムの最終的な目標は以下のように、 user が 果たして admin であろうが normal_user であろうがメソッド呼び出し時に気にせずにメソッドが使えるということです。これはポリモーフィック関連だろうが、STIであろうが実現可能です。

def open_image(user)
  user.image.open
end

open_image(admin_user)
open_image(normal_user)

どっちを使ってもいいのか

いえ、そうではありません。あくまで、STIはクラスの継承なので、ポリモーフィズムを含むであって、他にも素敵なオブジェクティブ指向的なものが実現されます。なので、どちらも使用可能な時はSTIを使うべきです。

どっちも使うときはないのか

あります。例えば、今回の例で行くと、 User とは全く関係ないモデルが has_many :images の関係だとすれば、どちらも使います。ただ、これは、Userと他のモデルなので、STIと一緒に使えるとが言えないかもしれませんが・・・

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?