Skip to content

Instantly share code, notes, and snippets.

@koraktor
Created April 15, 2009 13:49
Show Gist options
  • Save koraktor/95773 to your computer and use it in GitHub Desktop.
Save koraktor/95773 to your computer and use it in GitHub Desktop.
ActiveRecord: Saving IPs as 32bit signed integers
require 'IPAddr'
module ActiveRecord
module Validations
module ClassMethods
def converts_addresses(*attributes)
attributes.each do |attribute|
attr_accessor "#{attribute}_addr".to_sym
define_method("#{attribute}_addr".to_sym) do
attribute_value = read_attribute(attribute)
if attribute_value.nil?
return nil
end
return IPAddr.new(attribute_value + 2**31, Socket::AF_INET)
end
define_method("#{attribute}_addr=".to_sym) do |addr|
begin
write_attribute(attribute, IPAddr.new(addr, Socket::AF_INET).to_i - 2**31)
rescue ArgumentError
write_attribute(attribute, nil)
end
end
end
end
end
end
end
require 'converts_addresses'
class Host < ActiveRecord::Base
belongs_to :subnet
converts_addresses :ip
validates_presence_of :ip
validates_uniqueness_of :ip
def validate
Subnet.all.each do |subnet|
if (self.ip + 2**31) & (subnet.mask + 2**31) == (subnet.network + 2**31)
self.subnet = subnet
end
end
errors.add_to_base 'There's no subnet for this IP.' if @subnet.nil?
end
end
require 'converts_addresses'
class Subnet < ActiveRecord::Base
has_many :hosts
converts_addresses :network, :mask
validates_presence_of :name
validates_numericality_of :network,
:only_integer => true,
:greater_than_or_equal_to => -2**31,
:less_than => 2**31
validates_numericality_of :mask,
:only_integer => true,
:greater_than_or_equal_to => -2**31,
:less_than => 2**31
validates_uniqueness_of :name
validates_uniqueness_of :network, :scope => :mask
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment