2014-10-19 4 views
0

Итак, подумав об этом некоторое время, я понятия не имею, как правильно это моделировать.Моделирование подписки в Rails

У меня есть сайт, посвященный обмену изображениями. Чтобы сделать пользователей счастливыми, я хочу, чтобы они могли подписаться на множество разных коллекций изображений.

До сих пор существует два типа коллекций. Один из них - это «создатель», который определяет людей, которые работали над определенным образом. Это выглядит следующим образом:

class Image < ActiveRecord::Base 
    has_many :creations 
    has_and_belongs_to_many :locations 
    has_many :creators, through: :creations 
end 

class Creator < ActiveRecord::Base 
    has_many :images, ->{uniq}, through: :creations 
    has_many :creations 
    belongs_to :user 
end 


class Creation < ActiveRecord::Base 
    belongs_to :image 
    belongs_to :creator 
end 

Пользователи также могут пометить изображение с субъективным тегом, который является то, что объективно не присутствует в изображении. Типичные субъективные теги будут включать в себя «смешные» или «грустные» вещи. Вот реализована следующим образом:

class SubjectiveTag < ActiveRecord::Base 
    # Has a "name" field. The reason why the names of tags are a first-class DB model 
    # is so we can display how many times a given image has been tagged with a specific tag 
end 

class SubjectiveCollection < ActiveRecord::Base 
    # Basically, "User X tagged image Y with tag Z" 
    belongs_to :subjective_tag 
    belongs_to :user 
    has_many :images, through: :subjective_collection_member 
end 

class SubjectiveCollectionMember < ActiveRecord::Base 
    belongs_to :subjective_collection 
    belongs_to :image 
end 

Я хочу, чтобы пользователи могли подписаться на обоих творцов и SubjectiveTags, и отображать все изображения в этих коллекциях, последовательно, на домашней странице, когда они войти

. Каков наилучший способ сделать это? Должен ли я иметь кучу разных типов подписки - например, один из них - SubjectiveTagSubscription и один - CreatorSubscription? Если я поеду по этому маршруту, то какой самый эффективный способ получить все изображения в каждой коллекции?

ответ

1

Что вы хотите использовать, это Polymorphic Association.

В вашем случае, это будет выглядеть следующим образом:

class Subscription < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :subscribeable, polymorphic: true 
end 

В таблице subscriptions необходимо будет включать в себя следующие поля:

  • user_id (целое число)
  • subscribeable_id (целое число)
  • subscribeable_type (строка)

Эта настройка позволит подписке ссылаться на экземпляр любой другой модели, так как ActiveRecord будет использовать поле subscribeable_type для записи имени класса на подписке.

Для получения списка изображений для текущего зарегистрированного пользователя, вы можете сделать это:

Subscription.where(user_id: current_user.id).map do |subscription| 
    subscription.subscribeable.images.all 
end.flatten 

Если влияние на производительность вышеуказанного подхода являются недопустимыми (один запрос на подписку), вы можете свернуть ваш два типа подписчиков в одну таблицу через STI (что здесь не кажется хорошей идеей, поскольку эти две таблицы не очень похожи), или вы можете вернуться к первоначальному предложению о наличии двух разных типов моделей подписки/таблицы, запрашивая каждый отдельно для подписки.

+1

Другие модели нуждаются в 'has_many: подписках, как:: subscribeable'. – Substantial

+0

Я уже пробовал это. Попытка найти образы подписки сообщает мне, что ActiveRecord не поддерживает полиморфные has_many: через отношения. – TheSuper

+0

Правильно - вы не можете 'have_many_through' полиморфную ассоциацию, потому что вы не можете получить результаты в одном запросе.В случае, когда вы указали (отображая изображения из подписки на домашней странице пользователя), вам нужно будет перебирать подписки пользователя (это один запрос), а затем извлекать изображения для каждой подписки (по одному запросу для каждой подписки). –