假设您希望多个用户拥有相同的徽章,您需要在徽章和用户之间建立多对多关联。一个用户可以有很多徽章,一个徽章可以有很多用户。这需要一个连接表来存储哪个用户拥有哪些徽章。
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 中添加一行带有徽章和用户 ID。
See here for more about how to use these collections.
不是将用户的积分存储在用户中,而是从他们的徽章中计算出来。
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 and 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