Skip to content
This repository
Browse code

Converts inet and cidr columns to NetAddr::CIDR

  • Loading branch information...
commit c334175f0a83303c70cc272f7965284c79698dec 1 parent f7b8fbd
Dan McClain authored
1  activerecord/activerecord.gemspec
@@ -24,4 +24,5 @@ Gem::Specification.new do |s|
24 24
   s.add_dependency('arel',          '~> 3.0.2')
25 25
 
26 26
   s.add_dependency('active_record_deprecated_finders', '0.0.1')
  27
+  s.add_dependency('netaddr', '~> 1.5.0')
27 28
 end
1  activerecord/lib/active_record/connection_adapters/column.rb
@@ -124,6 +124,7 @@ def type_cast_code(var_name)
124 124
         when :binary               then "#{klass}.binary_to_string(#{var_name})"
125 125
         when :boolean              then "#{klass}.value_to_boolean(#{var_name})"
126 126
         when :hstore               then "#{klass}.string_to_hstore(#{var_name})"
  127
+        when :inet, :cidr          then "#{klass}.string_to_cidr(#{var_name})"
127 128
         else var_name
128 129
         end
129 130
       end
15  activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -137,6 +137,14 @@ def type_cast(value)
137 137
           end
138 138
         end
139 139
 
  140
+        class Cidr < Type
  141
+          def type_cast(value)
  142
+            return if value.nil?
  143
+
  144
+            ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
  145
+          end
  146
+        end
  147
+
140 148
         class TypeMap
141 149
           def initialize
142 150
             @mapping = {}
@@ -212,11 +220,9 @@ def self.registered_type?(name)
212 220
         # FIXME: why are we keeping these types as strings?
213 221
         alias_type 'tsvector', 'text'
214 222
         alias_type 'interval', 'text'
215  
-        alias_type 'cidr',     'text'
216  
-        alias_type 'inet',     'text'
217  
-        alias_type 'macaddr',  'text'
218 223
         alias_type 'bit',      'text'
219 224
         alias_type 'varbit',   'text'
  225
+        alias_type 'macaddr',  'text'
220 226
 
221 227
         # FIXME: I don't think this is correct. We should probably be returning a parsed date,
222 228
         # but the tests pass with a string returned.
@@ -237,6 +243,9 @@ def self.registered_type?(name)
237 243
         register_type 'polygon', OID::Identity.new
238 244
         register_type 'circle', OID::Identity.new
239 245
         register_type 'hstore', OID::Hstore.new
  246
+
  247
+        register_type 'cidr', OID::Cidr.new
  248
+        alias_type 'inet', 'cidr'
240 249
       end
241 250
     end
242 251
   end
28  activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -3,6 +3,7 @@
3 3
 require 'active_record/connection_adapters/statement_pool'
4 4
 require 'active_record/connection_adapters/postgresql/oid'
5 5
 require 'arel/visitors/bind_visitor'
  6
+require 'netaddr'
6 7
 
7 8
 # Make sure we're using pg high enough for PGResult#values
8 9
 gem 'pg', '~> 0.11'
@@ -79,6 +80,25 @@ def string_to_hstore(string)
79 80
           end
80 81
         end
81 82
 
  83
+        def string_to_cidr(string)
  84
+          if string.nil?
  85
+            nil
  86
+          elsif String === string
  87
+            NetAddr::CIDR.create(string)
  88
+          else
  89
+            string
  90
+          end
  91
+
  92
+        end
  93
+
  94
+        def cidr_to_string(object)
  95
+          if NetAddr::CIDR === object
  96
+            object.to_s
  97
+          else
  98
+            object
  99
+          end
  100
+        end
  101
+
82 102
         private
83 103
         HstorePair = begin
84 104
           quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
@@ -529,6 +549,11 @@ def quote(value, column = nil) #:nodoc:
529 549
           when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column)
530 550
           else super
531 551
           end
  552
+        when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6
  553
+          case column.sql_type
  554
+          when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column)
  555
+          else super
  556
+          end
532 557
         when Float
533 558
           if value.infinite? && column.type == :datetime
534 559
             "'#{value.to_s.downcase}'"
@@ -568,6 +593,9 @@ def type_cast(value, column)
568 593
         when Hash
569 594
           return super unless 'hstore' == column.sql_type
570 595
           PostgreSQLColumn.hstore_to_string(value)
  596
+        when NetAddr::CIDR, NetAddr::CIDRv4, NetAddr::CIDRv6
  597
+          return super unless ['inet','cidr'].includes? column.sql_type
  598
+          PostgreSQLColumn.cidr_to_string(value)
571 599
         else
572 600
           super
573 601
         end
10  activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -135,8 +135,10 @@ def test_time_values
135 135
   end
136 136
 
137 137
   def test_network_address_values
138  
-    assert_equal '192.168.0.0/24', @first_network_address.cidr_address
139  
-    assert_equal '172.16.1.254', @first_network_address.inet_address
  138
+    cidr_address = NetAddr::CIDR.create '192.168.0.0/24'
  139
+    inet_address = NetAddr::CIDR.create '172.16.1.254'
  140
+    assert_equal cidr_address, @first_network_address.cidr_address
  141
+    assert_equal inet_address, @first_network_address.inet_address
140 142
     assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address
141 143
   end
142 144
 
@@ -200,8 +202,8 @@ def test_update_time
200 202
   end
201 203
 
202 204
   def test_update_network_address
203  
-    new_cidr_address = '10.1.2.3/32'
204  
-    new_inet_address = '10.0.0.0/8'
  205
+    new_inet_address = '10.1.2.3/32'
  206
+    new_cidr_address = '10.0.0.0/8'
205 207
     new_mac_address = 'bc:de:f0:12:34:56'
206 208
     assert @first_network_address.cidr_address = new_cidr_address
207 209
     assert @first_network_address.inet_address = new_inet_address

0 notes on commit c334175

Please sign in to comment.
Something went wrong with that request. Please try again.