aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/activerecord.gemspec1
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb15
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb28
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb10
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