Предполагая, что вы хотите, чтобы у многих пользователей был один и тот же значок, вам нужна ассоциация «многие ко многим» между значком и пользователем.Пользователь может иметь много значков, а значок может иметь много пользователей.Для этого требуется таблица соединений для хранения того, у какого пользователя какие значки.
create_table :badges_users do |t|
t.belongs_to :user, index: true
t.belongs_to :badge, index: true
end
Поскольку это всего лишь список, модель для этой таблицы не требуется.Используйте has_and_belongs_to_many
.
class Badge < ApplicationRecord
has_and_belongs_to_many :users
end
class User < ApplicationRecord
has_and_belongs_to_many :badges
end
Добавить значок пользователю так же просто, как нажать на массив.
user.badges << badge
Или наоборот.
badge.users << user
Они делают то же самое, добавляют строку к badges_users
со значком и идентификаторами пользователя.
Подробнее об использовании этих коллекций см. Здесь .
Вместо того, чтобы хранить баллы Пользователя в Пользователе, рассчитайте их по их значкам.
def total_points
badges.sum(:points)
end
Если вам необходимо отслеживать, собрал ли пользователь значок или ещенет, вам нужно будет сохранить это в таблице соединений и использовать модель для получения этой информации.
create_table :badge_users do |t|
t.belongs_to :user, index: true
t.belongs_to :badges, index: true
t.boolean :collected, default: false
end
class BadgeUser < ApplicationRecord
belongs_to :user
belongs_to :badges
end
А затем используйте has_many
и has_many :through
для настройкиассоциации.
class User < ApplicationRecord
has_many :badge_users
has_many :badges, through: :badge_users
end
class Badge < ApplicationRecord
has_many :badge_users
has_many :users, through: :badge_users
end
Добавление значка для пользователя такое же, как и раньше, user.badges << badge
.
Затем мы разрешаем пользователям собирать значки.
# In BadgeUser
def collect
if collected
raise "Badge already collected"
end
update!(collected: true)
end
# In User
def collect_badge(badge)
badge_users.find_by( badge: badge ).collect
end
И пользователи могут найти свои собранные значки.
# In User
def collected_badges
badges.merge(BadgeUser.where(collected: true))
end
Как только пользователь может найти свои собранные значки, они могут суммировать свои очки, чтобы узнать, сколько очков они использовали.
# In User
def used_points
collected_badges.sum(:points)
end