perpetuity-postgres 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e26e3fe68009d265b58369daac0505ea33923e54
4
- data.tar.gz: 0c78137c119589349a4ad4aa27efc5a19917f66e
3
+ metadata.gz: 131881bc7b24a361b04326b0fac2699ca1ca2c22
4
+ data.tar.gz: 57dc7bd53e485500524439604ceaa517f5990215
5
5
  SHA512:
6
- metadata.gz: c6a27b6627af877519f3c95e2b18bb0afa0df15a73c995e6dd01ee7c097aa4b16acc24221d6a057120e67efbcc3a1ff1134583190afc6adfe232ac7a7d428404
7
- data.tar.gz: 9936e242b444565acc5651779667531fe5d50c2641484b017f3fadd01ed5800abd35d4a3f3337e7d0b0fcdc3d6db7c9ffa183665730d5e90c0902fd48c28e9f3
6
+ metadata.gz: e1c978801cc9d1a5c4bc888c899ce27ff15166bb396ad4eb5b95212664b408e76f13afb57175220072b532b6beaeb598794c67c0f1de809cb893bad71de49e8a
7
+ data.tar.gz: 5645ce0e3ebca3602b789515db6762ca0713c958dd915502dea87d8137df67f1c55b8b53bd9a632e081c55ce8ee767a12984a294a74db2992150ef48c8b32a68
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## Version 0.0.7
2
+
3
+ - Allow for querying within a range: `mapper.select { |o| o.value.in (1..3) }`
4
+ - Serialize Ruby `Date` objects
5
+
1
6
  ## Version 0.0.6
2
7
 
3
8
  - Depend on [perpetuity](https://github.com/jgaskins/perpetuity) 1.0 final
@@ -0,0 +1,29 @@
1
+ require 'date'
2
+
3
+ module Perpetuity
4
+ class Postgres
5
+ class DateValue
6
+ attr_reader :date
7
+
8
+ def initialize date
9
+ @date = date
10
+ end
11
+
12
+ def self.from_sql date_string
13
+ new(Date.parse(date_string))
14
+ end
15
+
16
+ def to_date
17
+ date
18
+ end
19
+
20
+ def to_s
21
+ "'#{date.to_s}'::date"
22
+ end
23
+
24
+ def value
25
+ date
26
+ end
27
+ end
28
+ end
29
+ end
@@ -66,7 +66,12 @@ module Perpetuity
66
66
  end
67
67
 
68
68
  def in
69
- "#{attribute} IN #{sql_value}"
69
+ case sql_value
70
+ when Range
71
+ "#{attribute} BETWEEN #{SQLValue.new(sql_value.min)} AND #{SQLValue.new(sql_value.max)}"
72
+ else
73
+ "#{attribute} IN #{sql_value}"
74
+ end
70
75
  end
71
76
 
72
77
  def =~
@@ -12,7 +12,7 @@ module Perpetuity
12
12
  class Serializer
13
13
  include DataInjectable
14
14
 
15
- SERIALIZABLE_CLASSES = Set[Fixnum, Float, String, Time, TrueClass, FalseClass, NilClass]
15
+ SERIALIZABLE_CLASSES = Set[Fixnum, Float, String, Time, Date, TrueClass, FalseClass, NilClass]
16
16
  attr_reader :mapper, :mapper_registry
17
17
 
18
18
  def initialize mapper
@@ -1,5 +1,6 @@
1
1
  require 'perpetuity/postgres/text_value'
2
2
  require 'perpetuity/postgres/timestamp_value'
3
+ require 'perpetuity/postgres/date_value'
3
4
  require 'perpetuity/postgres/numeric_value'
4
5
  require 'perpetuity/postgres/null_value'
5
6
  require 'perpetuity/postgres/boolean_value'
@@ -17,6 +18,8 @@ module Perpetuity
17
18
  TextValue.new(value)
18
19
  when Time
19
20
  TimestampValue.new(value)
21
+ when Date
22
+ DateValue.new(value)
20
23
  when Fixnum, Float
21
24
  NumericValue.new(value)
22
25
  when Hash, JSONHash
@@ -18,6 +18,7 @@ module Perpetuity
18
18
  Float => 'FLOAT',
19
19
  UUID => 'UUID',
20
20
  Time => 'TIMESTAMPTZ',
21
+ Date => 'DATE',
21
22
  TrueClass => 'BOOLEAN',
22
23
  FalseClass => 'BOOLEAN'
23
24
  }.tap{|m| m.default = 'JSON' }
@@ -26,7 +27,11 @@ module Perpetuity
26
27
  @name = name
27
28
  @type = type
28
29
  @max_length = options[:max_length]
29
- @primary_key = options.fetch(:primary_key) { false }
30
+ @primary_key = if @name.to_s == 'id'
31
+ true
32
+ else
33
+ options.fetch(:primary_key) { false }
34
+ end
30
35
  @default = options.fetch(:default) { NoDefaultValue }
31
36
  end
32
37
 
@@ -1,5 +1,5 @@
1
1
  module Perpetuity
2
2
  class Postgres
3
- VERSION = "0.0.6"
3
+ VERSION = "0.0.7"
4
4
  end
5
5
  end
@@ -6,7 +6,7 @@ module Perpetuity
6
6
  let(:pool) { ConnectionPool.new }
7
7
 
8
8
  it 'defaults to 5 connections' do
9
- pool.should have(5).connections
9
+ expect(pool.connections.size).to eq 5
10
10
  end
11
11
 
12
12
  describe 'lending a connection' do
@@ -20,9 +20,9 @@ module Perpetuity
20
20
 
21
21
  it 'lends a connection for the duration of a block' do
22
22
  pool.lend_connection do |connection|
23
- pool.should have(4).connections
23
+ expect(pool.connections.size).to eq 4
24
24
  end
25
- pool.should have(5).connections
25
+ expect(pool.connections.size).to eq 5
26
26
  end
27
27
 
28
28
  it 'returns the value of the block' do
@@ -48,7 +48,7 @@ module Perpetuity
48
48
  pool.lend_connection { |c| connections << c }
49
49
  end
50
50
 
51
- connections.uniq.should have(pool.size).items
51
+ expect(connections.uniq.size).to eq pool.size
52
52
  end
53
53
  end
54
54
  end
@@ -0,0 +1,24 @@
1
+ require 'perpetuity/postgres/date_value'
2
+
3
+ module Perpetuity
4
+ class Postgres
5
+ describe DateValue do
6
+ it 'converts to a SQL string' do
7
+ date = Date.new(2014, 8, 25)
8
+ DateValue.new(date).to_s.should == "'2014-08-25'::date"
9
+ end
10
+
11
+ describe 'conversion from a SQL value string' do
12
+ it 'converts GMT-X times' do
13
+ actual = DateValue.from_sql('2013-12-01')
14
+ expected = Date.new(2013, 12, 1)
15
+ actual.to_date.should == expected
16
+ end
17
+ end
18
+
19
+ it 'returns its wrapped value' do
20
+ DateValue.new(:foo).value.should == :foo
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,9 +4,10 @@ module Perpetuity
4
4
  class Postgres
5
5
  describe QueryAttribute do
6
6
  let(:attribute) { QueryAttribute.new :attribute_name }
7
- subject { attribute }
8
7
 
9
- its(:name) { should == :attribute_name }
8
+ it 'returns its name' do
9
+ attribute.name.should == :attribute_name
10
+ end
10
11
 
11
12
  it 'checks for equality' do
12
13
  (attribute == 1).should be_a QueryExpression
@@ -57,6 +57,12 @@ module Perpetuity
57
57
  expression.to_db.should == "attribute IN (1,2,3)"
58
58
  end
59
59
 
60
+ it 'checks for inclusion in a range' do
61
+ expression.comparator = :in
62
+ expression.value = (1..3)
63
+ expression.to_db.should == "attribute BETWEEN 1 AND 3"
64
+ end
65
+
60
66
  it 'checks for inclusion of strings' do
61
67
  expression.comparator = :in
62
68
  expression.value = ['abc', '123']
@@ -45,9 +45,9 @@ module Perpetuity
45
45
  end
46
46
 
47
47
  it 'checks whether there are any objects' do
48
- serialized.any?.should be_true
48
+ serialized.any?.should be_truthy
49
49
  serialized.values.clear << []
50
- serialized.any?.should be_false
50
+ serialized.any?.should be_falsey
51
51
  end
52
52
 
53
53
  it 'iterates like a hash' do
@@ -81,6 +81,11 @@ module Perpetuity
81
81
  serializer.serialize_attribute(time).should == "'2000-01-02 03:04:05.123456-0400'::timestamptz"
82
82
  end
83
83
 
84
+ it 'serializes Date objects' do
85
+ date = Date.new(2014, 8, 25)
86
+ serializer.serialize_attribute(date).should == "'2014-08-25'::date"
87
+ end
88
+
84
89
  it 'serializes an array as JSON' do
85
90
  serializer.serialize_attribute([1, 'foo']).should == %q{'[1,"foo"]'}
86
91
  end
@@ -181,25 +186,25 @@ module Perpetuity
181
186
 
182
187
  describe 'identifying embedded/referenced objects as foreign' do
183
188
  it 'sees hashes with metadata keys as foreign objects' do
184
- serializer.foreign_object?({'__metadata__' => 'lol'}).should be_true
189
+ serializer.foreign_object?({'__metadata__' => 'lol'}).should be_truthy
185
190
  end
186
191
 
187
192
  it 'sees hashes without metadata keys as simple hashes' do
188
- serializer.foreign_object?({ 'name' => 'foo' }).should be_false
193
+ serializer.foreign_object?({ 'name' => 'foo' }).should be_falsey
189
194
  end
190
195
  end
191
196
 
192
197
  describe 'identifying possible JSON strings' do
193
198
  it 'identifies JSON objects' do
194
- serializer.possible_json_value?('{"name":"foo"}').should be_true
199
+ serializer.possible_json_value?('{"name":"foo"}').should be_truthy
195
200
  end
196
201
 
197
202
  it 'identifies JSON arrays' do
198
- serializer.possible_json_value?('[{"name":"foo"}]').should be_true
203
+ serializer.possible_json_value?('[{"name":"foo"}]').should be_truthy
199
204
  end
200
205
 
201
206
  it 'rejects things it does not detect as either of the above' do
202
- serializer.possible_json_value?('foo is my name').should be_false
207
+ serializer.possible_json_value?('foo is my name').should be_falsey
203
208
  end
204
209
  end
205
210
 
@@ -8,9 +8,17 @@ module Perpetuity
8
8
  limit: 4) }
9
9
  subject { query }
10
10
 
11
- its(:table) { should == 'foo' }
12
- its(:where) { should == "name = 'foo'" }
13
- its(:limit) { should == 4 }
11
+ it 'returns its table name' do
12
+ query.table.should == 'foo'
13
+ end
14
+
15
+ it 'returns its WHERE clause' do
16
+ query.where.should == "name = 'foo'"
17
+ end
18
+
19
+ it 'returns its limit' do
20
+ query.limit.should == 4
21
+ end
14
22
 
15
23
  it 'generates a SQL query' do
16
24
  query.to_s.should == %Q{SELECT * FROM "foo" WHERE name = 'foo' LIMIT 4}
@@ -50,6 +50,11 @@ module Perpetuity
50
50
  time = Time.new(2013, 1, 2, 3, 4, 5.1234567, '+05:30')
51
51
  SQLValue.new(time).should == "'2013-01-02 03:04:05.123456+0530'::timestamptz"
52
52
  end
53
+
54
+ it 'converts Date objects' do
55
+ date = Date.new(2014, 8, 25)
56
+ SQLValue.new(date).should == "'2014-08-25'::date"
57
+ end
53
58
  end
54
59
  end
55
60
  end
@@ -80,6 +80,14 @@ module Perpetuity
80
80
  end
81
81
  end
82
82
 
83
+ describe 'dates' do
84
+ let(:date) { Attribute.new('anniversary_date', Date) }
85
+
86
+ it 'converts to the SQL DATE type' do
87
+ date.sql_type.should == 'DATE'
88
+ end
89
+ end
90
+
83
91
  describe 'booleans' do
84
92
  it 'is stored in a BOOLEAN column' do
85
93
  Attribute.new(:true, TrueClass).sql_type.should == 'BOOLEAN'
@@ -29,6 +29,14 @@ module Perpetuity
29
29
  'CREATE TABLE IF NOT EXISTS "Article" (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), title TEXT, body TEXT, author JSON, published_at TIMESTAMPTZ, views BIGINT)'
30
30
  end
31
31
 
32
+ it 'sets the id as PRIMARY KEY even if specified in attributes' do
33
+ attributes = self.attributes.dup
34
+ attributes.unshift Table::Attribute.new(:id, String)
35
+ table = Table.new('Article', attributes)
36
+ table.create_table_sql.should ==
37
+ 'CREATE TABLE IF NOT EXISTS "Article" (id TEXT PRIMARY KEY, title TEXT, body TEXT, author JSON, published_at TIMESTAMPTZ, views BIGINT)'
38
+ end
39
+
32
40
  describe 'id column' do
33
41
  context 'when there is an id attribute' do
34
42
  it 'uses the attribute type for the column type' do
@@ -25,25 +25,36 @@ module Perpetuity
25
25
  password: password
26
26
  )
27
27
  end
28
- subject { postgres }
29
-
30
- its(:host) { should == host }
31
- its(:port) { should == port }
32
- its(:db) { should == db }
33
- its(:pool_size) { should == pool_size }
34
- its(:username) { should == username }
35
- its(:password) { should == password }
28
+
29
+ [:host, :port, :db, :pool_size, :username, :password].each do |attribute|
30
+ it "returns its #{attribute}" do
31
+ postgres.public_send(attribute).should == send(attribute)
32
+ end
33
+ end
36
34
  end
37
35
 
38
36
  context 'default values' do
39
37
  let(:postgres) { Postgres.new(db: 'my_db') }
40
- subject { postgres }
41
38
 
42
- its(:host) { should == 'localhost' }
43
- its(:port) { should == 5432 }
44
- its(:pool_size) { should == 5 }
45
- its(:username) { should == ENV['USER'] }
46
- its(:password) { should be_nil }
39
+ it 'defaults to host = localhost' do
40
+ postgres.host.should == 'localhost'
41
+ end
42
+
43
+ it 'defaults to port = 5432 (Postgres default)' do
44
+ postgres.port.should == 5432
45
+ end
46
+
47
+ it "defaults to username = #{ENV['USER']}" do
48
+ postgres.username.should == ENV['USER']
49
+ end
50
+
51
+ it 'defaults to a blank password' do
52
+ postgres.password.should be nil
53
+ end
54
+
55
+ it 'defaults to pool_size = 5' do
56
+ postgres.pool_size.should == 5
57
+ end
47
58
  end
48
59
  end
49
60
 
@@ -108,7 +119,7 @@ module Perpetuity
108
119
  Postgres::SerializedData.new([:name], ["'Kevin'"])
109
120
  ids = postgres.insert('User', data, attributes)
110
121
  ids.should be_a Array
111
- ids.should have(3).items
122
+ expect(ids.count).to eq 3
112
123
  end
113
124
 
114
125
  it 'returns numeric ids when numeric ids are specified' do
@@ -128,7 +139,7 @@ module Perpetuity
128
139
  it 'counts objects with a string query' do
129
140
  insert = proc { postgres.insert 'User', data, attributes }
130
141
  expect(&insert).to change { postgres.count('User', "name = 'Jamie'") }.by 1
131
- expect(&insert).not_to change { postgres.count('User', "name = 'Jessica'") }.by 1
142
+ expect(&insert).not_to change { postgres.count('User', "name = 'Jessica'") }
132
143
  end
133
144
 
134
145
  it 'returns a count of 0 when the table does not exist' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: perpetuity-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Gaskins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-16 00:00:00.000000000 Z
11
+ date: 2014-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -98,6 +98,7 @@ files:
98
98
  - lib/perpetuity/postgres/boolean_value.rb
99
99
  - lib/perpetuity/postgres/connection.rb
100
100
  - lib/perpetuity/postgres/connection_pool.rb
101
+ - lib/perpetuity/postgres/date_value.rb
101
102
  - lib/perpetuity/postgres/expression.rb
102
103
  - lib/perpetuity/postgres/index.rb
103
104
  - lib/perpetuity/postgres/index_collection.rb
@@ -130,6 +131,7 @@ files:
130
131
  - spec/perpetuity/postgres/boolean_value_spec.rb
131
132
  - spec/perpetuity/postgres/connection_pool_spec.rb
132
133
  - spec/perpetuity/postgres/connection_spec.rb
134
+ - spec/perpetuity/postgres/date_value_spec.rb
133
135
  - spec/perpetuity/postgres/expression_spec.rb
134
136
  - spec/perpetuity/postgres/index_collection_spec.rb
135
137
  - spec/perpetuity/postgres/index_spec.rb
@@ -187,6 +189,7 @@ test_files:
187
189
  - spec/perpetuity/postgres/boolean_value_spec.rb
188
190
  - spec/perpetuity/postgres/connection_pool_spec.rb
189
191
  - spec/perpetuity/postgres/connection_spec.rb
192
+ - spec/perpetuity/postgres/date_value_spec.rb
190
193
  - spec/perpetuity/postgres/expression_spec.rb
191
194
  - spec/perpetuity/postgres/index_collection_spec.rb
192
195
  - spec/perpetuity/postgres/index_spec.rb