我有一个包含以下列的清单表: -
id | product_id | content | archived
用户注册后,会创建产品表并创建相应的清单表。
我希望在他/她注册后为每个用户添加默认的5个条目以及清单表的数据。有什么帮助吗?
答案 0 :(得分:2)
我会用service object解决这个问题。
# app/services/default_checklist_service.rb
class DefaultChecklistService
attr_accessor :user, :defaults
def initialize(user, defaults = nil)
@user = user
@defaults = defaults || self.class.load_defaults
end
def self.call(user, defaults = nil)
new(user, defaults).call
end
def call
self.defaults.map do |attributes|
user.checklists.create(attributes)
end
end
private
def self.load_defaults
YAML.load_file(Rails.root.join('config', 'default_checklist.yml'))
.try(:[], 'checklists')
end
end
这创建了一个易于测试的单一目的对象。 VS模型回调,它为已经上帝的模型增加了更多的责任,并且在测试和控制它们发射的时间和地点都很棘手。
# config/default_checklists.yml
checklists:
-
foo: 1
bar: 2
-
foo: 2
bar: 3
请注意,这将创建 n (其中 n 是默认项目的数量)单独的插入查询,这不是非常快。如果性能成为问题,则可以使用大量插入:
# app/services/default_checklist_service.rb
class DefaultChecklistService
# ...
def call
sql = "INSERT INTO users(user_id, foo, bar) VALUES "
values = defaults.map do |a|
"(#{@user.id}, #{a["foo"]}, #{a["bar"]})"
end
ActiveRecord::Base.connection.execute( sql + values.join(', ') )
end
end
由于创建默认值很昂贵并且会降低测试速度,因此我不会使用模型回调。而是从您希望播种的控制器调用服务:
class UsersController
def create
@user = User.create(user_params)
if @user.save
DefaultChecklistService.call(@user)
# ...
else
# ...
end
end
end
答案 1 :(得分:1)
创建回调后使用:
User < ActiveRecord::Base
has_many :check_lists
after_create :add_default_checklist
def add_default_checklist
default_check_lists.each do |check_list_data| # Define way to get default values
check_lists.create(check_list_data)
end
end
end
您需要将user_id
列添加到核对清单