json_schematize 0.6.0 → 0.7.0
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 +4 -4
- data/.circleci/config.yml +10 -183
- data/Gemfile +1 -1
- data/Gemfile.lock +12 -5
- data/LICENSE +21 -0
- data/docker-compose.yml +1 -8
- data/lib/json_schematize/base.rb +5 -3
- data/lib/json_schematize/boolean.rb +12 -10
- data/lib/json_schematize/cache/class_methods/client.rb +71 -0
- data/lib/json_schematize/cache/class_methods/configuration.rb +44 -0
- data/lib/json_schematize/cache/instance_methods.rb +8 -5
- data/lib/json_schematize/cache.rb +6 -4
- data/lib/json_schematize/configuration.rb +85 -0
- data/lib/json_schematize/version.rb +1 -1
- data/lib/json_schematize.rb +23 -1
- metadata +7 -4
- data/lib/json_schematize/cache/class_methods.rb +0 -81
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 332c8451a65d8d3ef3c738e6a06d54407e62d479f6d0f015aa348c01c8c70f03
|
|
4
|
+
data.tar.gz: 534ae0f9dd57ee349c99fa75305370241470afb99ca0273afe98d9b206a9eb57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce9ed85a4db89c977231290127487fde0d703ac527009173d28d0d10a1ced80a43d1febcb8cc3e4dff3b64bd80dc20c2817dd14fe301c478d3169342799f1187
|
|
7
|
+
data.tar.gz: 6eca9b7c49801e97d1393157c8c49a42ffafcb26bcdc103974329c2222ce3f804a496038f1cf8041836170ac251b3e9f977727f99d4bd11edad6de47931b76de
|
data/.circleci/config.yml
CHANGED
|
@@ -1,202 +1,29 @@
|
|
|
1
1
|
version: 2.1
|
|
2
2
|
|
|
3
|
-
# Declare the orbs that we'll use in our config.
|
|
4
|
-
# read more about orbs: https://circleci.com/docs/2.0/using-orbs/
|
|
5
3
|
orbs:
|
|
6
4
|
ruby: circleci/ruby@1.0
|
|
5
|
+
node: circleci/node@2
|
|
6
|
+
cst: cst/framework@1
|
|
7
7
|
|
|
8
|
-
common_envs: &common_envs
|
|
9
|
-
environment:
|
|
10
|
-
APP_BUNDLER_VERSION: "2.3.8"
|
|
11
|
-
REDIS_URL: "redis://127.0.0.1"
|
|
12
|
-
|
|
13
|
-
executors:
|
|
14
|
-
gem:
|
|
15
|
-
parameters:
|
|
16
|
-
ruby-version:
|
|
17
|
-
default: "3.0.0"
|
|
18
|
-
type: string
|
|
19
|
-
docker:
|
|
20
|
-
- image: cimg/ruby:<< parameters.ruby-version >>
|
|
21
|
-
- image: circleci/redis:6.0
|
|
22
|
-
|
|
23
|
-
<<: *common_envs
|
|
24
|
-
|
|
25
|
-
commands:
|
|
26
|
-
bundler-preamble:
|
|
27
|
-
description: "Install ruby and the Gemfile dependencies"
|
|
28
|
-
parameters:
|
|
29
|
-
ruby-version:
|
|
30
|
-
type: string
|
|
31
|
-
default: "3"
|
|
32
|
-
description: "Ruby Gem version"
|
|
33
|
-
key-name:
|
|
34
|
-
type: string
|
|
35
|
-
default: ""
|
|
36
|
-
description: Custom name to add to the cache key
|
|
37
|
-
cache-breaker:
|
|
38
|
-
type: string
|
|
39
|
-
default: "0"
|
|
40
|
-
description: "Cache breaker to force new cache instantiation"
|
|
41
|
-
keep-lock-file:
|
|
42
|
-
type: boolean
|
|
43
|
-
default: false
|
|
44
|
-
description: "Retain lock file when bit is set to true. Otherwise generate a new one specific for this build"
|
|
45
|
-
steps:
|
|
46
|
-
- checkout
|
|
47
|
-
- attach_workspace:
|
|
48
|
-
at: workspace
|
|
49
|
-
- unless:
|
|
50
|
-
condition:
|
|
51
|
-
equal: [ true, << parameters.keep-lock-file >> ]
|
|
52
|
-
steps:
|
|
53
|
-
- run:
|
|
54
|
-
name: Remove Gemfile.lock
|
|
55
|
-
command: rm Gemfile.lock
|
|
56
|
-
- restore_cache:
|
|
57
|
-
key: bundle-<< parameters.ruby-version >>-<< parameters.key-name >>-{{ checksum "Gemfile" }}-<< parameters.cache-breaker >>
|
|
58
|
-
- ruby/install-deps:
|
|
59
|
-
path: vendor/bundle
|
|
60
|
-
with-cache: false
|
|
61
|
-
- run:
|
|
62
|
-
name: "Update dependencies"
|
|
63
|
-
command: bundle update
|
|
64
|
-
- save_cache:
|
|
65
|
-
key: bundle-<< parameters.ruby-version >>-<< parameters.key-name >>-{{ checksum "Gemfile" }}-<< parameters.cache-breaker >>
|
|
66
|
-
paths:
|
|
67
|
-
- vendor/bundle
|
|
68
|
-
|
|
69
|
-
jobs:
|
|
70
|
-
publish-rubygems:
|
|
71
|
-
executor: gem
|
|
72
|
-
steps:
|
|
73
|
-
- bundler-preamble:
|
|
74
|
-
keep-lock-file: true
|
|
75
|
-
- run:
|
|
76
|
-
name: Publish to Ruby Gems
|
|
77
|
-
command: |
|
|
78
|
-
if [ -z "$GEM_HOST_API_KEY" ]; then
|
|
79
|
-
echo 'Environment variable GEM_HOST_API_KEY is not present'
|
|
80
|
-
exit 1
|
|
81
|
-
fi
|
|
82
|
-
gem_output=$(gem build json_schematize.gemspec)
|
|
83
|
-
VERSION=$(printf "$gem_output" | awk '/Version: / {print $2}')
|
|
84
|
-
FILE=$(printf "$gem_output" | awk '/File: / {print $2}')
|
|
85
|
-
|
|
86
|
-
gem push ${FILE}
|
|
87
|
-
|
|
88
|
-
publish-github:
|
|
89
|
-
executor: gem
|
|
90
|
-
steps:
|
|
91
|
-
- bundler-preamble:
|
|
92
|
-
keep-lock-file: true
|
|
93
|
-
- run:
|
|
94
|
-
name: 'Get Go'
|
|
95
|
-
command: |
|
|
96
|
-
sudo apt-get update -qq
|
|
97
|
-
sudo apt-get -y --no-install-recommends install golang-go
|
|
98
|
-
- run:
|
|
99
|
-
name: 'Set Git stats'
|
|
100
|
-
command: |
|
|
101
|
-
git config user.name $GITHUB_USER
|
|
102
|
-
git config user.email $GITHUB_EMAIL
|
|
103
|
-
- run:
|
|
104
|
-
name: Publish Git Release
|
|
105
|
-
command: |
|
|
106
|
-
curl -sSL https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz | tar xz -f - -C . ghr_v0.13.0_linux_amd64/ghr
|
|
107
|
-
mv ghr_v0.13.0_linux_amd64/ghr .
|
|
108
|
-
rm -rf ghr_v0.13.0_linux_amd64
|
|
109
|
-
chmod 0755 ghr
|
|
110
|
-
|
|
111
|
-
if [ -z "$GITHUB_TOKEN" ]; then
|
|
112
|
-
echo 'Environment variable GITHUB_TOKEN is not present'
|
|
113
|
-
exit 1
|
|
114
|
-
fi
|
|
115
|
-
|
|
116
|
-
if [ -z "$GITHUB_USER" ]; then
|
|
117
|
-
echo 'Environment variable GITHUB_USER is not present'
|
|
118
|
-
exit 1
|
|
119
|
-
fi
|
|
120
|
-
|
|
121
|
-
if [ $(git tag -l "$VERSION") ]; then
|
|
122
|
-
echo "Pre existing version $VERSION, not tagging."
|
|
123
|
-
exit 0
|
|
124
|
-
fi
|
|
125
|
-
|
|
126
|
-
gem_output=$(gem build json_schematize.gemspec)
|
|
127
|
-
VERSION=$(printf "$gem_output" | awk '/Version: / {print $2}')
|
|
128
|
-
FILE=$GEM_PATH$(printf "$gem_output" | awk '/File: / {print $2}')
|
|
129
|
-
|
|
130
|
-
git tag -a $VERSION -m "$VERSION"
|
|
131
|
-
|
|
132
|
-
SHA=$(git rev-parse HEAD)
|
|
133
|
-
./ghr -soft -t ${GITHUB_TOKEN} -u ${GITHUB_USER} -r json_schematize -c ${SHA} ${VERSION} ${FILE}
|
|
134
|
-
|
|
135
|
-
test:
|
|
136
|
-
parameters:
|
|
137
|
-
ruby-version:
|
|
138
|
-
default: "3.0.0"
|
|
139
|
-
type: string
|
|
140
|
-
description: "Ruby version to test against"
|
|
141
|
-
executor:
|
|
142
|
-
name: gem
|
|
143
|
-
ruby-version: << parameters.ruby-version >>
|
|
144
|
-
steps:
|
|
145
|
-
- bundler-preamble:
|
|
146
|
-
ruby-version: "<< parameters.ruby-version >>"
|
|
147
|
-
- run:
|
|
148
|
-
name: Setup Climate Control test-reporter
|
|
149
|
-
command: |
|
|
150
|
-
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
151
|
-
chmod +x ./cc-test-reporter
|
|
152
|
-
- run:
|
|
153
|
-
name: Waiting for Redis to be ready
|
|
154
|
-
command: |
|
|
155
|
-
for i in `seq 1 10`;
|
|
156
|
-
do
|
|
157
|
-
nc -z localhost 6379 && echo Success && exit 0
|
|
158
|
-
echo -n .
|
|
159
|
-
sleep 1
|
|
160
|
-
done
|
|
161
|
-
echo Failed waiting for Redis to be available && exit 1
|
|
162
|
-
- run:
|
|
163
|
-
name: Run and Report tests
|
|
164
|
-
command: |
|
|
165
|
-
./cc-test-reporter before-build
|
|
166
|
-
SIMPLE_COV_RUN=true bundle exec rspec --format RspecJunitFormatter --out test-results/rspec/rspec.xml --format progress --color
|
|
167
|
-
- when:
|
|
168
|
-
condition:
|
|
169
|
-
equal:
|
|
170
|
-
[
|
|
171
|
-
required-test-ruby2.7.5,
|
|
172
|
-
required-test-ruby<< parameters.ruby-version >>,
|
|
173
|
-
]
|
|
174
|
-
steps:
|
|
175
|
-
- run:
|
|
176
|
-
name: Report CodeClimate Coverage
|
|
177
|
-
command: ./cc-test-reporter after-build --coverage-input-type simplecov
|
|
178
8
|
workflows:
|
|
179
9
|
version: 2
|
|
180
10
|
yeet-le-jobs:
|
|
181
11
|
jobs:
|
|
182
|
-
-
|
|
12
|
+
- cst/enforce-gem-version-bump
|
|
13
|
+
- cst/rspec-ruby:
|
|
14
|
+
rspec-system-args: "SIMPLE_COV_RUN=true"
|
|
15
|
+
cc-report-collect-ruby: "2.7.5"
|
|
183
16
|
matrix:
|
|
184
17
|
parameters:
|
|
185
18
|
ruby-version: ["2.7.5" , "3.0.0", "3.0.3"]
|
|
186
19
|
alias: required-matrix-tests
|
|
187
|
-
name:
|
|
188
|
-
- publish-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
filters:
|
|
192
|
-
branches:
|
|
193
|
-
only:
|
|
194
|
-
- main
|
|
195
|
-
- publish-rubygems:
|
|
20
|
+
name: test-ruby<< matrix.ruby-version >>
|
|
21
|
+
- cst/publish-gem:
|
|
22
|
+
publish-git: true
|
|
23
|
+
publish-default-gem: true
|
|
196
24
|
requires:
|
|
197
25
|
- required-matrix-tests
|
|
198
26
|
filters:
|
|
199
27
|
branches:
|
|
200
28
|
only:
|
|
201
29
|
- main
|
|
202
|
-
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
json_schematize (0.
|
|
4
|
+
json_schematize (0.7.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
+
activesupport (7.0.2.4)
|
|
10
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
11
|
+
i18n (>= 1.6, < 2)
|
|
12
|
+
minitest (>= 5.1)
|
|
13
|
+
tzinfo (~> 2.0)
|
|
9
14
|
byebug (11.1.3)
|
|
10
15
|
coderay (1.1.3)
|
|
11
|
-
concurrent-ruby (1.1.
|
|
16
|
+
concurrent-ruby (1.1.9)
|
|
12
17
|
diff-lcs (1.5.0)
|
|
13
18
|
docile (1.4.0)
|
|
14
19
|
faker (2.20.0)
|
|
@@ -16,6 +21,7 @@ GEM
|
|
|
16
21
|
i18n (1.10.0)
|
|
17
22
|
concurrent-ruby (~> 1.0)
|
|
18
23
|
method_source (1.0.0)
|
|
24
|
+
minitest (5.15.0)
|
|
19
25
|
pry (0.13.1)
|
|
20
26
|
coderay (~> 1.1)
|
|
21
27
|
method_source (~> 1.0)
|
|
@@ -23,7 +29,6 @@ GEM
|
|
|
23
29
|
byebug (~> 11.0)
|
|
24
30
|
pry (~> 0.13.0)
|
|
25
31
|
rake (12.3.3)
|
|
26
|
-
redis (4.6.0)
|
|
27
32
|
rspec (3.11.0)
|
|
28
33
|
rspec-core (~> 3.11.0)
|
|
29
34
|
rspec-expectations (~> 3.11.0)
|
|
@@ -33,7 +38,7 @@ GEM
|
|
|
33
38
|
rspec-expectations (3.11.0)
|
|
34
39
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
35
40
|
rspec-support (~> 3.11.0)
|
|
36
|
-
rspec-mocks (3.11.
|
|
41
|
+
rspec-mocks (3.11.0)
|
|
37
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
38
43
|
rspec-support (~> 3.11.0)
|
|
39
44
|
rspec-support (3.11.0)
|
|
@@ -45,17 +50,19 @@ GEM
|
|
|
45
50
|
simplecov_json_formatter (~> 0.1)
|
|
46
51
|
simplecov-html (0.12.3)
|
|
47
52
|
simplecov_json_formatter (0.1.4)
|
|
53
|
+
tzinfo (2.0.4)
|
|
54
|
+
concurrent-ruby (~> 1.0)
|
|
48
55
|
|
|
49
56
|
PLATFORMS
|
|
50
57
|
x86_64-linux
|
|
51
58
|
|
|
52
59
|
DEPENDENCIES
|
|
60
|
+
activesupport
|
|
53
61
|
faker
|
|
54
62
|
json_schematize!
|
|
55
63
|
pry
|
|
56
64
|
pry-byebug
|
|
57
65
|
rake (~> 12.0)
|
|
58
|
-
redis
|
|
59
66
|
rspec (~> 3.0)
|
|
60
67
|
rspec_junit_formatter
|
|
61
68
|
simplecov
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Matt Taylor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/docker-compose.yml
CHANGED
data/lib/json_schematize/base.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
module JsonSchematize
|
|
4
|
+
class Base
|
|
5
|
+
def self.acceptable_types
|
|
6
|
+
raise NoMethodError, "Expected acceptable_values to be defined in parent class"
|
|
7
|
+
end
|
|
6
8
|
end
|
|
7
9
|
end
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
require "json_schematize/base"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
module JsonSchematize
|
|
6
|
+
class Boolean < JsonSchematize::Base
|
|
7
|
+
FALSE_VALUES = ["false", "f", "0", false]
|
|
8
|
+
TRUE_VALUES = ["true", "t", "1", true]
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
def self.new(val)
|
|
11
|
+
return false if FALSE_VALUES.include?(val)
|
|
12
|
+
return true if TRUE_VALUES.include?(val)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
raise JsonSchematize::UndefinedBoolean, "#{val} is not a valid #{self.class}"
|
|
15
|
+
end
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
def self.acceptable_types
|
|
18
|
+
[TrueClass, FalseClass]
|
|
19
|
+
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JsonSchematize::Cache::ClassMethods
|
|
4
|
+
module Client
|
|
5
|
+
|
|
6
|
+
def __deserialize_keys__(key_hash_bytes)
|
|
7
|
+
return [{}, 0] if key_hash_bytes.nil?
|
|
8
|
+
|
|
9
|
+
min_expire = Time.now.to_i
|
|
10
|
+
key_hash = Marshal.load(key_hash_bytes)
|
|
11
|
+
keys_removed = 0
|
|
12
|
+
key_hash.each do |key, expire|
|
|
13
|
+
next if expire.to_i > min_expire
|
|
14
|
+
|
|
15
|
+
key_hash.delete(key)
|
|
16
|
+
keys_removed += 1
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
[key_hash, keys_removed]
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
::Kernel.warn("Yikes!! Failed to parse. Returning empty. #{e.message}")
|
|
22
|
+
[{}, 0]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def __update_record_keeper__!(expire:, cache_key:, delete_key: false)
|
|
26
|
+
record_of_truth = cached_keys(with_expire: true)
|
|
27
|
+
if delete_key
|
|
28
|
+
record_of_truth.delete(cache_key)
|
|
29
|
+
else
|
|
30
|
+
record_of_truth[cache_key] = expire
|
|
31
|
+
end
|
|
32
|
+
serialized_string = Marshal.dump(record_of_truth)
|
|
33
|
+
|
|
34
|
+
cache_client.write(cache_namespace, serialized_string)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def __delete_record__!(key)
|
|
38
|
+
__update_record_keeper__!(expire: nil, cache_key: key, delete_key: true)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cached_keys(with_expire: false, count_removed: false)
|
|
42
|
+
raw_string = cache_client.read(cache_namespace)
|
|
43
|
+
key_hash, keys_removed = __deserialize_keys__(raw_string)
|
|
44
|
+
return key_hash if with_expire
|
|
45
|
+
return keys_removed if count_removed
|
|
46
|
+
|
|
47
|
+
key_hash.keys
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def cached_items(key_includes: nil)
|
|
51
|
+
clear_unscored_items! if rand > cache_configuration[:stochastic_cache_bust]
|
|
52
|
+
|
|
53
|
+
cached_keys.map do |key|
|
|
54
|
+
if key_includes
|
|
55
|
+
next unless key.include?(key_includes)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
serialized_string = cache_client.read(key)
|
|
59
|
+
Marshal.load(serialized_string)
|
|
60
|
+
end.compact
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def clear_cache!
|
|
64
|
+
cache_client.delete_multi(([cache_namespace] + cached_keys))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def clear_unscored_items!
|
|
68
|
+
cached_keys(count_removed: true)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JsonSchematize::Cache::ClassMethods
|
|
4
|
+
module Configuration
|
|
5
|
+
def cache_options(key: nil, cache_client: nil, cache_namespace: nil, ttl: nil, update_on_change: nil, stochastic_cache_bust: nil)
|
|
6
|
+
cache_configuration[:key] = key if key
|
|
7
|
+
cache_configuration[:ttl] = ttl if ttl
|
|
8
|
+
cache_configuration[:stochastic_cache_bust] = stochastic_cache_bust if stochastic_cache_bust
|
|
9
|
+
cache_configuration[:update_on_change] = update_on_change if update_on_change
|
|
10
|
+
cache_namespace = cache_configuration[:cache_namespace] = cache_namespace if cache_namespace
|
|
11
|
+
|
|
12
|
+
self.cache_client = cache_configuration[:cache_client] = cache_client if cache_client
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def cache_namespace
|
|
16
|
+
cache_configuration[:cache_namespace] ||= "jss:#{self.name.downcase}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def cache_namespace=(namespace)
|
|
20
|
+
cache_configuration[:cache_namespace] = namespace
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def cache_configuration
|
|
24
|
+
@cache_configuration ||= begin
|
|
25
|
+
{
|
|
26
|
+
cache_client: JsonSchematize.configuration.cache_client,
|
|
27
|
+
cache_namespace: JsonSchematize.configuration.cache_namespace,
|
|
28
|
+
key: JsonSchematize.configuration.cache_key,
|
|
29
|
+
stochastic_cache_bust: JsonSchematize.configuration.cache_stochastic_bust,
|
|
30
|
+
ttl: JsonSchematize.configuration.cache_ttl,
|
|
31
|
+
update_on_change: JsonSchematize.configuration.cache_update_on_change,
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def cache_client=(client)
|
|
37
|
+
cache_configuration[:cache_client] = client
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def cache_client
|
|
41
|
+
cache_configuration[:cache_client].is_a?(Proc) ? cache_configuration[:cache_client].call : cache_configuration[:cache_client]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module JsonSchematize
|
|
2
4
|
module Cache
|
|
3
5
|
module InstanceMethods
|
|
@@ -12,16 +14,17 @@ module JsonSchematize
|
|
|
12
14
|
|
|
13
15
|
def __update_cache_item__(with_delete: true)
|
|
14
16
|
__clear_entry__! if with_delete # needs to get done first in the event the cache_key changes
|
|
15
|
-
client = self.class.
|
|
17
|
+
client = self.class.cache_client
|
|
16
18
|
ttl = self.class.cache_configuration[:ttl].to_i
|
|
17
19
|
score = Time.now.to_i + ttl
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
self.class.__update_record_keeper__!(expire: score, cache_key: __cache_key__)
|
|
21
|
+
|
|
22
|
+
client.write(__cache_key__, Marshal.dump(self), expires_in: ttl)
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
def __clear_entry__!
|
|
23
|
-
self.class.
|
|
24
|
-
self.class.
|
|
26
|
+
self.class.cache_client.delete(__cache_key__)
|
|
27
|
+
self.class.__delete_record__!(__cache_key__)
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
def __cache_key__
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json_schematize/cache/instance_methods"
|
|
4
|
-
require "json_schematize/cache/class_methods"
|
|
4
|
+
require "json_schematize/cache/class_methods/client"
|
|
5
|
+
require "json_schematize/cache/class_methods/configuration"
|
|
5
6
|
|
|
6
7
|
module JsonSchematize
|
|
7
8
|
module Cache
|
|
8
|
-
|
|
9
|
-
raise StandardError, "Yikes! JsonSchematize::Cache Needs Redis to work. Include it as a gem" unless defined?(Redis)
|
|
9
|
+
module ClassMethods; end
|
|
10
10
|
|
|
11
|
+
def self.included(base)
|
|
11
12
|
base.include(JsonSchematize::Cache::InstanceMethods)
|
|
12
|
-
base.extend(JsonSchematize::Cache::ClassMethods)
|
|
13
|
+
base.extend(JsonSchematize::Cache::ClassMethods::Client)
|
|
14
|
+
base.extend(JsonSchematize::Cache::ClassMethods::Configuration)
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JsonSchematize
|
|
4
|
+
class Configuration
|
|
5
|
+
DEFAULT_ONE_MIN = 60 * 60
|
|
6
|
+
DEFAULT_ONE_HOUR = DEFAULT_ONE_MIN * 60
|
|
7
|
+
DEFAULT_ONE_DAY = DEFAULT_ONE_HOUR * 24
|
|
8
|
+
DEFAULT_CACHE_OPTIONS = {
|
|
9
|
+
cache_client: nil,
|
|
10
|
+
cache_key: ->(val, _custom_key) { val.hash },
|
|
11
|
+
cache_namespace: nil,
|
|
12
|
+
cache_stochastic_bust: 0.8,
|
|
13
|
+
cache_ttl: DEFAULT_ONE_DAY,
|
|
14
|
+
cache_update_on_change: true,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
attr_accessor *DEFAULT_CACHE_OPTIONS.keys
|
|
18
|
+
|
|
19
|
+
def initialize
|
|
20
|
+
@cache_client = DEFAULT_CACHE_OPTIONS[:cache_client]
|
|
21
|
+
@cache_key = DEFAULT_CACHE_OPTIONS[:cache_key]
|
|
22
|
+
@cache_namespace = DEFAULT_CACHE_OPTIONS[:cache_namespace]
|
|
23
|
+
@cache_stochastic_bust = DEFAULT_CACHE_OPTIONS[:cache_stochastic_bust]
|
|
24
|
+
@cache_ttl = DEFAULT_CACHE_OPTIONS[:cache_ttl]
|
|
25
|
+
@cache_update_on_change = DEFAULT_CACHE_OPTIONS[:cache_update_on_change]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cache_hash
|
|
29
|
+
DEFAULT_CACHE_OPTIONS.map do |key, value|
|
|
30
|
+
val = public_send(key)
|
|
31
|
+
[key, val]
|
|
32
|
+
end.to_h
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def cache_key=(value)
|
|
36
|
+
if value.is_a? Proc
|
|
37
|
+
@key = value
|
|
38
|
+
return @key
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
assign = _assign_msg_("cache_key", "->(val, cusom_key) { val.hash }", "Default proc to assign cache key")
|
|
42
|
+
msg = "cache_key must be a proc. \n#{assign}"
|
|
43
|
+
raise JsonSchematize::ConfigError, msg
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def cache_client=(client)
|
|
47
|
+
min_required = [:read, :write, :delete_multi, :read_multi]
|
|
48
|
+
min_required.each do |meth|
|
|
49
|
+
next if client.methods.include?(meth)
|
|
50
|
+
|
|
51
|
+
assign = _assign_msg_("cache_client", "_initialized_client_", "Preferably an ActiveSupport::Cache::Store supported client")
|
|
52
|
+
msg = "Passed in client does not accept minimum values. #{min_required} are required methods \n#{assign}"
|
|
53
|
+
raise JsonSchematize::ConfigError, msg
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@cache_client = client
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def cache_client
|
|
61
|
+
return @cache_client unless @cache_client.nil?
|
|
62
|
+
|
|
63
|
+
begin
|
|
64
|
+
Kernel.require 'active_support'
|
|
65
|
+
rescue LoadError
|
|
66
|
+
assign = _assign_msg_("cache_client", "ActiveSupport::Cache::MemoryStore.new", "A ActiveSupport::Cache::Store supported client")
|
|
67
|
+
msg = "Default client missing. Attempted to use 'active_support/cache' but not loaded. \n#{assign}"
|
|
68
|
+
raise JsonSchematize::ConfigError, msg
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
@cache_client = ActiveSupport::Cache::MemoryStore.new
|
|
72
|
+
@cache_client
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def _assign_msg_(key, assignment, comment)
|
|
78
|
+
config = " config.#{key} = #{assignment} # #{comment}"
|
|
79
|
+
"\n\n# Initializer for json_schematize\n" \
|
|
80
|
+
"JsonSchematize.configure do |config|\n" \
|
|
81
|
+
"#{config}\n" \
|
|
82
|
+
"end\n\n"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/json_schematize.rb
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json_schematize/version"
|
|
4
|
+
|
|
3
5
|
require "json_schematize/base"
|
|
4
6
|
require "json_schematize/boolean"
|
|
5
|
-
require "json_schematize/
|
|
7
|
+
require "json_schematize/configuration"
|
|
6
8
|
require "json_schematize/empty_value"
|
|
9
|
+
require "json_schematize/generator"
|
|
7
10
|
require "json_schematize/version"
|
|
8
11
|
|
|
9
12
|
module JsonSchematize
|
|
10
13
|
class Error < StandardError; end
|
|
14
|
+
class ConfigError < StandardError; end
|
|
11
15
|
class FieldError < Error; end
|
|
12
16
|
class InvalidField < Error; end
|
|
13
17
|
class InvalidFieldByValidator < InvalidField; end
|
|
@@ -16,4 +20,22 @@ module JsonSchematize
|
|
|
16
20
|
|
|
17
21
|
## Customized class errors
|
|
18
22
|
class UndefinedBoolean < Error; end
|
|
23
|
+
|
|
24
|
+
def self.configure
|
|
25
|
+
yield configuration if block_given?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.configuration
|
|
29
|
+
@configuration ||= JsonSchematize::Configuration.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.configuration=(object)
|
|
33
|
+
raise ConfigError, "Expected configuration to be a JsonSchematize::Configuration" unless object.is_a?(JsonSchematize::Configuration)
|
|
34
|
+
|
|
35
|
+
@configuration = object
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.cache_client
|
|
39
|
+
configuration.cache_client
|
|
40
|
+
end
|
|
19
41
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json_schematize
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Taylor
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-05-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pry-byebug
|
|
@@ -82,6 +82,7 @@ files:
|
|
|
82
82
|
- Dockerfile
|
|
83
83
|
- Gemfile
|
|
84
84
|
- Gemfile.lock
|
|
85
|
+
- LICENSE
|
|
85
86
|
- Makefile
|
|
86
87
|
- README.md
|
|
87
88
|
- bin/console
|
|
@@ -91,8 +92,10 @@ files:
|
|
|
91
92
|
- lib/json_schematize/base.rb
|
|
92
93
|
- lib/json_schematize/boolean.rb
|
|
93
94
|
- lib/json_schematize/cache.rb
|
|
94
|
-
- lib/json_schematize/cache/class_methods.rb
|
|
95
|
+
- lib/json_schematize/cache/class_methods/client.rb
|
|
96
|
+
- lib/json_schematize/cache/class_methods/configuration.rb
|
|
95
97
|
- lib/json_schematize/cache/instance_methods.rb
|
|
98
|
+
- lib/json_schematize/configuration.rb
|
|
96
99
|
- lib/json_schematize/empty_value.rb
|
|
97
100
|
- lib/json_schematize/field.rb
|
|
98
101
|
- lib/json_schematize/field_transformations.rb
|
|
@@ -121,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
121
124
|
- !ruby/object:Gem::Version
|
|
122
125
|
version: '0'
|
|
123
126
|
requirements: []
|
|
124
|
-
rubygems_version: 3.
|
|
127
|
+
rubygems_version: 3.3.11
|
|
125
128
|
signing_key:
|
|
126
129
|
specification_version: 4
|
|
127
130
|
summary: This gem gives you the ability to turn API results into a standardized schema's
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
module JsonSchematize
|
|
2
|
-
module Cache
|
|
3
|
-
module ClassMethods
|
|
4
|
-
DEFAULT_ONE_MIN = 60 * 60
|
|
5
|
-
DEFAULT_ONE_HOUR = DEFAULT_ONE_MIN * 60
|
|
6
|
-
DEFAULT_ONE_DAY = DEFAULT_ONE_HOUR * 24
|
|
7
|
-
DEFAULT_URL = ENV["CACHE_LAYER_REDIS_URL"] || ENV["REDIS_URL"]
|
|
8
|
-
DEFAULTS = {
|
|
9
|
-
redis_url: DEFAULT_URL,
|
|
10
|
-
ttl: DEFAULT_ONE_DAY,
|
|
11
|
-
key: ->(val, _custom_key) { val.hash },
|
|
12
|
-
update_on_change: true,
|
|
13
|
-
redis_client: ->() { ::Redis.new(url: DEFAULT_URL) },
|
|
14
|
-
stochastic_cache_bust: 0.8,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
def cache_options(key: nil, redis_url: nil, redis_client: nil, cache_namespace: nil, ttl: nil, update_on_change: nil, stochastic_cache_bust: nil)
|
|
18
|
-
cache_configuration[:key] = key if key
|
|
19
|
-
cache_configuration[:ttl] = ttl if ttl
|
|
20
|
-
cache_configuration[:stochastic_cache_bust] = stochastic_cache_bust if stochastic_cache_bust
|
|
21
|
-
cache_configuration[:update_on_change] = update_on_change if update_on_change
|
|
22
|
-
cache_namespace = cache_configuration[:cache_namespace] = cache_namespace if cache_namespace
|
|
23
|
-
|
|
24
|
-
self.redis_client = cache_configuration[:redis_client] = redis_client if redis_client
|
|
25
|
-
self.redis_url = cache_configuration[:redis_url] = redis_url if redis_url
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def cache_namespace
|
|
29
|
-
cache_configuration[:cache_namespace] ||= "jss:#{self.name.downcase}"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def cache_namespace=(namespace)
|
|
33
|
-
cache_configuration[:cache_namespace] = namespace
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def cache_configuration
|
|
37
|
-
@cache_configuration ||= DEFAULTS.clone
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def redis_client=(client)
|
|
41
|
-
cache_configuration[:redis_client] = client
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def redis_url=(url)
|
|
45
|
-
cache_configuration[:redis_url] = url
|
|
46
|
-
cache_configuration[:redis_client] = ::Redis.new(url: url)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def redis_client
|
|
50
|
-
cache_configuration[:redis_client].is_a?(Proc) ? cache_configuration[:redis_client].call : cache_configuration[:redis_client]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def cached_keys
|
|
54
|
-
max_length = Time.now.to_i + cache_configuration[:ttl].to_i + 10
|
|
55
|
-
redis_client.zrangebyscore(cache_namespace, Time.now.to_i, "+inf")
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def cached_items(key_includes: nil)
|
|
59
|
-
clear_unscored_items! if rand > cache_configuration[:stochastic_cache_bust]
|
|
60
|
-
|
|
61
|
-
cached_keys.map do |key|
|
|
62
|
-
if key_includes
|
|
63
|
-
next unless key.include?(key_includes)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
serialized_string = redis_client.get(key)
|
|
67
|
-
Marshal.load(serialized_string)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def clear_cache!
|
|
72
|
-
redis_client.unlink(*cached_keys) if cached_keys.length > 0
|
|
73
|
-
redis_client.unlink(cache_namespace)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def clear_unscored_items!
|
|
77
|
-
redis_client.zremrangebyscore(cache_namespace, "-inf", Time.now.to_i)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|