ruby-on-rails rails迁移使用up/down添加和更新现有记录

brvekthn  于 2023-02-26  发布在  Ruby
关注(0)|答案(5)|浏览(168)

我必须向现有表中添加2个新列,它们是created_atupdated_at。但是,created_atupdated_at字段不应为空,除非我的数据库中存在多个现有记录,因此简单的change迁移不起作用。向下迁移,因为我需要在将这些字段设置为not null之前先更新这些记录。
我的迁移文件如下所示:

Class AddColumnsToCharge < ActiveRecord::Migration[6.0]
   def up
     add_column :charges, :created_at, :datetime
     add_column :charges, :updated_at, :datetime
     Charge.update_all(created_at: Time.now, updated_at: Time.now)
   end

  def down
     change_column :charges, :created_at, :datetime, null:false
     change_column :charges, :updated_at, :datetime, null:false
  end
end

现在看来,这似乎起作用了,因为我不再收到错误消息,抱怨现有列中的created_at/updated_at字段为空值。

create_table "charges", force: :cascade do |t|
  t.bigint 'amount'
  t.datetime 'created_at'
  t.datetime 'updated_at'

我期待看到的是

create_table "charges", force: :cascade do |t|
      t.bigint 'amount'
      t.datetime 'created_at', null: false
      t.datetime 'updated_at', null: false

是我的down没有被执行还是我在我的迁移文件中做错了什么?(感谢任何帮助提前)

yjghlzjz

yjghlzjz1#

down在运行rails db:rollback时使用,这是您尝试执行的操作吗?
up是在运行rails db:migrate时使用的,通常Rails知道要做什么,所以在迁移中使用change就足够了,但有时你需要使用up/down,这样迁移才是可逆的。
从文件上看
您还可以使用up和down方法而不是change方法来使用旧式迁移。up方法应该描述您要对架构进行的转换,而迁移的down方法应该还原up方法所做的转换。换句话说,如果您先执行up,然后执行down,则数据库架构应该保持不变。例如,如果你用up方法创建了一个表,你应该用down方法把它放下。

wsxa1bj1

wsxa1bj12#

你需要这个:

class AddTimestamps < ActiveRecord::Migration[6.1]
  def change
    reversible do |dir|
      change_table :charges do |t|
        dir.up do
          t.timestamps
          Charge.update_all(created_at: Time.now, updated_at: Time.now)
        end
        dir.down do
          remove_column :charges, :created_at
          remove_column :charges, :updated_at
        end
      end
    end
  end
end

created_atupdated_at的默认值不反映在架构B/c中,它始终由ActiveRecord填充,它们没有数据库配置的默认值。分配的值是动态的,您只能在架构中放置固定的默认值。
当您使用timestamps方法指定created_at时,null: false会自动添加(Rails 5以上)。当您显式创建/删除created_at/updated_at列时,不会自动添加该选项。

gupuwyp2

gupuwyp23#

我觉得你在找这样的东西。

add_column :charges, :created_at, :datetime
 add_column :charges, :updated_at, :datetime
 change_column_null(:charges, :created_at, false, Time.now)
 change_column_null(:charges, :updated_at, false, Time.now)

checkout 此更改列空值

mbskvtky

mbskvtky4#

下面是使用updown的一个很好的示例(来自Rails迁移指南:

class ChangeProductsPrice < ActiveRecord::Migration[7.0]
  def up
    change_table :products do |t|
      t.change :price, :string
    end
  end

  def down
    change_table :products do |t|
      t.change :price, :integer
    end
  end
end
ldfqzlk8

ldfqzlk85#

我能够通过运行两个不同的迁移来解决我的问题。
我的第一次迁移添加了新列:

Class AddColumnsToCharge < ActiveRecord::Migration[6.0]
   def change
     add_column :charges, :created_at, :datetime
     add_column :charges, :updated_at, :datetime
   end
end

在运行第二次迁移之前,我进入rails控制台并更新了当前记录:Charge.update_all(created_at: Time.now, updated_at: Time.now)
第二次迁移:

Class AddColumnsToCharge < ActiveRecord::Migration[6.0]
  def change
     change_column :charges, :created_at, :datetime, null:false
     change_column :charges, :updated_at, :datetime, null:false
  end
end

这个答案并没有回答最初的问题,但完成了工作,这最终是我想要的。

相关问题