【问题标题】:Migrate from two string yes/no variable to a single boolean variable in rails?从两个字符串是/否变量迁移到rails中的单个布尔变量?
【发布时间】:2019-08-06 15:37:33
【问题描述】:

问题是关于 Rails 数据库迁移。

当前数据库包含两个条目,用于一个假定为布尔变量的数据库方案,如下所示:

create_table "table_name", force: :cascade do |t|
    ... 

    t.string "yes_boolvar"
    t.string "no_boolvar"
    ...

end

我需要将其转换为一个布尔变量,如下所示:

    t.boolean "boolvar"

我考虑过重命名“yes_boolvar”,将其类型从字符串更改为布尔值,然后根据一些读数删除“no_boolvar”列,如下所示:

 t.rename :yes_boolvar,
          :boolvar
 t.change :boolvar,
          :boolean
 t.remove :no_boolvar

但是,在复制变量的值时,这只会考虑 'yes_*' 而不是 'no_*' 的真值。有没有办法成功迁移 var,以便将两个 var 的真值(或 nil)值都考虑在内。

【问题讨论】:

    标签: ruby-on-rails database-migration ruby-on-rails-5.1


    【解决方案1】:

    这取决于您的应用。

    如果没有人可以更新这些值(即它不是用户配置文件中的字段),那么您可以:

    1. 制作数据库转储
    2. 运行迁移
    3. 执行将填充boolvar的代码

    另一种解决方案是分 3 步迁移数据:

    1. 第一次迁移重命名列
    2. 第二次迁移迁移数据
    3. 第三次迁移删除了no_boolvar

    我想可以将前两个操作合并到一个迁移中(但我更喜欢将它们分开)。

    【讨论】:

      【解决方案2】:

      我建议您处理 3 次迁移。 首先,创建一个迁移添加一个boolean: :boolvar

      class AddBoolvarToTableName < ActiveRecord::Migration
        def up
          add_column :table, :boolvar, :boolean
        end
      
        def down
          remove_column :table, :boolvar  
        end
      end
      

      之后,创建一个新的迁移来处理数据:

      class RepopulateBooleanValues < ActiveRecord::Migration[5.0]
        def change
          YourClass.all.each do |record|
            # put the logic here like:
            record.boolvar = record.yes_boolvar == 'true' 
            # or 
            record.boolvar = record.not_boolvar == 'false'
            # I'am not sure whats the content of yes_boolvar and not_boolvar, elaborate the logic here
            record.save
          end
        end
      end
      

      要完成它,只需创建一个新的迁移删除 yes_boolvarno_boolvar

      【讨论】:

        【解决方案3】:

        这大致是我写的迁移(我没有运行代码,但它应该可以工作):

        # This ensures the migration to work
        # regardless the customizations on your original model
        class TempModel < ActiveRecord::Base
          self.table_name = 'table_name'
        end
        
        class MyMigration < ActiveRecord::Migration[5.0]
          def up
            add_column :table_name, :boolvar, :boolean
        
            TempModel.reset_column_information
            TempModel.find_each do |record|
              # Decide some logic here about how to migrate values from yes_boolvar
              # and no_boolvar columns to boolvar column
              boolvar_value = record.yes_boolvar || !record.no_boolvar
              record.update_column :boolvar, boolvar_value
            end
        
             remove_column :table_name, :yes_boolvar
             remove_column :table_name, :no_boolvar
          end
        
          def down
            add_column :table_name, :yes_boolvar, :string
            add_column :table_name, :no_boolvar, :string
        
            TempModel.reset_column_information
            TempModel.find_each do |record|
              # Decide some logic here about how to handle yes_boolvar
              # and no_boolvar values
              record.update_columns yes_boolvar: record.boolvar,
                                    no_boolvar: !record.boolvar
            end
        
            remove_column :table_name, :boolvar
          end
        end
        

        【讨论】:

          猜你喜欢
          • 2020-05-28
          • 2011-11-22
          • 2014-10-29
          • 2019-07-05
          • 2021-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多