尝试将现有 IPS 转换为整数
Trying to convert existing IPS to integers
我有一个 users
table 包含一堆字符串格式的 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
此代码工作正常,当新用户注册时,his/her IP 将存储为整数。现在我需要创建一个迁移,将 IP 列的类型从字符串更改为整数:
class ConvertStringIpsToIntegers < ActiveRecord::Migration
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
结束
但是,此迁移将破坏旧的 IPS,这些旧 IPS 存储为字符串“127.0.0.1”,迁移后将变为 127。
知道如何在 运行 迁移之前将所有现有 IPS 从字符串转换为整数吗?
谢谢
您可以在迁移中包含您的转化代码。在单独的转换中执行从字符串到整数的实际转换。
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
我有一个 users
table 包含一堆字符串格式的 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
此代码工作正常,当新用户注册时,his/her IP 将存储为整数。现在我需要创建一个迁移,将 IP 列的类型从字符串更改为整数:
class ConvertStringIpsToIntegers < ActiveRecord::Migration
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
结束
但是,此迁移将破坏旧的 IPS,这些旧 IPS 存储为字符串“127.0.0.1”,迁移后将变为 127。 知道如何在 运行 迁移之前将所有现有 IPS 从字符串转换为整数吗?
谢谢
您可以在迁移中包含您的转化代码。在单独的转换中执行从字符串到整数的实际转换。
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