perpetuity-postgres 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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