views: convert 'ip' (bigint) -> 'ip_address' (inet)

This fixes all known issues when connecting to discourse over IPv6.

This table has no primary key, so the migration is done with update_all,
for each ip address in the views table. Since this table can potentially
grow quite large, this process might take a long time. I don't know any
way around this, though.

This migration uses a SQL command to populate the new field from the old
one, so as not to rely on the View model class, which should keep the
migration from failing if that class is modified in the future.
This commit is contained in:
Dan Johnson 2013-06-25 00:18:54 -04:00
parent 2e478d8537
commit 9f6b7889a8
3 changed files with 26 additions and 4 deletions

View File

@ -3,7 +3,7 @@ require 'ipaddr'
class View < ActiveRecord::Base
belongs_to :parent, polymorphic: true
belongs_to :user
validates_presence_of :parent_type, :parent_id, :ip, :viewed_at
validates_presence_of :parent_type, :parent_id, :ip_address, :viewed_at
# TODO: This could happen asyncronously
def self.create_for(parent, ip, user=nil)
@ -20,7 +20,7 @@ class View < ActiveRecord::Base
$redis.expire(redis_key, 1.day.to_i)
View.transaction do
View.create(parent: parent, ip: IPAddr.new(ip).to_i, viewed_at: Date.today, user: user)
View.create(parent: parent, ip_address: ip, viewed_at: Date.today, user: user)
# Update the views count in the parent, if it exists.
if parent.respond_to?(:views)
@ -37,9 +37,9 @@ end
#
# parent_id :integer not null
# parent_type :string(50) not null
# ip :integer not null
# viewed_at :date not null
# user_id :integer
# ip_address :string not null
#
# Indexes
#

View File

@ -0,0 +1,22 @@
require 'ipaddr'
class ChangeIpToInetInViews < ActiveRecord::Migration
def up
table = :views
add_column table, :ip_address, :inet
execute "UPDATE views SET ip_address = inet(
(ip >> 24 & 255) || '.' ||
(ip >> 16 & 255) || '.' ||
(ip >> 8 & 255) || '.' ||
(ip >> 0 & 255)
);"
change_column table, :ip_address, :inet, { :null => false }
remove_column table, :ip
end
def down
raise ActiveRecord::IrreversibleMigration
end
end

View File

@ -6,7 +6,7 @@ describe View do
it { should belong_to :user }
it { should validate_presence_of :parent_type }
it { should validate_presence_of :parent_id }
it { should validate_presence_of :ip }
it { should validate_presence_of :ip_address }
it { should validate_presence_of :viewed_at }