ruby Rails向下迁移以减小字符串值大小

k10s72fa  于 2022-12-29  发布在  Ruby
关注(0)|答案(1)|浏览(101)

我正在做一个任务,我需要增加字符串字段的大小限制。我已经写了下面的迁移。

class IncreaseCompanyNumberLimit < ActiveRecord::Migration[6.1]
  def up
    if Company.columns.find { |c| c.name == 'company_number' }.limit < 25
      change_column :company, :company_number, :string, :limit => 25
    end  
  end

  def down
    change_column :company, :company_number, :string, :limit => 20
  end
end

我遇到的问题是,如果有人在迁移过程中运行up方法后输入了company_number,如果新的company_number大于我尝试使用down方法设置的20限制,那么当我运行down方法时,它会崩溃,因为现有数据太长。
有没有一种有效的方法可以将大于down方法所设定的限制的内容进行删减?这是一个很大的表,所以我试图找到一种有效的方法来实现这一点,而google并没有提供多少帮助。
提前感谢您的帮助!

cwtwac6a

cwtwac6a1#

作为迁移的一部分,您需要运行trim值。您可以使用数据库自己的字符串处理函数来执行此操作,这比Ruby中检索值和trim要高效得多。每个数据库的这些函数都不同。我将在本示例中使用PostgreSQL's string functions。您应该能够将其适用于任何数据库。
批量执行此操作以避免在表运行时锁定整个表。

class IncreaseCompanyNumberLimit < ActiveRecord::Migration[6.1]
  NEW_LIMIT = 25
  OLD_LIMIT = 20

  def up
    change_column :company, :company_number, :string, limit: NEW_LIMIT
  end

  def down
    Company.in_batches.update_all("company_number = left(company_number, OLD_LIMIT)")
    change_column :company, :company_number, :string, :limit => OLD_LIMIT
  end
end

传统的SQL模式管理要求在模式中使用约束和限制来确保数据一致。Rails不同。模型和数据库是不可分割的。对于像这样的ORM管理模式,我建议 * 不要将业务逻辑放在您的模式中 *。任意的字段限制是最大的违规者。正如您正在学习的,因为本周的限制是25,下周的限制是20,所以必须进行模式更新,这是对程序员时间的低效使用。

class RemoveCompanyNumberLimit < ActiveRecord::Migration[6.1]
  NEW_LIMIT = nil
  OLD_LIMIT = 20

  def up
    change_column :company, :company_number, :string, limit: NEW_LIMIT
  end

  def down
    Company.in_batches.update_all("company_number = left(company_number, OLD_LIMIT)")
    change_column :company, :company_number, :string, :limit => OLD_LIMIT
  end
end

相反,在Company模型中使用validation强制执行此操作,这样更灵活,并且会提供信息性错误消息。

class Company
  validates :company_number, length: { maximum: 25 }
end

然后,控制器可以使用验证错误通知用户出了什么问题。

相关问题