postgres_ext 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 0.0.9
2
+
3
+ * Fixes #<attribute_name>?, Adds (pending) test case for #update_column - Dan McClain (@danmcclain)
4
+ * Fix handing of pgsql arrays for the literal and argument-binding
5
+ cases - Michael Graff (@skandragon)
6
+ * Fixes UTF-8 strings in string arrays are not returned as UTF-8
7
+ encoded strings - Michael Graff (@skandragon)
8
+ * Documentation fixes - Michael Graff (@skandragon) and Dan McClain
9
+ (@danmcclain)
10
+ * Properly encode strings stored in an array. - Michael Graff
11
+ (@skandragon)
12
+ * Fixes integer array support - Keenan Brock (@kbrock)
13
+ * Adds more robust index types with add_index options :index_type and :where. - Keenan Brock (@kbrock)
14
+
1
15
  ## 0.0.8
2
16
 
3
17
  Fixes add and change column
data/CONTRIBUTING.md CHANGED
@@ -25,9 +25,11 @@ If you'd like to submit a pull request please adhere to the following:
25
25
  5. General Rails/Ruby naming conventions for files and classes
26
26
  6. *Do not* use Ruby 1.9 hash syntax
27
27
  7. *Do not* use Ruby 1.9 stubby proc syntax
28
+ 8. Follow Tim Pope's [model for git commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). This will make it
29
+ much easier to generate change logs and navigate through the logs
28
30
 
29
31
  Plase note that you must adhere to each of the above mentioned rules.
30
32
  Failure to do so will result in an immediate closing of the pull
31
33
  request. If you update and rebase the pull request to follow the
32
34
  guidelines your pull request will be re-opened and considered for
33
- inclusion.
35
+ inclusion.
data/README.md CHANGED
@@ -99,9 +99,9 @@ ones added by postgre\_ext), and respect length constraints
99
99
  create_table :testing do |t|
100
100
  t.integer :int_array, :array => true
101
101
  # integer[]
102
- t.integer :int_array, :array => true, :length => 2
102
+ t.integer :int_array, :array => true, :limit => 2
103
103
  # smallint[]
104
- t.string :macaddr_column_1, :array => true, :length => 30
104
+ t.string :macaddr_column_1, :array => true, :limit => 30
105
105
  # char varying(30)[]
106
106
  end
107
107
  ```
@@ -218,7 +218,7 @@ accompish this:
218
218
  user_arel = User.arel_table
219
219
 
220
220
  any_tags_function = Arel::Nodes::NamedFunction.new('ANY', [user_arel[:tags]])
221
- predicate = Arel::Nodes::Equality('test', any_tags_function)
221
+ predicate = Arel::Nodes::Equality.new('test', any_tags_function)
222
222
 
223
223
  User.where(predicate).to_sql
224
224
  #=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
@@ -253,6 +253,25 @@ user_arel = User.arel_table
253
253
  User.where(user_arel[:ip_address].contained_witin('127.0.0.1/24')).to_sql
254
254
  # => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
255
255
  ```
256
+
257
+ ## Indexes
258
+
259
+ ### Index types
260
+
261
+ Postgres\_ext allows you to specify an index type at index creation.
262
+
263
+ ```ruby
264
+ add_index :table_name, :column, :index_type => :gin
265
+ ```
266
+
267
+ ### Where clauses
268
+
269
+ Postgres\_ext allows you to specify a where clause at index creation.
270
+
271
+ ```ruby
272
+ add_index :table_name, :column, :where => 'column < 50'
273
+ ```
274
+
256
275
  ## Authors
257
276
 
258
277
  Dan McClain [twitter](http://twitter.com/_danmcclain) [github](http://github.com/danmcclain)
@@ -4,6 +4,11 @@ require 'pg_array_parser'
4
4
 
5
5
  module ActiveRecord
6
6
  module ConnectionAdapters
7
+ # class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :index_type)
8
+ class IndexDefinition
9
+ attr_accessor :index_type, :where
10
+ end
11
+
7
12
  class PostgreSQLColumn
8
13
  include PgArrayParser
9
14
  attr_accessor :array
@@ -37,7 +42,7 @@ module ActiveRecord
37
42
  else
38
43
  case type
39
44
  when :inet, :cidr then klass.string_to_cidr_address(value)
40
- else
45
+ else
41
46
  type_cast_without_extended_types(value)
42
47
  end
43
48
  end
@@ -49,7 +54,7 @@ module ActiveRecord
49
54
  else
50
55
  string_array = parse_pg_array value
51
56
  if type == :string
52
- string_array
57
+ force_character_encoding(string_array)
53
58
  else
54
59
  type_cast_array(string_array)
55
60
  end
@@ -57,15 +62,13 @@ module ActiveRecord
57
62
  end
58
63
 
59
64
  def type_cast_array(array)
60
- casted_array = []
61
- array.each do |value|
62
- if Array === value
63
- casted_array.push type_cast_array(value)
64
- else
65
- casted_array.push type_cast value
66
- end
65
+ array.map do |value|
66
+ Array === value ? type_cast_array(value) : type_cast(value)
67
67
  end
68
- casted_array
68
+ end
69
+
70
+ def number?
71
+ !self.array && super
69
72
  end
70
73
 
71
74
  def type_cast_code_with_extended_types(var_name)
@@ -89,8 +92,15 @@ module ActiveRecord
89
92
  return IPAddr.new(string)
90
93
  end
91
94
  end
95
+
92
96
  private
93
97
 
98
+ def force_character_encoding(string_array)
99
+ string_array.map do |item|
100
+ item.respond_to?(:force_encoding) ? item.force_encoding(ActiveRecord::Base.connection.encoding_for_ruby) : item
101
+ end
102
+ end
103
+
94
104
  def simplified_type_with_extended_types(field_type)
95
105
  case field_type
96
106
  when 'uuid'
@@ -115,6 +125,17 @@ module ActiveRecord
115
125
  attr_accessor :array
116
126
  end
117
127
 
128
+ # Translate from the current database encoding to the encoding we
129
+ # will force string array components into on retrievial.
130
+ def encoding_for_ruby
131
+ @database_encoding ||= case ActiveRecord::Base.connection.encoding
132
+ when 'UTF8'
133
+ 'UTF-8'
134
+ else
135
+ ActiveRecord::Base.connection.encoding
136
+ end
137
+ end
138
+
118
139
  class TableDefinition
119
140
  EXTENDED_TYPES.keys.map(&:to_s).each do |column_type|
120
141
  class_eval <<-EOV, __FILE__, __LINE__ + 1
@@ -179,6 +200,15 @@ module ActiveRecord
179
200
  super
180
201
  end
181
202
 
203
+ def add_index(table_name, column_name, options = {})
204
+ index_name, unique, index_columns, _ = add_index_options(table_name, column_name, options)
205
+ if options.is_a? Hash
206
+ index_type = options[:index_type] ? " USING #{options[:index_type]} " : ""
207
+ index_options = options[:where] ? " WHERE #{options[:where]}" : ""
208
+ end
209
+ execute "CREATE #{unique} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}#{index_type}(#{index_columns})#{index_options}"
210
+ end
211
+
182
212
  def change_table(table_name, options = {})
183
213
  if supports_bulk_alter? && options[:bulk]
184
214
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
@@ -221,7 +251,7 @@ module ActiveRecord
221
251
  end
222
252
  when Array
223
253
  if column.array
224
- array_to_string(value, column)
254
+ array_to_string(value, column)
225
255
  else
226
256
  type_cast_without_extended_types(value, column)
227
257
  end
@@ -234,22 +264,93 @@ module ActiveRecord
234
264
  alias_method_chain :type_cast, :extended_types
235
265
 
236
266
  def quote_with_extended_types(value, column = nil)
237
- if [Array, IPAddr].include? value.class
267
+ if value.is_a? IPAddr
238
268
  "'#{type_cast(value, column)}'"
269
+ elsif value.is_a? Array
270
+ "'#{array_to_string(value, column, true)}'"
239
271
  else
240
272
  quote_without_extended_types(value, column)
241
273
  end
242
274
  end
243
275
  alias_method_chain :quote, :extended_types
244
276
 
277
+ # this is based upon rails 4 changes to include different index methods
278
+ # Returns an array of indexes for the given table.
279
+ def indexes(table_name, name = nil)
280
+ result = select_rows(<<-SQL, name)
281
+ SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
282
+ FROM pg_class t
283
+ INNER JOIN pg_index d ON t.oid = d.indrelid
284
+ INNER JOIN pg_class i ON d.indexrelid = i.oid
285
+ WHERE i.relkind = 'i'
286
+ AND d.indisprimary = 'f'
287
+ AND t.relname = '#{table_name}'
288
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
289
+ ORDER BY i.relname
290
+ SQL
291
+ result.map do |row|
292
+ index_name = row[0]
293
+ unique = row[1] == 't'
294
+ indkey = row[2].split(" ")
295
+ inddef = row[3]
296
+ oid = row[4]
297
+
298
+ columns = Hash[select_rows(<<-SQL, "Columns for index #{row[0]} on #{table_name}")]
299
+ SELECT a.attnum::text, a.attname
300
+ FROM pg_attribute a
301
+ WHERE a.attrelid = #{oid}
302
+ AND a.attnum IN (#{indkey.join(",")})
303
+ SQL
304
+ column_names = columns.values_at(*indkey).compact
305
+
306
+ # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
307
+ desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
308
+ orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
309
+ #changed from rails 3.2
310
+ where = inddef.scan(/WHERE (.+)$/).flatten[0]
311
+ index_type = inddef.scan(/USING (.+?) /).flatten[0].to_sym
312
+ if column_names.present?
313
+ index_def = IndexDefinition.new(table_name, index_name, unique, column_names, [], orders)
314
+ index_def.where = where
315
+ index_def.index_type = index_type if index_type && index_type != :btree
316
+ index_def
317
+ # else nil
318
+ end
319
+ #/changed
320
+ end.compact
321
+ end
322
+
245
323
  private
246
324
 
247
325
  def ipaddr_to_string(value)
248
326
  "#{value.to_s}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
249
327
  end
250
328
 
251
- def array_to_string(value, column)
252
- "{#{value.map{|val| type_cast(val, column, true)}.join(',')}}"
329
+ def array_to_string(value, column, encode_single_quotes = false)
330
+ "{#{value.map { |val| item_to_string(val, column, encode_single_quotes) }.join(',')}}"
331
+ end
332
+
333
+ def item_to_string(value, column, encode_single_quotes = false)
334
+ if value.nil?
335
+ 'NULL'
336
+ elsif value.is_a? String
337
+ value = type_cast(value, column, true).dup
338
+ # Encode backslashes. One backslash becomes 4 in the resulting SQL.
339
+ # (why 4, and not 2? Trial and error shows 4 works, 2 fails to parse.)
340
+ value.gsub!('\\', '\\\\\\\\')
341
+ # Encode a bare " in the string as \"
342
+ value.gsub!('"', '\\"')
343
+ # PostgreSQL parses the string values differently if they are quoted for
344
+ # use in a statement, or if it will be used as part of a bound argument.
345
+ # For directly-inserted values (UPDATE foo SET bar='{"array"}') we need to
346
+ # escape ' as ''. For bound arguments, do not escape them.
347
+ if encode_single_quotes
348
+ value.gsub!("'", "''")
349
+ end
350
+ "\"#{value}\""
351
+ else
352
+ type_cast(value, column, true)
353
+ end
253
354
  end
254
355
  end
255
356
  end
@@ -2,6 +2,11 @@ require 'active_record/schema_dumper'
2
2
 
3
3
  module ActiveRecord
4
4
  class SchemaDumper
5
+ VALID_COLUMN_SPEC_KEYS = [:name, :limit, :precision, :scale, :default, :null, :array]
6
+ def self.valid_column_spec_keys
7
+ VALID_COLUMN_SPEC_KEYS
8
+ end
9
+
5
10
  private
6
11
  def table(table, stream)
7
12
  columns = @connection.columns(table)
@@ -30,11 +35,13 @@ module ActiveRecord
30
35
  column_specs = columns.map do |column|
31
36
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
32
37
  next if column.name == pk
33
- column_spec(column)
38
+ spec = column_spec(column)
39
+ (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
40
+ spec
34
41
  end.compact
35
42
 
36
43
  # find all migration keys used in this table
37
- keys = [:name, :limit, :precision, :scale, :default, :null, :array] & column_specs.map{ |k| k.keys }.flatten
44
+ keys = self.class.valid_column_spec_keys & column_specs.map{ |k| k.keys }.flatten
38
45
 
39
46
  # figure out the lengths for each column based on above keys
40
47
  lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
@@ -73,6 +80,37 @@ module ActiveRecord
73
80
  stream
74
81
  end
75
82
 
83
+ #mostly rails 3.2 code
84
+ def indexes(table, stream)
85
+ if (indexes = @connection.indexes(table)).any?
86
+ add_index_statements = indexes.map do |index|
87
+ statement_parts = [
88
+ ('add_index ' + index.table.inspect),
89
+ index.columns.inspect,
90
+ (':name => ' + index.name.inspect),
91
+ ]
92
+ statement_parts << ':unique => true' if index.unique
93
+
94
+ index_lengths = (index.lengths || []).compact
95
+ statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
96
+
97
+ index_orders = (index.orders || {})
98
+ statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty?
99
+
100
+ # changed from rails 2.3
101
+ statement_parts << (':where => ' + index.where.inspect) if index.where
102
+ statement_parts << (':index_type => ' + index.index_type.inspect) if index.index_type
103
+ # /changed
104
+
105
+ ' ' + statement_parts.join(', ')
106
+ end
107
+
108
+ stream.puts add_index_statements.sort.join("\n")
109
+ stream.puts
110
+ end
111
+ end
112
+
113
+ #mostly rails 3.2 code (pulled out of table method)
76
114
  def column_spec(column)
77
115
  spec = {}
78
116
  spec[:name] = column.name.inspect
@@ -89,8 +127,9 @@ module ActiveRecord
89
127
  spec[:scale] = column.scale.inspect if column.scale
90
128
  spec[:null] = 'false' unless column.null
91
129
  spec[:default] = default_string(column.default) if column.has_default?
130
+ # changed from rails 3.2 code
92
131
  spec[:array] = 'true' if column.respond_to?(:array) && column.array
93
- (spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
132
+ # /changed
94
133
  spec
95
134
  end
96
135
  end
@@ -21,11 +21,8 @@ module Arel
21
21
  end
22
22
 
23
23
  def change_string value
24
- if value.match /"|,|\{/
25
- value.gsub(/"/, "\"").gsub(/'/,'"')
26
- else
27
- value.gsub(/'/,'')
28
- end
24
+ return value unless value.is_a?(String)
25
+ value.gsub(/^\'/, '"').gsub(/\'$/, '"')
29
26
  end
30
27
  end
31
28
  end
@@ -1,3 +1,3 @@
1
1
  module PostgresExt
2
- VERSION = '0.0.8'
2
+ VERSION = '0.0.9'
3
3
  end
data/postgres_ext.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.version = PostgresExt::VERSION
17
17
 
18
18
  gem.add_dependency 'activerecord', '~> 3.2.0'
19
- gem.add_dependency 'pg_array_parser', '~> 0.0.3'
19
+ gem.add_dependency 'pg_array_parser', '~> 0.0.8'
20
20
 
21
21
  gem.add_development_dependency 'rails', '~> 3.2.0'
22
22
  gem.add_development_dependency 'rspec-rails', '~> 2.9.0'
@@ -27,8 +27,11 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency 'pg', '~> 0.13.2'
28
28
  end
29
29
  unless ENV['CI']
30
- gem.add_development_dependency 'debugger', '~> 1.1.2' if RUBY_VERSION == '1.9.3'
31
- gem.add_development_dependency 'ruby-debug' if RUBY_PLATFORM =~ /java/
30
+ if RUBY_PLATFORM =~ /java/
31
+ gem.add_development_dependency 'ruby-debug'
32
+ elsif RUBY_VERSION == '1.9.3'
33
+ gem.add_development_dependency 'debugger', '~> 1.1.2'
34
+ end
32
35
  end
33
36
  gem.add_development_dependency 'fivemat'
34
37
  end
@@ -6,6 +6,7 @@ describe 'Array Column Predicates' do
6
6
  before do
7
7
  adapter.create_table :arel_arrays, :force => true do |t|
8
8
  t.string :tags, :array => true
9
+ t.integer :tag_ids, :array => true
9
10
  end
10
11
 
11
12
  class ArelArray < ActiveRecord::Base
@@ -22,7 +23,13 @@ describe 'Array Column Predicates' do
22
23
  it 'converts Arel array_overlap statment' do
23
24
  arel_table = ArelArray.arel_table
24
25
 
25
- arel_table.where(arel_table[:tags].array_overlap(['tag','tag 2'])).to_sql.should match /&& '\{tag,tag 2\}'/
26
+ arel_table.where(arel_table[:tags].array_overlap(['tag','tag 2'])).to_sql.should match /&& '\{"tag","tag 2"\}'/
27
+ end
28
+
29
+ it 'converts Arel array_overlap statment' do
30
+ arel_table = ArelArray.arel_table
31
+
32
+ arel_table.where(arel_table[:tag_ids].array_overlap([1,2])).to_sql.should match /&& '\{1,2\}'/
26
33
  end
27
34
 
28
35
  it 'returns matched records' do
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'Array column' do
@@ -13,14 +15,32 @@ describe 'Array column' do
13
15
  end
14
16
  end
15
17
 
18
+ context 'utf8' do
19
+ it "handles incoming UTF8 as UTF8" do
20
+ string_array_column.type_cast('{"Аркалио"}').should eq ['Аркалио']
21
+ end
22
+ end
23
+
16
24
  context 'corner cases, strings with commas and quotations' do
17
25
  it 'converts the PostgreSQL value containing escaped " to an array' do
18
26
  string_array_column.type_cast('{"has \" quote",another value}').should eq ['has " quote', 'another value']
19
27
  end
20
28
 
21
- it 'converts the PostgreSQL value containgin commas to an array' do
29
+ it 'converts the PostgreSQL value containing commas to an array' do
22
30
  string_array_column.type_cast('{"has , comma",another value,"more, commas"}').should eq ['has , comma', 'another value', 'more, commas']
23
31
  end
32
+
33
+ it 'converts strings containing , to the proper value' do
34
+ adapter.type_cast(['c,'], string_array_column).should eq '{"c,"}'
35
+ end
36
+
37
+ it "handles strings with double quotes" do
38
+ adapter.type_cast(['a"b'], string_array_column).should eq '{"a\\"b"}'
39
+ end
40
+
41
+ it 'converts arrays of strings containing nil to the proper value' do
42
+ adapter.type_cast(['one', nil, 'two'], string_array_column).should eq '{"one",NULL,"two"}'
43
+ end
24
44
  end
25
45
  end
26
46
  end
@@ -1,5 +1,5 @@
1
1
  Dummy::Application.configure do
2
- require 'debugger' if RUBY_VERSION == '1.9.3'
2
+ require 'debugger' if RUBY_VERSION == '1.9.3' && ! ENV['CI']
3
3
  # Settings specified here will take precedence over those in config/application.rb
4
4
 
5
5
  # In the development environment your application's code is reloaded on
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'index migrations' do
4
+ let!(:connection) { ActiveRecord::Base.connection }
5
+ it 'creates special index' do
6
+ lambda do
7
+ connection.create_table :index_types do |t|
8
+ t.integer :col1, :array => true
9
+ t.integer :col2
10
+ end
11
+ connection.add_index(:index_types, :col1, :index_type => :gin)
12
+ connection.add_index(:index_types, :col2, :where => '(col2 > 50)')
13
+ end.should_not raise_exception
14
+
15
+ indexes = connection.indexes(:index_types)
16
+ index_1 = indexes.detect { |c| c.columns.map(&:to_s) == ['col1']}
17
+ index_2 = indexes.detect { |c| c.columns.map(&:to_s) == ['col2']}
18
+
19
+ index_1.index_type.to_s.should eq 'gin'
20
+ index_2.where.should match /col2 > 50/
21
+ end
22
+ end
@@ -7,12 +7,13 @@ describe 'Models with array columns' do
7
7
  before do
8
8
  adapter.create_table :users, :force => true do |t|
9
9
  t.string :nick_names, :array => true
10
+ t.integer :favorite_numbers, :array => true
10
11
 
11
12
  t.timestamps
12
13
  end
13
14
 
14
15
  class User < ActiveRecord::Base
15
- attr_accessible :nick_names
16
+ attr_accessible :nick_names, :favorite_numbers
16
17
  end
17
18
  end
18
19
 
@@ -73,6 +74,42 @@ describe 'Models with array columns' do
73
74
  end
74
75
  end
75
76
 
77
+ context '#<column>? do' do
78
+ describe 'checking a value via <attribute_name>? 'do
79
+ it 'returns false if it\'s an empty array' do
80
+ user = User.create(:nick_names => [], :favorite_numbers => [])
81
+ user.reload
82
+
83
+ user.nick_names?.should be_false
84
+ user.favorite_numbers?.should be_false
85
+ end
86
+
87
+ it 'returns false if it\'s an empty array' do
88
+ user = User.create(:nick_names => ['bob'], :favorite_numbers => [0])
89
+ user.reload
90
+
91
+ user.nick_names?.should be_true
92
+ user.favorite_numbers?.should be_true
93
+ end
94
+ end
95
+ end
96
+
97
+ context '#update_column' do
98
+ describe 'setting a value via update_column' do
99
+ it 'returns the value set when the record is retrieved' do
100
+ pending #This fails, not sure where to fix this, takes different code path than #update_attribute
101
+ user = User.create(:nick_names => [])
102
+ user.reload
103
+
104
+ user.update_column(:nick_names, ['some', 'values'])
105
+ user.save
106
+
107
+ user.reload
108
+ user.nick_names.should eq ['some', 'values']
109
+ end
110
+ end
111
+ end
112
+
76
113
  context '#update_attributes' do
77
114
  describe 'setting a value via update_attributes' do
78
115
  it 'returns the value set when the record is retrieved' do
@@ -87,6 +124,105 @@ describe 'Models with array columns' do
87
124
  end
88
125
  end
89
126
  end
127
+
128
+ describe 'strings contain special characters' do
129
+ context '#save' do
130
+ it 'contains: \'' do
131
+ data = ['some\'thing']
132
+ u = User.create
133
+ u.nick_names = data
134
+ u.save!
135
+ u.reload
136
+ u.nick_names.should eq data
137
+ end
138
+
139
+ it 'contains: {' do
140
+ data = ['some{thing']
141
+ u = User.create
142
+ u.nick_names = data
143
+ u.save!
144
+ u.reload
145
+ u.nick_names.should eq data
146
+ end
147
+
148
+ it 'contains: }' do
149
+ data = ['some}thing']
150
+ u = User.create
151
+ u.nick_names = data
152
+ u.save!
153
+ u.reload
154
+ u.nick_names.should eq data
155
+ end
156
+
157
+ it 'contains: backslash' do
158
+ data = ['some\\thing']
159
+ u = User.create
160
+ u.nick_names = data
161
+ u.save!
162
+ u.reload
163
+ u.nick_names.should eq data
164
+ end
165
+
166
+ it 'contains: "' do
167
+ data = ['some"thing']
168
+ u = User.create
169
+ u.nick_names = data
170
+ u.save!
171
+ u.reload
172
+ u.nick_names.should eq data
173
+ end
174
+ end
175
+
176
+ context '#create' do
177
+ it 'contains: \'' do
178
+ data = ['some\'thing']
179
+ u = User.create(:nick_names => data)
180
+ u.reload
181
+ u.nick_names.should eq data
182
+ end
183
+
184
+ it 'contains: {' do
185
+ data = ['some{thing']
186
+ u = User.create(:nick_names => data)
187
+ u.reload
188
+ u.nick_names.should eq data
189
+ end
190
+
191
+ it 'contains: }' do
192
+ data = ['some}thing']
193
+ u = User.create(:nick_names => data)
194
+ u.reload
195
+ u.nick_names.should eq data
196
+ end
197
+
198
+ it 'contains: backslash' do
199
+ data = ['some\\thing']
200
+ u = User.create(:nick_names => data)
201
+ u.reload
202
+ u.nick_names.should eq data
203
+ end
204
+
205
+ it 'contains: "' do
206
+ data = ['some"thing']
207
+ u = User.create(:nick_names => data)
208
+ u.reload
209
+ u.nick_names.should eq data
210
+ end
211
+ end
212
+ end
213
+
214
+ describe 'array_overlap' do
215
+ it "works" do
216
+ arel = User.arel_table
217
+ User.create(:nick_names => ['this'])
218
+ x = User.create
219
+ x.nick_names = ["s'o{m}e", 'thing']
220
+ x.save
221
+ u = User.where(arel[:nick_names].array_overlap(["s'o{m}e"]))
222
+ u.first.should_not be_nil
223
+ u.first.nick_names.should eq ["s'o{m}e", 'thing']
224
+ end
225
+ end
90
226
  end
91
227
 
92
228
  context 'default values' do
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'index schema dumper' do
4
+ let!(:connection) { ActiveRecord::Base.connection }
5
+ it 'correctly generates index statements' do
6
+ connection.create_table :index_types do |t|
7
+ t.integer :col1, :array => true
8
+ t.integer :col2
9
+ end
10
+ connection.add_index(:index_types, :col1, :index_type => :gin)
11
+ connection.add_index(:index_types, :col2, :where => '(col2 > 50)')
12
+
13
+ stream = StringIO.new
14
+ ActiveRecord::SchemaDumper.dump(connection, stream)
15
+ output = stream.string
16
+
17
+ output.should match /:index_type => :gin/
18
+ output.should_not match /:index_type => :btree/
19
+ output.should match /:where => "\(col2 > 50\)"/
20
+ end
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ ENV['RAILS_ENV'] = 'test'
3
3
  require File.expand_path('../dummy/config/environment.rb', __FILE__)
4
4
 
5
5
  require 'rspec/rails'
6
+ require 'rspec/autorun'
6
7
  require 'bourne'
7
8
 
8
9
  ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postgres_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-28 00:00:00.000000000 Z
12
+ date: 2012-11-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.0.3
37
+ version: 0.0.8
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.0.3
45
+ version: 0.0.8
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rails
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -226,6 +226,7 @@ files:
226
226
  - spec/migrations/active_record_migration_spec.rb
227
227
  - spec/migrations/array_spec.rb
228
228
  - spec/migrations/cidr_spec.rb
229
+ - spec/migrations/index_spec.rb
229
230
  - spec/migrations/inet_spec.rb
230
231
  - spec/migrations/macaddr_spec.rb
231
232
  - spec/migrations/uuid_spec.rb
@@ -233,6 +234,7 @@ files:
233
234
  - spec/models/inet_spec.rb
234
235
  - spec/schema_dumper/array_spec.rb
235
236
  - spec/schema_dumper/cidr_spec.rb
237
+ - spec/schema_dumper/index_spec.rb
236
238
  - spec/schema_dumper/inet_spec.rb
237
239
  - spec/schema_dumper/macaddr_spec.rb
238
240
  - spec/schema_dumper/uuid_spec.rb
@@ -251,7 +253,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
253
  version: '0'
252
254
  segments:
253
255
  - 0
254
- hash: -830312040655703419
256
+ hash: -842218502147903775
255
257
  required_rubygems_version: !ruby/object:Gem::Requirement
256
258
  none: false
257
259
  requirements:
@@ -260,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
262
  version: '0'
261
263
  segments:
262
264
  - 0
263
- hash: -830312040655703419
265
+ hash: -842218502147903775
264
266
  requirements: []
265
267
  rubyforge_project:
266
268
  rubygems_version: 1.8.23
@@ -326,6 +328,7 @@ test_files:
326
328
  - spec/migrations/active_record_migration_spec.rb
327
329
  - spec/migrations/array_spec.rb
328
330
  - spec/migrations/cidr_spec.rb
331
+ - spec/migrations/index_spec.rb
329
332
  - spec/migrations/inet_spec.rb
330
333
  - spec/migrations/macaddr_spec.rb
331
334
  - spec/migrations/uuid_spec.rb
@@ -333,6 +336,7 @@ test_files:
333
336
  - spec/models/inet_spec.rb
334
337
  - spec/schema_dumper/array_spec.rb
335
338
  - spec/schema_dumper/cidr_spec.rb
339
+ - spec/schema_dumper/index_spec.rb
336
340
  - spec/schema_dumper/inet_spec.rb
337
341
  - spec/schema_dumper/macaddr_spec.rb
338
342
  - spec/schema_dumper/uuid_spec.rb