activerecord-postgres-array 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ require 'rails'
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+
5
+ class ActiveRecordPostgresArray < Rails::Railtie
6
+
7
+ initializer 'activerecord-postgres-array' do
8
+ ActiveSupport.on_load :active_record do
9
+ require "activerecord-postgres-array/activerecord"
10
+ end
11
+ end
12
+ end
13
+
14
+ require "activerecord-postgres-array/string"
15
+ require "activerecord-postgres-array/array"
@@ -0,0 +1,70 @@
1
+ module ActiveRecord
2
+ class ArrayTypeMismatch < ActiveRecord::ActiveRecordError
3
+ end
4
+
5
+ module ConnectionAdapters
6
+ class PostgreSQLAdapter < AbstractAdapter
7
+ POSTGRES_ARRAY_TYPES = %w( string text integer float decimal datetime timestamp time date binary boolean )
8
+
9
+ def native_database_types_with_array(*args)
10
+ native_database_types_without_array.merge(POSTGRES_ARRAY_TYPES.inject(Hash.new) {|h, t| h.update("#{t}_array".to_sym => {:name => "#{t}_array"})})
11
+ end
12
+ alias_method_chain :native_database_types, :array
13
+
14
+
15
+ # Quotes a value for use in an SQL statement
16
+ def quote_with_array(value, column = nil)
17
+ if value && column && column.sql_type =~ /\[\]$/
18
+ raise ArrayTypeMismatch, "#{column.name} must have a Hash or a valid array value (#{value})" unless value.kind_of?(Array) || value.valid_postgres_array?
19
+ return value.to_postgres_array
20
+ end
21
+ quote_without_array(value,column)
22
+ end
23
+ alias_method_chain :quote, :array
24
+ end
25
+
26
+ class TableDefinition
27
+ # Adds array type for migrations. So you can add columns to a table like:
28
+ # create_table :people do |t|
29
+ # ...
30
+ # t.string_array :real_energy
31
+ # t.decimal_array :real_energy, :precision => 18, :scale => 6
32
+ # ...
33
+ # end
34
+ PostgreSQLAdapter::POSTGRES_ARRAY_TYPES.each do |column_type|
35
+ define_method("#{column_type}_array") do |*args|
36
+ options = args.extract_options!
37
+ base_type = @base.type_to_sql(column_type.to_sym, options[:limit], options[:precision], options[:scale])
38
+ column_names = args
39
+ column_names.each { |name| column(name, "#{base_type}[]", options) }
40
+ end
41
+ end
42
+ end
43
+
44
+ class PostgreSQLColumn < Column
45
+ # Does the type casting from array columns using String#from_postgres_array or Array#from_postgres_array.
46
+ def type_cast_code_with_array(var_name)
47
+ if type =~ /_array$/
48
+ base_type = type.gsub(/_array/, '')
49
+ "#{var_name}.from_postgres_array(:#{base_type})"
50
+ else
51
+ type_cast_code_without_array(var_name)
52
+ end
53
+ end
54
+ alias_method_chain :type_cast_code, :array
55
+
56
+
57
+ # Adds the array type for the column.
58
+ def simplified_type_with_array(field_type)
59
+ if field_type =~ /^numeric.+\[\]$/
60
+ :decimal_array
61
+ elsif field_type =~ /\[\]$/
62
+ field_type.gsub(/\[\]/, '_array')
63
+ else
64
+ simplified_type_without_array(field_type)
65
+ end
66
+ end
67
+ alias_method_chain :simplified_type, :array
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,20 @@
1
+ class Array
2
+
3
+ # Generates a single quoted postgres array string format. This is the format used
4
+ # to insert or update stuff in the database.
5
+ def to_postgres_array(omit_quotes = false)
6
+ result = "#{omit_quotes ? '' : "'" }{"
7
+
8
+ result << collect do |value|
9
+ value.is_a?(Array) ? value.to_postgres_array(true) : value
10
+ end.join(", ")
11
+
12
+ result << "}#{omit_quotes ? '' : "'" }"
13
+ end
14
+
15
+ # If the method from_postgres_array is called in an Array, it just returns self.
16
+ def from_postgres_array(base_type = :string)
17
+ self
18
+ end
19
+
20
+ end
@@ -0,0 +1,30 @@
1
+ class String
2
+
3
+ def to_postgres_array
4
+ self
5
+ end
6
+
7
+ # Validates the array format. Valid formats are:
8
+ # * An empty string
9
+ # * A string like '{10000, 10000, 10000, 10000}'
10
+ # * TODO A multi dimensional array string like '{{"meeting", "lunch"}, {"training", "presentation"}}'
11
+ def valid_postgres_array?
12
+ # TODO validate formats above
13
+ true
14
+ end
15
+
16
+ # Creates an array from a postgres array string that postgresql spits out.
17
+ def from_postgres_array(base_type = :string)
18
+ if empty?
19
+ return []
20
+ else
21
+ elements = match(/^\{(.+)\}$/).captures.first.split(",").collect(&:strip)
22
+
23
+ if base_type == :decimal
24
+ return elements.collect(&:to_d)
25
+ else
26
+ return elements
27
+ end
28
+ end
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-postgres-array
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Tim Connor
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-14 00:00:00 +12:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Adds support for postgres arrays to ActiveRecord
23
+ email: tim@youdo.co.nz
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/activerecord-postgres-array.rb
32
+ - lib/activerecord-postgres-array/activerecord.rb
33
+ - lib/activerecord-postgres-array/array.rb
34
+ - lib/activerecord-postgres-array/string.rb
35
+ has_rdoc: true
36
+ homepage:
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 3
50
+ segments:
51
+ - 0
52
+ version: "0"
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.6.2
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Adds support for postgres arrays to ActiveRecord
69
+ test_files: []
70
+