sequel-tstzrange-fields 0.1.1 → 0.2.0

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
  SHA256:
3
- metadata.gz: 35ed468cd261b95f2381b6f90c5e1b8afa2318aa406ce06fbec30e8fdb85b89e
4
- data.tar.gz: f501a551e2decbcc47ea133a0527921c182049a48248692ae0d0dea205b04471
3
+ metadata.gz: 2aa09554035af74a589ddd776eff11bf70fa33431c841bb20de3eef9674b4051
4
+ data.tar.gz: 824c97bbb6ea48333980f88aa42f6b5b009f3b1d61fefb13646f54d6511eb378
5
5
  SHA512:
6
- metadata.gz: 9d8fe7ed1837254fa1cc6a183f780d29af01e27367dbbe56e2a7380446ff7aa36808ead45bbf65e562a5e8aff849d8e04f9019a2db40f79f75d709495c1da160
7
- data.tar.gz: 0b94430bb0c3cc0eec9e37309493f08c76fceda6277d71d9918ff12d0ee1b0aaafd5cae364c2eb6530ac72f1f245f1f2ce9c3f698544f0a58dc3c445c604459b
6
+ metadata.gz: c2f59a89cb58c004224b1931a3359bacc70c296c322d108f84082488fb225f1866168d3adfc2669cdbe45cb52819bfe42f3b9b8a9801ee3740ab4ec6a21264c6
7
+ data.tar.gz: ec010f2605963f1cd27d03a1945854ed2f675b1fd77c9435f640673145cc636f64118ff24babd086689c2940a4656c799163d15c7c7df2466189784cb72076f9
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel-tstzrange-fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lithic Tech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-06 00:00:00.000000000 Z
11
+ date: 2023-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: pg
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -52,20 +38,6 @@ dependencies:
52
38
  - - ">="
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: yajl-ruby
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
41
  - !ruby/object:Gem::Dependency
70
42
  name: rake
71
43
  requirement: !ruby/object:Gem::Requirement
@@ -98,44 +70,16 @@ dependencies:
98
70
  name: rubocop
99
71
  requirement: !ruby/object:Gem::Requirement
100
72
  requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop-rake
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: rubocop-rspec
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
73
+ - - "~>"
130
74
  - !ruby/object:Gem::Version
131
- version: '0'
75
+ version: '1.48'
132
76
  type: :development
133
77
  prerelease: false
134
78
  version_requirements: !ruby/object:Gem::Requirement
135
79
  requirements:
136
- - - ">="
80
+ - - "~>"
137
81
  - !ruby/object:Gem::Version
138
- version: '0'
82
+ version: '1.48'
139
83
  - !ruby/object:Gem::Dependency
140
84
  name: rubocop-sequel
141
85
  requirement: !ruby/object:Gem::Requirement
@@ -156,14 +100,12 @@ email:
156
100
  executables: []
157
101
  extensions: []
158
102
  extra_rdoc_files: []
159
- files:
160
- - lib/sequel/plugins/tstzrange_fields.rb
161
- - spec/sequel/plugins/tstzrange_fields_spec.rb
162
- - spec/spec_helper.rb
103
+ files: []
163
104
  homepage:
164
105
  licenses:
165
106
  - MIT
166
- metadata: {}
107
+ metadata:
108
+ rubygems_mfa_required: 'true'
167
109
  post_install_message:
168
110
  rdoc_options: []
169
111
  require_paths:
@@ -172,14 +114,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
172
114
  requirements:
173
115
  - - ">="
174
116
  - !ruby/object:Gem::Version
175
- version: 2.4.0
117
+ version: 2.7.0
176
118
  required_rubygems_version: !ruby/object:Gem::Requirement
177
119
  requirements:
178
120
  - - ">="
179
121
  - !ruby/object:Gem::Version
180
122
  version: '0'
181
123
  requirements: []
182
- rubygems_version: 3.1.4
124
+ rubygems_version: 3.3.3
183
125
  signing_key:
184
126
  specification_version: 4
185
127
  summary: Gem for enabling time ranges when working with postgres
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sequel'
4
- require 'sequel/model'
5
- require 'yajl'
6
-
7
- # Plugin for adding methods for working with time ranges.
8
- #
9
- # == Example
10
- #
11
- # Defining a model class with a timestamptz range:
12
- #
13
- # class ACME::Lease < Sequel::Model(:leases)
14
- # plugin :tstzrange_fields, :active_during
15
- #
16
- # And in the schema:
17
- #
18
- # create_table(:leases) do
19
- # primary_key :id
20
- # tstzrange :active_during
21
- # end
22
- #
23
- # You can use it as follows:
24
- #
25
- # lease = ACME::Lease.new
26
- # lease.active_during_begin = Time.now
27
- # lease.active_during_end = 1.year.from_now
28
- # lease.active_during = 1.year.ago..1.year.from_now
29
- # lease.active_during_end = nil # Unbounded end set
30
- # lease.active_during = nil # Empty set
31
- #
32
- module Sequel
33
- module Plugins
34
- module TstzrangeFields
35
- VERSION = '0.1.1'
36
-
37
- def self.configure(model, *args)
38
- unless model.db.schema_type_class(:tstzrange)
39
- msg = 'tstzrange_fields plugin requires pg_range db extension to be installed. ' \
40
- ' Use db.extension(:pg_range) after the db = Sequel.connect call.'
41
- raise msg
42
- end
43
- args << :period if args.empty?
44
- args = args.flatten
45
-
46
- setup_model(model)
47
-
48
- args.flatten.each do |column|
49
- create_accessors(model, column)
50
- end
51
- end
52
-
53
- def self.setup_model(model)
54
- model.class.define_method(:new_tstzrange) do |b, e|
55
- b = value_to_time(b)
56
- e = value_to_time(e)
57
- return Sequel::Postgres::PGRange.empty(:tstzrange) if b.nil? && e.nil?
58
-
59
- return Sequel::Postgres::PGRange.new(b&.to_time, e&.to_time, db_type: :tstzrange, exclude_end: true)
60
- end
61
-
62
- model.class.define_method(:value_to_time) do |v|
63
- return v if v.nil?
64
- return v if v.respond_to?(:to_time)
65
-
66
- return Time.parse(v)
67
- end
68
- end
69
-
70
- def self.create_accessors(model, column)
71
- get_column_method = column.to_sym
72
- set_column_method = "#{column}=".to_sym
73
- get_begin_method = "#{column}_begin".to_sym
74
- set_begin_method = "#{column}_begin=".to_sym
75
- get_end_method = "#{column}_end".to_sym
76
- set_end_method = "#{column}_end=".to_sym
77
-
78
- model.define_method(get_column_method) do
79
- self[column]
80
- end
81
-
82
- model.define_method(set_column_method) do |value|
83
- case value
84
- when Sequel::Postgres::PGRange
85
- self[column] = value
86
- when Float::INFINITY
87
- range = Sequel::Postgres::PGRange.new(nil, nil, empty: false, db_type: :tstzrange)
88
- self[column] = range
89
- when 'empty'
90
- self[column] = Sequel::Postgres::PGRange.empty(:tstzrange)
91
- else
92
- beg = value.respond_to?(:begin) ? value.begin : (value[:begin] || value['begin'])
93
- en = value.respond_to?(:end) ? value.end : (value[:end] || value['end'])
94
- self[column] = self.class.new_tstzrange(beg, en)
95
- end
96
- end
97
-
98
- model.define_method(get_begin_method) do
99
- send(get_column_method).begin
100
- end
101
-
102
- model.define_method(set_begin_method) do |new_time|
103
- new_range = self.class.new_tstzrange(new_time, send(get_end_method))
104
- send(set_column_method, new_range)
105
- end
106
-
107
- model.define_method(get_end_method) do
108
- r = send(get_column_method)
109
- return r.nil? ? nil : r.end # &.end is invalid syntax
110
- end
111
-
112
- model.define_method(set_end_method) do |new_time|
113
- new_range = self.class.new_tstzrange(send(get_begin_method), new_time)
114
- send(set_column_method, new_range)
115
- end
116
- end
117
- end
118
- end
119
- end
@@ -1,179 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/core_ext/integer/time'
4
- require 'sequel'
5
- require 'sequel/model'
6
- require 'sequel/extensions/pg_range'
7
- require 'sequel/plugins/tstzrange_fields'
8
-
9
- RSpec.describe Sequel::Plugins::TstzrangeFields do
10
- before(:each) do
11
- @db = Sequel.connect('postgres://sequel_tstzrange:sequel_tstzrange@localhost:18101/sequel_tstzrange_test')
12
- @db.extension(:pg_range)
13
- end
14
- after(:each) do
15
- @db.disconnect
16
- end
17
-
18
- it 'errors if the db does not have pg_range registered' do
19
- db = Sequel.connect('postgres://sequel_tstzrange:sequel_tstzrange@localhost:18101/sequel_tstzrange_test')
20
- db.create_table(:tstzrange_fields_test, temp: true) do
21
- primary_key :id
22
- end
23
- expect do
24
- mc = Class.new(Sequel::Model(db[:tstzrange_fields_test]))
25
- mc.plugin(:tstzrange_fields)
26
- end.to raise_error(/tstzrange_fields plugin requires/)
27
- end
28
-
29
- context 'with no fields given' do
30
- let(:model_class) do
31
- @db.create_table(:tstzrange_fields_test, temp: true) do
32
- primary_key :id
33
- tstzrange :period
34
- end
35
- mc = Class.new(Sequel::Model(@db[:tstzrange_fields_test]))
36
- mc.class_eval do
37
- def initialize(*)
38
- super
39
- self[:period] ||= self.class.new_tstzrange(nil, nil)
40
- end
41
- end
42
- mc.plugin(:tstzrange_fields)
43
- mc
44
- end
45
-
46
- let(:model_object) { model_class.new }
47
-
48
- it 'uses :period as the high-level accessor' do
49
- expect(model_object).to respond_to(:period, :period=, :period_begin, :period_begin=, :period_end, :period_end=)
50
- end
51
-
52
- it 'sets a default empty range' do
53
- expect(model_object.period).to be_empty
54
- end
55
- end
56
-
57
- context 'for the given field' do
58
- let(:model_class) do
59
- @db.create_table(:tstzrange_fields_test, temp: true) do
60
- primary_key :id
61
- tstzrange :range
62
- end
63
- mc = Class.new(Sequel::Model(@db[:tstzrange_fields_test]))
64
- mc.plugin(:tstzrange_fields, :range)
65
- mc.class_eval do
66
- def initialize(*)
67
- super
68
- self[:range] ||= self.class.new_tstzrange(nil, nil)
69
- end
70
- end
71
- mc
72
- end
73
-
74
- let(:model_object) { model_class.new }
75
-
76
- let(:t) { Time.at(3.years.ago.to_i) }
77
- let(:ts) { t.to_s }
78
-
79
- it 'sets a default empty range' do
80
- expect(model_object.range).to be_empty
81
- end
82
-
83
- it 'can set an infinite range by assigning the field to Float::INFINITY' do
84
- expect(model_object.range).to be_empty
85
-
86
- model_object.range = Float::INFINITY
87
- expect(model_object.range_begin).to be_nil
88
- expect(model_object.range_end).to be_nil
89
- expect(model_object.range).not_to be_empty
90
- model_object.save_changes
91
- expect(model_class.where(Sequel.function(:lower_inf, :range)).count).to eq(1)
92
- expect(model_class.where(Sequel.function(:upper_inf, :range)).count).to eq(1)
93
- end
94
-
95
- it 'can set an empty range by assigning the field to the string "empty"' do
96
- model_object.range_begin = t
97
- model_object.range_end = t + 1.day
98
- expect(model_object.range).not_to be_empty
99
-
100
- model_object.range = 'empty'
101
- expect(model_object.range).to be_empty
102
- expect(model_object.range_begin).to be_nil
103
- expect(model_object.range_end).to be_nil
104
- model_object.save_changes
105
- expect(model_class.where(Sequel.function(:lower_inf, :range)).count).to eq(0)
106
- expect(model_class.where(Sequel.function(:upper_inf, :range)).count).to eq(0)
107
- end
108
-
109
- it 'can get/set the start' do
110
- model_object.range_begin = t
111
- expect(model_object.range_begin).to eq(t)
112
- expect(model_object.save_changes.refresh.range_begin).to eq(t)
113
-
114
- model_object.range_begin = ts
115
- expect(model_object.range_begin).to eq(t)
116
- expect(model_object.save_changes.refresh.range_begin).to eq(t)
117
-
118
- model_object.range_begin = nil
119
- expect(model_object.range_begin).to be_nil
120
- expect(model_object.save_changes.refresh.range_begin).to be_nil
121
- end
122
-
123
- it 'can get/set the end' do
124
- model_object.range_end = t
125
- expect(model_object.range_end).to eq(t)
126
- expect(model_object.save_changes.refresh.range_end).to eq(t)
127
-
128
- model_object.range_end = ts
129
- expect(model_object.range_end).to eq(t)
130
- expect(model_object.save_changes.refresh.range_end).to eq(t)
131
-
132
- model_object.range_end = nil
133
- expect(model_object.range_end).to be_nil
134
- expect(model_object.save_changes.refresh.range_end).to be_nil
135
- end
136
-
137
- it 'can initialize an instance using accessors' do
138
- o = model_class.create(range_begin: nil, range_end: nil)
139
- expect(o.range).to be_empty
140
-
141
- o = model_class.create(range_begin: Time.now, range_end: 1.hour.from_now)
142
- expect(o.range).not_to be_cover(30.minutes.ago)
143
- expect(o.range).to be_cover(30.minutes.from_now)
144
- expect(o.range).not_to be_cover(90.minutes.from_now)
145
-
146
- o = model_class.create(range_begin: nil, range_end: Time.now)
147
- expect(o.range).to be_cover(30.minutes.ago)
148
- expect(o.range).not_to be_cover(30.minutes.from_now)
149
-
150
- o = model_class.create(range_begin: Time.now, range_end: nil)
151
- expect(o.range).not_to be_cover(30.minutes.ago)
152
- expect(o.range).to be_cover(30.minutes.from_now)
153
- end
154
-
155
- it 'can be assigned to directly with an object with begin/end methods or keys' do
156
- early = 1.day.ago
157
- late = 2.days.from_now
158
-
159
- forms = [
160
- early...late,
161
- OpenStruct.new(begin: early, end: late),
162
- { begin: early, end: late },
163
- { 'begin' => early, 'end' => late }
164
- ]
165
-
166
- forms.each do |value|
167
- model_object.range = value
168
- model_object.save_changes.refresh
169
- expect(model_object.range_begin).to be_within(1).of(early)
170
- expect(model_object.range_end).to be_within(1).of(late)
171
- end
172
-
173
- model_object.range = {}
174
- expect(model_object.range).to be_empty
175
-
176
- expect { model_object.range = 1 }.to raise_error(TypeError)
177
- end
178
- end
179
- end
data/spec/spec_helper.rb DELETED
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'sequel/plugins/tstzrange_fields'
4
-
5
- RSpec.configure do |config|
6
- # config.full_backtrace = true
7
-
8
- # RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 600
9
-
10
- config.expect_with :rspec do |expectations|
11
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
12
- end
13
-
14
- config.mock_with :rspec do |mocks|
15
- mocks.verify_partial_doubles = true
16
- end
17
-
18
- config.order = :random
19
- Kernel.srand config.seed
20
-
21
- config.filter_run :focus
22
- config.run_all_when_everything_filtered = true
23
- config.disable_monkey_patching!
24
- config.default_formatter = 'doc' if config.files_to_run.one?
25
- end