sequel-tstzrange-fields 0.3.1 → 0.4.1
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
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e716d56781dee5b6570b4d933c58789e787668c0c6d395b46e2b84baad71767
|
|
4
|
+
data.tar.gz: f3f3adc71237ae2c3f077ad8bdaf7a8b144051e8a6f17b2b9643e7341c7ef258
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b293cd1d78b344123eded05c1120997ae1d40eb82de9c30aa550084b80b8e10568235845fd9b2b7b179cebb0f2171ae69643028e9e0ce392b37dae85fd63400
|
|
7
|
+
data.tar.gz: cd286d73033e03a7a0392381019856cdc89b43f3361a938b3ead0c0d456c26e04d4bcd165efbfba7c4cbeff7b6409e8907170b87368d93fc697ef7fc413aae6f
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sequel"
|
|
4
|
+
require "sequel/model"
|
|
5
|
+
|
|
6
|
+
require_relative "../../sequel_tstzrange_fields/version"
|
|
7
|
+
|
|
8
|
+
# Plugin for adding methods for working with time ranges.
|
|
9
|
+
#
|
|
10
|
+
# == Example
|
|
11
|
+
#
|
|
12
|
+
# Defining a model class with a timestamptz multirange:
|
|
13
|
+
#
|
|
14
|
+
# class Reminder < Sequel::Model(:reminders)
|
|
15
|
+
# plugin :tstzmultirange_fields, :active_during
|
|
16
|
+
#
|
|
17
|
+
# And in the schema:
|
|
18
|
+
#
|
|
19
|
+
# create_table(:reminders) do
|
|
20
|
+
# primary_key :id
|
|
21
|
+
# tstzmultirange :active_during
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# You can use it as follows:
|
|
25
|
+
#
|
|
26
|
+
# r = Reminder.new
|
|
27
|
+
# reminder.active_during = [{begin: Time.now, end: 1.year.from_now}]
|
|
28
|
+
# reminder.active_during = [1.year.ago..1.year.from_now]
|
|
29
|
+
# reminder.active_during = [Time.now..]
|
|
30
|
+
# reminder.active_during = []
|
|
31
|
+
#
|
|
32
|
+
module Sequel
|
|
33
|
+
module Plugins
|
|
34
|
+
module TstzmultirangeFields
|
|
35
|
+
VERSION = SequelTstzrangeFields::VERSION
|
|
36
|
+
|
|
37
|
+
def self.apply(_model, _opts={})
|
|
38
|
+
Sequel.extension :pg_range_ops
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.configure(model, *args)
|
|
42
|
+
SequelTstzrangeFields::Helpers.check_schema_type_available(model.db, :tstzmultirange, :pg_multirange)
|
|
43
|
+
args << :periods if args.empty?
|
|
44
|
+
args = args.flatten
|
|
45
|
+
|
|
46
|
+
setup_model(model)
|
|
47
|
+
model.tstzrange_columns = args
|
|
48
|
+
model.tstzrange_columns.each do |column|
|
|
49
|
+
create_accessors(model, column)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.setup_model(model)
|
|
54
|
+
model.extend(SequelTstzrangeFields::Helpers::ClassMethods)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.create_accessors(model, column)
|
|
58
|
+
get_column_method = column.to_sym
|
|
59
|
+
set_column_method = :"#{column}="
|
|
60
|
+
|
|
61
|
+
model.define_method(get_column_method) do
|
|
62
|
+
self[column]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
model.define_method(set_column_method) do |values|
|
|
66
|
+
values = [values] unless values.respond_to?(:to_ary)
|
|
67
|
+
ranges = values.map { |v| self.class.value_to_tstzrange(v) }
|
|
68
|
+
multirange = Sequel.pg_multirange(ranges, :tstzmultirange)
|
|
69
|
+
self[column] = multirange
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
module ClassMethods
|
|
74
|
+
# The Array of fields which are tstzrange columns.
|
|
75
|
+
attr_accessor :tstzrange_columns
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module DatasetMethods
|
|
79
|
+
# Limit the dataset to the rows where the tstzrange column contains the given value.
|
|
80
|
+
# val is cast into a timestamptz.
|
|
81
|
+
# column is the default/first tstzrange column if not given.
|
|
82
|
+
def tstzrange_contains(val, column: nil)
|
|
83
|
+
column ||= self.model.tstzrange_columns.first
|
|
84
|
+
self.where(Sequel.pg_range(column).contains(Sequel.cast(val, :timestamptz)))
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -4,6 +4,7 @@ require "sequel"
|
|
|
4
4
|
require "sequel/model"
|
|
5
5
|
|
|
6
6
|
require_relative "../../sequel_tstzrange_fields/version"
|
|
7
|
+
require_relative "../../sequel_tstzrange_fields/helpers"
|
|
7
8
|
|
|
8
9
|
# Plugin for adding methods for working with time ranges.
|
|
9
10
|
#
|
|
@@ -40,36 +41,19 @@ module Sequel
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def self.configure(model, *args)
|
|
43
|
-
|
|
44
|
-
msg = "tstzrange_fields plugin requires pg_range db extension to be installed. " \
|
|
45
|
-
"Use db.extension(:pg_range) after the db = Sequel.connect call."
|
|
46
|
-
raise msg
|
|
47
|
-
end
|
|
44
|
+
SequelTstzrangeFields::Helpers.check_schema_type_available(model.db, :tstzrange, :pg_range)
|
|
48
45
|
args << :period if args.empty?
|
|
49
46
|
args = args.flatten
|
|
50
47
|
|
|
51
48
|
setup_model(model)
|
|
52
|
-
model.tstzrange_columns = args
|
|
49
|
+
model.tstzrange_columns = args
|
|
53
50
|
model.tstzrange_columns.each do |column|
|
|
54
51
|
create_accessors(model, column)
|
|
55
52
|
end
|
|
56
53
|
end
|
|
57
54
|
|
|
58
55
|
def self.setup_model(model)
|
|
59
|
-
model.
|
|
60
|
-
b = value_to_time(b)
|
|
61
|
-
e = value_to_time(e)
|
|
62
|
-
return Sequel::Postgres::PGRange.empty(:tstzrange) if b.nil? && e.nil?
|
|
63
|
-
|
|
64
|
-
return Sequel::Postgres::PGRange.new(b&.to_time, e&.to_time, db_type: :tstzrange, exclude_end: true)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
model.class.define_method(:value_to_time) do |v|
|
|
68
|
-
return v if v.nil?
|
|
69
|
-
return v if v.respond_to?(:to_time)
|
|
70
|
-
|
|
71
|
-
return Time.parse(v)
|
|
72
|
-
end
|
|
56
|
+
model.extend(SequelTstzrangeFields::Helpers::ClassMethods)
|
|
73
57
|
end
|
|
74
58
|
|
|
75
59
|
def self.create_accessors(model, column)
|
|
@@ -85,19 +69,7 @@ module Sequel
|
|
|
85
69
|
end
|
|
86
70
|
|
|
87
71
|
model.define_method(set_column_method) do |value|
|
|
88
|
-
|
|
89
|
-
when Sequel::Postgres::PGRange
|
|
90
|
-
self[column] = value
|
|
91
|
-
when Float::INFINITY
|
|
92
|
-
range = Sequel::Postgres::PGRange.new(nil, nil, empty: false, db_type: :tstzrange)
|
|
93
|
-
self[column] = range
|
|
94
|
-
when "empty", nil
|
|
95
|
-
self[column] = Sequel::Postgres::PGRange.empty(:tstzrange)
|
|
96
|
-
else
|
|
97
|
-
beg = value.respond_to?(:begin) ? value.begin : (value[:begin] || value["begin"])
|
|
98
|
-
en = value.respond_to?(:end) ? value.end : (value[:end] || value["end"])
|
|
99
|
-
self[column] = self.class.new_tstzrange(beg, en)
|
|
100
|
-
end
|
|
72
|
+
self[column] = self.class.value_to_tstzrange(value)
|
|
101
73
|
end
|
|
102
74
|
|
|
103
75
|
model.define_method(get_begin_method) do
|
|
@@ -127,13 +99,7 @@ module Sequel
|
|
|
127
99
|
end
|
|
128
100
|
|
|
129
101
|
module DatasetMethods
|
|
130
|
-
|
|
131
|
-
# val is cast into a timestamptz.
|
|
132
|
-
# column is the default/first tstzrange column if not given.
|
|
133
|
-
def tstzrange_contains(val, column: nil)
|
|
134
|
-
column ||= self.model.tstzrange_columns.first
|
|
135
|
-
self.where(Sequel.pg_range(column).contains(Sequel.cast(val, :timestamptz)))
|
|
136
|
-
end
|
|
102
|
+
include SequelTstzrangeFields::Helpers::DatasetMethods
|
|
137
103
|
end
|
|
138
104
|
end
|
|
139
105
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SequelTstzrangeFields::Helpers
|
|
4
|
+
module ClassMethods
|
|
5
|
+
def new_tstzrange(b, e)
|
|
6
|
+
b = value_to_time(b)
|
|
7
|
+
e = value_to_time(e)
|
|
8
|
+
return Sequel::Postgres::PGRange.empty(:tstzrange) if b.nil? && e.nil?
|
|
9
|
+
return Sequel::Postgres::PGRange.new(b&.to_time, e&.to_time, db_type: :tstzrange, exclude_end: true)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def value_to_time(v)
|
|
13
|
+
return v if v.nil?
|
|
14
|
+
return v if v.respond_to?(:to_time)
|
|
15
|
+
return Time.parse(v)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Convert a range-like value into a PGRange.
|
|
19
|
+
# Note that we accept 'start' in addition to 'begin' since this is also very common,
|
|
20
|
+
# and trying to coerce the keys of objects in an array during input
|
|
21
|
+
# can be very annoying.
|
|
22
|
+
def value_to_tstzrange(value)
|
|
23
|
+
case value
|
|
24
|
+
when Sequel::Postgres::PGRange
|
|
25
|
+
return value
|
|
26
|
+
when Float::INFINITY
|
|
27
|
+
range = Sequel::Postgres::PGRange.new(nil, nil, empty: false, db_type: :tstzrange)
|
|
28
|
+
return range
|
|
29
|
+
when "empty", nil
|
|
30
|
+
return Sequel::Postgres::PGRange.empty(:tstzrange)
|
|
31
|
+
else
|
|
32
|
+
beg = if value.respond_to?(:begin)
|
|
33
|
+
value.begin
|
|
34
|
+
elsif value.respond_to?(:start)
|
|
35
|
+
value.start
|
|
36
|
+
else
|
|
37
|
+
value[:begin] || value["begin"] || value[:start] || value["start"]
|
|
38
|
+
end
|
|
39
|
+
en = value.respond_to?(:end) ? value.end : (value[:end] || value["end"])
|
|
40
|
+
return self.new_tstzrange(beg, en)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module DatasetMethods
|
|
46
|
+
# Limit the dataset to the rows where the tstzrange column contains the given value.
|
|
47
|
+
# val is cast into a timestamptz.
|
|
48
|
+
# column is the default/first tstzrange column if not given.
|
|
49
|
+
def tstzrange_contains(val, column: nil)
|
|
50
|
+
column ||= self.model.tstzrange_columns.first
|
|
51
|
+
self.where(Sequel.pg_range(column).contains(Sequel.cast(val, :timestamptz)))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.check_schema_type_available(db, dbtype, ext)
|
|
56
|
+
return if db.schema_type_class(dbtype)
|
|
57
|
+
msg = "plugin requires #{ext} db extension to be installed. " \
|
|
58
|
+
"Use db.extension(:#{ext}) after the db = Sequel.connect call."
|
|
59
|
+
raise TypeError, msg
|
|
60
|
+
end
|
|
61
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sequel-tstzrange-fields
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Lithic Tech
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-07-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pg
|
|
@@ -103,7 +103,9 @@ executables: []
|
|
|
103
103
|
extensions: []
|
|
104
104
|
extra_rdoc_files: []
|
|
105
105
|
files:
|
|
106
|
+
- lib/sequel/plugins/tstzmultirange_fields.rb
|
|
106
107
|
- lib/sequel/plugins/tstzrange_fields.rb
|
|
108
|
+
- lib/sequel_tstzrange_fields/helpers.rb
|
|
107
109
|
- lib/sequel_tstzrange_fields/version.rb
|
|
108
110
|
homepage: https://github.com/lithictech/sequel-tstzrange-fields
|
|
109
111
|
licenses:
|