Ruby on Rails 3: Ассоциации между моделями ч. 2

апреля 26, 2012  |  Published in Ruby on Rails, Ruby on Rails 3, Базы данных

ruby on rails tutorial Ассоциации между моделями ч. 1. В этой статьи мы поговорим об интересных параметрах и возможностях ассоциаций моделей.

Псевдонимы

Часто бывает необходимо или желательно использовать отличное от имени модели имя ассоциации. Например у нас есть две модели Store и User и у Store имеется владелец (seller — продавец). store.user выглядит не очень красиво, как буд-то речь идет о пользователе магазина, а не о его владельце (продавце), кроме того, у нас может быть несколько ассоциаций с моделью User, например у нас может быть buyer и seller.

 

Чтобы реализовать такие псевдонимы и множественные ассоциации между двумя моделями мы можем воспользоваться следующим кодом:

class User < ActiveRecord::Base
  if seller?
    has_one: :store, foreign_key: seller_id, dependent: :destroy
  elsif buyer?
    belongs_to :store
  end

  def seller?; role == 'seller'; end
  def buyer?; role == 'buyer'; end
end

class Store < ActiveRecord::Base
  has_many   :buyers, class_name: 'User'
  belongs_to :seller, class_name: 'User'
end

Полиморфизм

Полиморфные ассоциации — это ассоциации, где несколько различных сущностей (моделей) в контексте ассоциации представляются как одна единственная. Примером полиморфных ассоциаций могут служить комментарии. Единственная сущность Comment может принадлежать как статьям — Article, топикам — Topic и собственно другим комментариям, если разрешены вложенные комментарии. Пример:

class Article < ActiveRecord::Base
  has_many :comments, as: :commentable, dependent: :destroy
end

class Topic < ActiveRecord::Base
  has_many :comments, as: :commentable, dependent: :destroy
end

class Comment < ActiveRecord::Base
  has_many   :comments, as: :commentable, dependent: :destroy
  belongs_to :commentable, polymorphic: true
end

В данном случае все три сущности Article, Topic и Comment для комментариев превращаются в одну — Commentable (комментируемое). В таблице comments помимо поля commentsble_id должно также присутствовать поле commentable_type, которое хранит тип комментируемой сущности, соответственно Article, Topic или Comment.

 

Счетчики

Чтобы сократить число запросов рекомендуется использовать counter_cache. Рассмотрим пример, когда вам необходимо показать число комментариев к статье.


class Article < ActiveRecord::Base
  has_many :comments, dependent: :destroy
end

class Comment < ActiveRecord::Base
  belongs_to :article, counter_cache: true
end

У таблицы articles при этом должно присутствовать поле comments_count, для которого значение по умолчанию установлено в 0. Значение хранимое в этом поле будет приращиваться или убывать соответственно при создании или удалении комментария.

Теперь в представлениях статей мы можем использовать что-то вроде следующего slim-кода:

- if article.comments_count > 0
  = render article.comments
- else
  Нет комментариев

Удачи в освоении Ruby и Rails!

Tags: , , ,

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.