天天看點

【Rails】inverse_of在has_many和belongs_to中的用法

最近使用Rails時,遇到了通過關聯關系來多次通路同一條record,雖然得到的内容一樣,但是每次都會建立不同對象的情況。

通過查詢Rails官方文檔,找到了對關聯關系的一種設定inverse_of,可以避免在一些情況下重複建立對象的問題。

但是,文檔中提到了inverse_of的限制:

  • 不能和 :through 選項同時使用
  • 不能和 :polymorphic 選項同時使用
  • 不能和 :as 選項同時使用
  • 在 belongs_to 關聯中,會忽略 has_many 關聯的 inverse_of 選項

對于最後一條,文檔并沒有詳細解釋,是以我針對于Rails3.2.18版本做了試驗,但得到的結果與文檔中的例子并不一緻,現我把實驗步驟和結果貼出來供大家參考讨論。

1. 不設定inverse_of

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end
           

rails c

結果展示:

p = Post.first
c = p.comments.first
c.post.object_id == p.object_id # => false
           

可以看出,當不設定inverse_of時,

c.post

p

在記憶體中指向不同的對象。

2. has_many設定inverse_of

class Post < ActiveRecord::Base
  has_many :comments, :inverse_of => :post
end

class Comment < ActiveRecord::Base
  belongs_to :post
end
           

rails c

結果展示:

p = Post.first
c = p.comments.first
c.post.object_id == p.object_id # => true
           

可以看出,當在has_many處設定inverse_of時,

c.post

p

在記憶體中都指向同一個對象。

3. belongs_to設定inverse_of

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post, :inverse_of => :comments
end
           

rails c

結果展示:

p = Post.first
c = p.comments.first
c.post.object_id == p.object_id # => false
           

可以看出,當在belongs_to處設定inverse_of時,

c.post

p

在記憶體中指向不同的對象。

4. has_many和belongs_to都設定inverse_of

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post, :inverse_of => :comments
end
           

rails c

結果展示:

p = Post.first
c = p.comments.first
c.post.object_id == p.object_id # => true
           

可以看出,當在has_many和belongs_to處都設定inverse_of時,

c.post

p

在記憶體中都指向同一個對象。

通過上面4個測試,可以看到真正起作用的是:在has_many處設定inverse_of,而不是在belongs_to處設定。并且,當同時在has_many和belongs_to設定inverse_of的時候,文檔中所描述的“在 belongs_to 關聯中,會忽略 has_many 關聯的 inverse_of 選項”是不正确的,此時has_many處設定的inverse_of是有效的。

以上是本人的意見看法,如有錯誤,歡迎大家指正讨論。

轉載請注明出處:http://blog.csdn.net/sunset108/article/details/51742228