Я разрабатываю API в Rails, в котором существуют таблицы users
и messages
.Также users
имеют пол (gender_id
), принадлежат к стране (country_id
), а также имеют гражданский статус (civil_status_id
), а messages
создаются admins
.
Итак, до сих пор у меня есть эта модель.
![enter image description here](https://i.stack.imgur.com/JxFtk.jpg)
Теперь мне нужно разработать следующее требование
Администратор должен иметь возможность создавать сообщение с адресом users
в зависимости от его атрибутов (страна, пол или гражданский статус).Кроме того, администратор должен иметь возможность объявлять сообщение как глобальное сообщение, в этом случае «all» users
должно его получать, но исключения также должны быть разрешены.Например, в случае, когда администратор хочет отправить сообщение пользователям из всех стран, кроме людей из России и Китая.
Дело в том, что я не являюсь экспертом по Rails / SQL, но яЯ хочу сделать это эффективно, чтобы, если завтра у приложения будет десять тысяч или сто тысяч пользователей, сервер быстро откликнется.
Поэтому я подумал о следующем
Первое создание3 отношения «многие ко многим» (countries_messages
, genders_messages
и civil_statuses_messages
).Записи этих таблиц представляют отношения между messages
и countries
, civil_statuses
и genders
.
Затем создайте форму, где администратор может создать сообщение, где с помощью несколькихвыбирая поля, он должен иметь возможность выбирать атрибуты пользователей, с которыми он хочет связаться.Форма для создания сообщения также должна иметь флажок, чтобы определить, является ли сообщение глобальным, если оно помечено, я бы посчитал, что выбранные страны, полы и гражданские статусы будут категориями, которые администратор хочет исключить, т. Е. Если администраторЧтобы отправить сообщение всем людям в системе, кроме людей из Канады, он должен отметить глобальную опцию и выбрать страну Канада в поле выбора (очевидно, это будет указано в представлении).
Теперь у меня есть эта модель.
![enter image description here](https://i.stack.imgur.com/bwZlM.jpg)
В чем я сомневаюсь, так это в том, какой способ более эффективен для возврата сообщений, соответствующихпользователь.
Метод 1
Когда администратор указывает, что сообщение является глобальным, за исключением сообщений из страны с идентификатором 3, тогда я могу добавить к countries_messages
записи типа (country_id: 1,message_id: 2), (country_id: 2, message_id: 2), (country_id: 4, message_id: 2), ... и т. д., т. е. формирование отношения с каждой страной, кромеept the country with id 2.
Затем повторите сообщения, которые должен прочитать текущий пользователь, следующим образом:
global_messages = Message.where(global: true).ids
country_messages = current_user.country.messages.ids
gender_messages = current_user.gender.messages.ids
civil_status_messages = current_user.current_status.messages.ids
@messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages)
Метод 2
Другим способом может быть формированиесвязь этого сообщения с исключенной страной, т.е. если я делаю сообщение исключительно для людей из страны с идентификатором 2, тогда я должен добавить запись (country_id: 2, message_id: 2) в countries_messages
, но в противном случае, если яотправил сообщение в каждую страну, кроме страны с идентификатором 2, тогда я должен также добавить запись (country_id: 2, message_id: 2) в countries_messages
.
В этом случае я могу знать, исключено ли сообщениенапример, для мужчин и людей из Аргентины, если сообщение является глобальным И оно связано со страновой и гендерной записью, представляющей Аргентину и мужчин.
Тогда повторная проверка сообщений, которые должен прочитать текущий пользователь, будеткак это:
global_messages = Message.where(global: true).ids
country_messages = current_user.country.messages
gender_messages = current_user.gender.messages
civil_status_messages = current_user.current_status.messages
excluded_country_messages_ids = country_messages.where(global: true).ids
excluded_gender_messages_ids = gender_messages.where(global: true).ids
excluded_civil_status_messages_ids = civil_status_messages.where(global: true).ids
@messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages - excluded_country_messages_ids - excluded_gender_messages_ids - excluded_civil_status_messages_ids)
Могут быть и другие способы сделать то же самое, поэтому я хочу получать рекомендации или, если вы видите, что я справляюсьсделать улучшения, чтобы сделать то же самое, то скажите мне.Если есть что-то, чего вы не понимаете, спросите.