创建数据库表后,Rails将使用默认条目填充

时间:2018-04-16 11:48:54

标签: ruby-on-rails ruby postgresql

我有一个包含以下列的清单表: -

id  |  product_id  | content  |  archived 

用户注册后,会创建产品表并创建相应的清单表。

我希望在他/她注册后为每个用户添加默认的5个条目以及清单表的数据。有什么帮助吗?

2 个答案:

答案 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列添加到核对清单