如何使用 has_and_belongs_to_many 播种数据库

How to seed database with has_and_belongs_to_many

我在两个模型(PhoneCategory)之间有 has_and_belongs_to_many 关系,并且我在电话和类别表中添加了类似于此的内容:

Phone.create(name:'Home', phone:'+00 0 00 00 00 00')
Phone.create(name:'Work', phone:'+00 1 00 00 00 00')
Category.create(name:'tactile-screen')
Category.create(name:'mobile')
Category.create(name:'landline')

这是我的schema.rb

create_table "categories", force: :cascade do |t|
  t.string "name"
end

create_table "categories_phones", id: false, force: :cascade do |t|
  t.integer "category_id"
  t.integer "phones_id"
end

create_table "phones", force: :cascade do |t|
  t.string "name"
  t.string "phone"
end

这些是我的模型:

class Category < ApplicationRecord
    has_and_belongs_to_many :phones
end
class Phone < ApplicationRecord
    has_and_belongs_to_many :categories
end

我想为每部手机设置所属类别,我该怎么做?

您需要像这样将新创建的记录分配给实例变量:

# db/seeds.rb

phone_1 = Phone.create(name:'Home', phone:'+00 0 00 00 00 00')
phone_2 = Phone.create(name:'Work', phone:'+00 1 00 00 00 00')

category_1 = Category.create(name:'tactile-screen')
category_2 = Category.create(name:'mobile')
category_3 = Category.create(name:'landline')

...

假设您要将每个 phone 分配给每个类别,您可以让 Rails 像这样为您完成工作:

...

[category_1, category_2, category_3].each do |category|
  category.phones << [phone_1, phone_2]
end

如果您想将每个 Phone 实例与所有类别相关联,您可以这样做:

Category.create(name:'tactile-screen')
Category.create(name:'mobile')
Category.create(name:'landline')

ids = Category.all.ids

Phone.create(name:'Home', phone:'+00 0 00 00 00 00', category_ids: ids)
Phone.create(name:'Work', phone:'+00 1 00 00 00 00', category_ids: ids)

否则只需创建记录数组,如果您想应用随机类别,您可以执行类似以下操作:

categories = ['tactile-screen', 'mobile', 'landline'].map do |c|
  Category.create(name: c)
end

phones = [
  Phone.create(name:'Home', phone:'+00 0 00 00 00 00'),
  Phone.create(name:'Work', phone:'+00 1 00 00 00 00')
]

phones.each do |p|
  p.categories << categories.sample
end

如果您使用的是 Faker 或 FFaker,您可以使用这个绝妙的技巧来生成随机记录:

require 'ffaker'

# generate a 100 random numbers
phones = 100.times.map do 
  Phone.create(name:'Home', FFaker::PhoneNumber.phone_number)
end

# generate between 0 and 100 random numbers
phones = ((rand * 100).floor).times.map do
  Phone.create(name:'Home', FFaker::PhoneNumber.phone_number)
end