【问题标题】:Reset DB from Controller/Helper, Ruby on Rails从控制器/助手重置数据库,Ruby on Rails
【发布时间】:2017-01-13 23:51:08
【问题描述】:

我已经创建了我的程序的演示。该演示用于向客户展示该程序。在每次演示之前我想重置数据库并插入某些数据,我必须做的操作是:

rake db:drop
rake db:setup
rake db:seed:demo

但他们并不总是我来展示它,其他人也不使用控制台,所以我想在设置页面中添加通过按钮重置的功能。

我是这样尝试的:

module SettingsHelper
require 'rake'
  def reset
        Rake::Task[db:drop].invoke
        Rake::Task[db:setup].invoke
        Rake::Task[db:seeds:demo].invoke
  end
end

我输入了表格:

  <%=button_to "Reset", reset, class:"btn red" %>

但是我不能用活动服务器删除数据库......我该怎么办?

【问题讨论】:

  • 如果您有活动连接,则无法删除数据库。您可以做的是您可以销毁所有记录并创建新记录
  • 好的,如何调用种子来创建记录?
  • Rails.application.load_seed

标签: ruby-on-rails ruby postgresql ruby-on-rails-4


【解决方案1】:

当您的连接处于活动状态时,您不能删除数据库。相反,您可以做的是发出 TRUNCATE 命令,从表中删除所有行并重置 ID 列。

如果您想要更精细地控制哪些表被截断,您可以向模型添加一个类方法:

class User < ActiveRecord::Base
  self.truncate!
    self.connection.execute(
      "TRUNCATE TABLE #{ self.table_name };"
    )
    self.connection.reset_pk_sequence!(self.table_name)
  end
end 

但是让 DRY 到一个模块中,这样我们就不必在所有应该有这种行为的模型中重复它:

# app/models/concerns/resetable.rb
module Resetable
  extend ActiveSupport::Concern
  class_methods do
    def truncate!
      self.connection.execute(
        "TRUNCATE TABLE #{ self.table_name };"
      )
      self.connection.reset_pk_sequence!(self.table_name)
    end
  end
end

# app/models/user.rb
class User < ActiveRecord::Base
  include Resetable
  # ...
end 

 # app/models/book.rb
class Book < ActiveRecord::Base
  include Resetable
  # ...
end 
# ...

然后您可以通过以下方式重置每个模型的数据:

def reset_db
  [User, Book, Thing].each { |model| model.truncate! }
  Rails.application.load_seed
end

如果您只想对所有表格进行核对,您可以简单地执行以下操作:

ActiveRecord::Base.connection.tables.each do |t|
  conn = ActiveRecord::Base.connection
  conn.execute("TRUNCATE TABLE #{t} CASCADE;")
  conn.reset_pk_sequence!(t)
end

【讨论】:

  • TRUNCATE ... CASCADE 是 Postgres 特有的截断表的方法,即使存在外键约束也是如此。
  • 我在控制器中包含'Resetable'并将函数放在'helper'中,我有这个错误:`未定义的方法truncate!' for #&lt;Class:0x00559615887830&gt;和变量模型是学生,我通过的第一个模型
  • 模块和助手不是一回事。上面是一个模块,它混入模型类来扩展它。控制器中混入了你不想要的助手。
  • 您应该在 Student 类中包含 Resetable。请按照答案中的示例进行操作。
【解决方案2】:

我从以下 SO 答案中提取了一些代码

你可以在控制器中添加这样的东西

def reset_db
  conn = ActiveRecord::Base.connection
  tables = ActiveRecord::Base.connection.tables
  tables.each { |t| conn.execute("TRUNCATE #{t}") }

  Rails.application.load_seed
end

【讨论】:

  • 谢谢这是个好主意,但是我有一个问题,因为我使用的是Postgresql并且id并不总是从1开始,否则种子中的关系不起作用......我怎么能设置第一个 id 1?我认为这是一个名为“序列”的函数
  • 我试过这个功能,但它给了我这个错误:PG::UndefinedObject: ERROR: unrecognized configuration parameter "tables" : show tables
  • 在 postgres 中是 SELECT tablename FROM pg_tables,但您最好使用适配器提供的更高级别的 ActiveRecord::Base.connection.tables
  • @Deepak 是否正确?因为我收到此错误 undefined local variable or method conn' 对于 #:0x00559613c67c40>`
  • 已编辑,需要连接
猜你喜欢
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多