Правильный дизайн: пост может иметь одного пользователя (автора) плюс много пользователей (помеченных пользователей)

У меня есть ситуация, когда я немного застрял.

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

В моей модели Post:

belongs_to :user
has_and_belongs_to_many :users

В моей модели пользователя:

has_and_belongs_to_many :posts

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

Каким должен быть правильный дизайн? Возможно, заменить user_id в Post на author_id?


person Daniel    schedule 05.10.2011    source источник
comment
У вас есть таблица базы данных, в которой вы храните данные для отношений «многие ко многим»?   -  person Sergey Kishenin    schedule 05.10.2011


Ответы (1)


Я могу себе представить, что User и Users испортят ваши присоединения. Но имейте в виду, насколько я знаю, это то, что рельсы не решают хорошо. Просто переименовать его в author (при этом улучшив читаемость/выразив намерение лучше) не поможет, так как он по-прежнему будет указывать на ту же таблицу users.

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

Поэтому я думаю, что вам придется либо прибегнуть к созданному вручную sql (что будет быстро), либо использовать рельсы и сначала отсортировать сообщения по имени автора, а затем получить список отмеченных пользователей на секунду сообщения (что будет медленнее , но чистый рубин).

Сначала я бы выбрал второй вариант и оптимизировал его до первого, если это необходимо.

[ОБНОВЛЕНИЕ: добавьте определение области действия]

Лично я не одобряю default_scope и вместо этого предлагаю определить явную область действия

scope :with_authors_sorted, lambda { 
  Post.includes(:type).includes(:user).
       order('year DESC, week DESC, users.display_name ASC, posts.created_at DESC') 
}

который вы можете просто использовать в своем контроллере.

@posts = Post.with_authors_sorted

Надеюсь это поможет.

person nathanvda    schedule 05.10.2011
comment
Да я согласен. Я предпочитаю чистоту этого подхода. Знаете ли вы, как должна выглядеть моя область действия по умолчанию, если я хочу, чтобы сообщения сортировались по отображаемому_имени пользователя? это уместно default_scope includes(:type) / default_scope includes(:user) / default_scope order('year DESC, week DESC, users.display_name ASC, posts.created_at DESC') - person Daniel; 05.10.2011