From f7b8fbd4b12e07d94b2fbd23b07e8dd9c3f0e702 Mon Sep 17 00:00:00 2001 From: Dan Seaver Date: Sat, 5 May 2012 13:51:01 -0400 Subject: Adds migration and schema dump support for INET, CIDR, and MACADDR --- .../connection_adapters/postgresql_adapter.rb | 27 ++++++++++++++++++---- .../cases/adapters/postgresql/datatype_test.rb | 6 ++--- activerecord/test/cases/schema_dumper_test.rb | 21 +++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 4d5459939b..c68c08a488 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -197,6 +197,13 @@ module ActiveRecord :decimal when 'hstore' :hstore + # Network address types + when 'inet' + :inet + when 'cidr' + :cidr + when 'macaddr' + :macaddr # Character types when /^(?:character varying|bpchar)(?:\(\d+\))?$/ :string @@ -211,9 +218,6 @@ module ActiveRecord # Geometric types when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ :string - # Network address types - when /^(?:cidr|inet|macaddr)$/ - :string # Bit strings when /^bit(?: varying)?(?:\(\d+\))?$/ :string @@ -282,6 +286,18 @@ module ActiveRecord def hstore(name, options = {}) column(name, 'hstore', options) end + + def inet(name, options = {}) + column(name, 'inet', options) + end + + def cidr(name, options = {}) + column(name, 'cidr', options) + end + + def macaddr(name, options = {}) + column(name, 'macaddr', options) + end end ADAPTER_NAME = 'PostgreSQL' @@ -301,7 +317,10 @@ module ActiveRecord :boolean => { :name => "boolean" }, :xml => { :name => "xml" }, :tsvector => { :name => "tsvector" }, - :hstore => { :name => "hstore" } + :hstore => { :name => "hstore" }, + :inet => { :name => "inet" }, + :cidr => { :name => "cidr" }, + :macaddr => { :name => "macaddr" } } # Returns 'PostgreSQL' as adapter name for identification purposes. diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index ce08e4c6a7..d42f1ff5a1 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -86,9 +86,9 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end def test_data_type_of_network_address_types - assert_equal :string, @first_network_address.column_for_attribute(:cidr_address).type - assert_equal :string, @first_network_address.column_for_attribute(:inet_address).type - assert_equal :string, @first_network_address.column_for_attribute(:mac_address).type + assert_equal :cidr, @first_network_address.column_for_attribute(:cidr_address).type + assert_equal :inet, @first_network_address.column_for_attribute(:inet_address).type + assert_equal :macaddr, @first_network_address.column_for_attribute(:mac_address).type end def test_data_type_of_bit_string_types diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 15ceaa1fcc..ab80dd1d6d 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -236,6 +236,27 @@ class SchemaDumperTest < ActiveRecord::TestCase end end + def test_schema_dump_includes_inet_shorthand_definition + output = standard_dump + if %r{create_table "postgresql_network_address"} =~ output + assert_match %r{t.inet "inet_address"}, output + end + end + + def test_schema_dump_includes_cidr_shorthand_definition + output = standard_dump + if %r{create_table "postgresql_network_address"} =~ output + assert_match %r{t.cidr "cidr_address"}, output + end + end + + def test_schema_dump_includes_macaddr_shorthand_definition + output = standard_dump + if %r{create_table "postgresql_network_address"} =~ output + assert_match %r{t.macaddr "macaddr_address"}, output + end + end + def test_schema_dump_includes_hstores_shorthand_definition output = standard_dump if %r{create_table "postgresql_hstores"} =~ output -- cgit v1.2.3 From c334175f0a83303c70cc272f7965284c79698dec Mon Sep 17 00:00:00 2001 From: Dan Seaver Date: Mon, 7 May 2012 09:25:36 -0400 Subject: Converts inet and cidr columns to NetAddr::CIDR --- activerecord/activerecord.gemspec | 1 + .../active_record/connection_adapters/column.rb | 1 + .../connection_adapters/postgresql/oid.rb | 15 +++++++++--- .../connection_adapters/postgresql_adapter.rb | 28 ++++++++++++++++++++++ .../cases/adapters/postgresql/datatype_test.rb | 10 ++++---- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index e8e5f4adfe..b91940569e 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -24,4 +24,5 @@ Gem::Specification.new do |s| s.add_dependency('arel', '~> 3.0.2') s.add_dependency('active_record_deprecated_finders', '0.0.1') + s.add_dependency('netaddr', '~> 1.5.0') end diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 9af8e46120..75049a30f6 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -124,6 +124,7 @@ module ActiveRecord when :binary then "#{klass}.binary_to_string(#{var_name})" when :boolean then "#{klass}.value_to_boolean(#{var_name})" when :hstore then "#{klass}.string_to_hstore(#{var_name})" + when :inet, :cidr then "#{klass}.string_to_cidr(#{var_name})" else var_name end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index c82afc232c..df3d5e4657 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -137,6 +137,14 @@ module ActiveRecord end end + class Cidr < Type + def type_cast(value) + return if value.nil? + + ConnectionAdapters::PostgreSQLColumn.string_to_cidr value + end + end + class TypeMap def initialize @mapping = {} @@ -212,11 +220,9 @@ module ActiveRecord # FIXME: why are we keeping these types as strings? alias_type 'tsvector', 'text' alias_type 'interval', 'text' - alias_type 'cidr', 'text' - alias_type 'inet', 'text' - alias_type 'macaddr', 'text' alias_type 'bit', 'text' alias_type 'varbit', 'text' + alias_type 'macaddr', 'text' # FIXME: I don't think this is correct. We should probably be returning a parsed date, # but the tests pass with a string returned. @@ -237,6 +243,9 @@ module ActiveRecord register_type 'polygon', OID::Identity.new register_type 'circle', OID::Identity.new register_type 'hstore', OID::Hstore.new + + register_type 'cidr', OID::Cidr.new + alias_type 'inet', 'cidr' end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index c68c08a488..45149e69a6 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank' require 'active_record/connection_adapters/statement_pool' require 'active_record/connection_adapters/postgresql/oid' require 'arel/visitors/bind_visitor' +require 'netaddr' # Make sure we're using pg high enough for PGResult#values gem 'pg', '~> 0.11' @@ -79,6 +80,25 @@ module ActiveRecord end end + def string_to_cidr(string) + if string.nil? + nil + elsif String === string + NetAddr::CIDR.create(string) + else + string + end + + end + + def cidr_to_string(object) + if NetAddr::CIDR === object + object.to_s + else + object + end + end + private HstorePair = begin quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ @@ -529,6 +549,11 @@ module ActiveRecord when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column) else super end + when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6 + case column.sql_type + when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column) + else super + end when Float if value.infinite? && column.type == :datetime "'#{value.to_s.downcase}'" @@ -568,6 +593,9 @@ module ActiveRecord when Hash return super unless 'hstore' == column.sql_type PostgreSQLColumn.hstore_to_string(value) + when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6 + return super unless ['inet','cidr'].includes? column.sql_type + PostgreSQLColumn.cidr_to_string(value) else super end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index d42f1ff5a1..cf58c3089f 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -135,8 +135,10 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end def test_network_address_values - assert_equal '192.168.0.0/24', @first_network_address.cidr_address - assert_equal '172.16.1.254', @first_network_address.inet_address + cidr_address = NetAddr::CIDR.create '192.168.0.0/24' + inet_address = NetAddr::CIDR.create '172.16.1.254' + assert_equal cidr_address, @first_network_address.cidr_address + assert_equal inet_address, @first_network_address.inet_address assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address end @@ -200,8 +202,8 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end def test_update_network_address - new_cidr_address = '10.1.2.3/32' - new_inet_address = '10.0.0.0/8' + new_inet_address = '10.1.2.3/32' + new_cidr_address = '10.0.0.0/8' new_mac_address = 'bc:de:f0:12:34:56' assert @first_network_address.cidr_address = new_cidr_address assert @first_network_address.inet_address = new_inet_address -- cgit v1.2.3 From 0e1c6513a442737ab9ff757efec24a10cd2f947a Mon Sep 17 00:00:00 2001 From: Dan McClain Date: Tue, 8 May 2012 15:32:21 -0400 Subject: Removes NetAddr dependency --- activerecord/activerecord.gemspec | 1 - .../active_record/connection_adapters/postgresql_adapter.rb | 13 +++++++------ .../test/cases/adapters/postgresql/datatype_test.rb | 7 ++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec index b91940569e..e8e5f4adfe 100644 --- a/activerecord/activerecord.gemspec +++ b/activerecord/activerecord.gemspec @@ -24,5 +24,4 @@ Gem::Specification.new do |s| s.add_dependency('arel', '~> 3.0.2') s.add_dependency('active_record_deprecated_finders', '0.0.1') - s.add_dependency('netaddr', '~> 1.5.0') end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 45149e69a6..6714970103 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -3,12 +3,13 @@ require 'active_support/core_ext/object/blank' require 'active_record/connection_adapters/statement_pool' require 'active_record/connection_adapters/postgresql/oid' require 'arel/visitors/bind_visitor' -require 'netaddr' # Make sure we're using pg high enough for PGResult#values gem 'pg', '~> 0.11' require 'pg' +require 'ipaddr' + module ActiveRecord module ConnectionHandling # Establishes a connection to the database that's used by all Active Record objects @@ -84,7 +85,7 @@ module ActiveRecord if string.nil? nil elsif String === string - NetAddr::CIDR.create(string) + IPAddr.new(string) else string end @@ -92,8 +93,8 @@ module ActiveRecord end def cidr_to_string(object) - if NetAddr::CIDR === object - object.to_s + if IPAddr === object + "#{object.to_s}/#{object.instance_variable_get(:@mask_addr).to_s(2).count('1')}" else object end @@ -549,7 +550,7 @@ module ActiveRecord when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column) else super end - when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6 + when IPAddr case column.sql_type when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column) else super @@ -593,7 +594,7 @@ module ActiveRecord when Hash return super unless 'hstore' == column.sql_type PostgreSQLColumn.hstore_to_string(value) - when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6 + when IPAddr return super unless ['inet','cidr'].includes? column.sql_type PostgreSQLColumn.cidr_to_string(value) else diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index cf58c3089f..34660577da 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -134,9 +134,10 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase assert_equal '-1 years -2 days', @first_time.time_interval end - def test_network_address_values - cidr_address = NetAddr::CIDR.create '192.168.0.0/24' - inet_address = NetAddr::CIDR.create '172.16.1.254' + def test_network_address_values_ipaddr + cidr_address = IPAddr.new '192.168.0.0/24' + inet_address = IPAddr.new '172.16.1.254' + assert_equal cidr_address, @first_network_address.cidr_address assert_equal inet_address, @first_network_address.inet_address assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address -- cgit v1.2.3