【问题标题】:Trying to convert existing IPS to integers尝试将现有 IPS 转换为整数
【发布时间】:2015-03-21 22:03:59
【问题描述】:

我有一个 users 表,其中包含一堆字符串格式的 IPS,现在我们决定开始将 IPS 存储为整数,所以我将这段代码添加到我的 user.rb 模型中:

class User < ActiveRecord::Base
  [:current_sign_in_ip, :last_sign_in_ip].each do |field|
    define_method(field) do
      ip = read_attribute(field)
      return nil unless ip
      ip += 4_294_967_296 if ip < 0 # Convert from 2's complement
      "#{(ip & 0xFF000000) >> 24}.#{(ip & 0x00FF0000) >> 16}.#{(ip & 0x0000FF00) >> 8}.#{ip & 0x000000FF}"
    end

    define_method("#{field}=") do |value|
      quads = value.split('.')
      if quads.length == 4
        as_int = (quads[0].to_i * (2**24)) + (quads[1].to_i * (2**16)) + (quads[2].to_i * (2**8)) + quads[3].to_i
        as_int -= 4_294_967_296 if as_int > 2147483647 # Convert to 2's complement
      else
        as_int = nil
      end
      write_attribute(field, as_int)
    end

  end
end

此代码工作正常,当新用户注册时,他/她的 IP 将存储为整数。现在我需要创建一个迁移,将 IP 列的类型从字符串更改为整数:

类 ConvertStringIpsToIntegers

def up

  change_column :users, :current_sign_in_ip, :integer
  change_column :users, :last_sign_in_ip,    :integer
end

def down
  change_column :users, :current_sign_in_ip, :string
  change_column :users, :last_sign_in_ip,    :string
end

结束

但是,此迁移将破坏存储为字符串“127.0.0.1”的旧 IPS,迁移后将变为 127。 知道如何在运行迁移之前将所有现有的 IPS 从字符串转换为整数吗?

谢谢

【问题讨论】:

  • 这里已经回答了我相信stackoverflow.com/questions/13244792/… 编辑:好的,我还不能发表评论。您可以先将字段迁移为字符串。将 IP 转换为数字,然后从字符串字段进行第二次迁移到数字
  • 不,抱歉,我的问题不同。我知道如何转换我只是不知道把代码放在哪里。
  • @webmastersupport.com 如果我迁移到字符串,IPS 将丢失。

标签: ruby-on-rails database-migration


【解决方案1】:

您可以在迁移中包含您的转化代码。在单独的转换中执行从字符串到整数的实际转换。

def up
  User.all.each do
    [:current_sign_in_ip, :last_sign_in_ip].each do |field|
      quads = user.read_attribute(field).split('.')
      if quads.length == 4
        as_int = (quads[0].to_i * (2**24)) + (quads[1].to_i * (2**16)) + (quads[2].to_i * (2**8)) + quads[3].to_i
        as_int -= 4_294_967_296 if as_int > 2147483647 # Convert to 2's complement
      else
        as_int = nil
      end
      user.write_attribute(field, "#{as_int}")
    end
  end
end

def down
  User.all.each do |user|
    [:current_sign_in_ip, :last_sign_in_ip].each do |field|
      ip = user.read_attribute(field).to_i
      return nil unless ip
      ip += 4_294_967_296 if ip < 0 # Convert from 2's complement
      user.write_attribute(field, "#{(ip & 0xFF000000) >> 24}.#{(ip & 0x00FF0000) >> 16}.#{(ip & 0x0000FF00) >> 8}.#{ip & 0x000000FF}")
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 2017-02-25
    • 2013-02-28
    • 2020-02-12
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多