json_schematize 0.5.2 → 0.6.2
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 -170
- data/CHANGELOG.md +4 -2
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/LICENSE +21 -0
- data/README.md +81 -0
- data/docker-compose.yml +8 -1
- data/lib/json_schematize/base.rb +5 -3
- data/lib/json_schematize/boolean.rb +12 -10
- data/lib/json_schematize/cache/class_methods.rb +81 -0
- data/lib/json_schematize/cache/instance_methods.rb +36 -0
- data/lib/json_schematize/cache.rb +15 -0
- data/lib/json_schematize/generator.rb +15 -0
- data/lib/json_schematize/version.rb +1 -1
- data/lib/json_schematize.rb +2 -0
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51e2681baf728aedcec1f36235ec2c80ba340228da15d8445b64d1f520c0226d
|
|
4
|
+
data.tar.gz: b0423051b51cce86508bc2e554365d7df66f88824124ad0157087e9b11577733
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b84409952c29690b3e9f731dcd4bdf15cf5b63ca494875b319d383640ebd4197f4ec3b59b0d96721d9b6ae26d4784f40a1afbb4ade69911944530f3032a7451e
|
|
7
|
+
data.tar.gz: 786329f8de424b9a83a4eb7ac12884fa1f352f8eef62f4c65fb23b11e5561b10a2a3c204ccaf7cd4adda1988b9ca9bb2576a83df44bbbd8e88acc74a2ed6f710
|
data/.circleci/config.yml
CHANGED
|
@@ -1,189 +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
|
-
|
|
12
|
-
executors:
|
|
13
|
-
gem:
|
|
14
|
-
parameters:
|
|
15
|
-
ruby-version:
|
|
16
|
-
default: "3.0.0"
|
|
17
|
-
type: string
|
|
18
|
-
docker:
|
|
19
|
-
- image: cimg/ruby:<< parameters.ruby-version >>
|
|
20
|
-
<<: *common_envs
|
|
21
|
-
|
|
22
|
-
commands:
|
|
23
|
-
bundler-preamble:
|
|
24
|
-
description: "Install ruby and the Gemfile dependencies"
|
|
25
|
-
parameters:
|
|
26
|
-
ruby-version:
|
|
27
|
-
type: string
|
|
28
|
-
default: "3"
|
|
29
|
-
description: "Ruby Gem version"
|
|
30
|
-
key-name:
|
|
31
|
-
type: string
|
|
32
|
-
default: ""
|
|
33
|
-
description: Custom name to add to the cache key
|
|
34
|
-
cache-breaker:
|
|
35
|
-
type: string
|
|
36
|
-
default: "0"
|
|
37
|
-
description: "Cache breaker to force new cache instantiation"
|
|
38
|
-
keep-lock-file:
|
|
39
|
-
type: boolean
|
|
40
|
-
default: false
|
|
41
|
-
description: "Retain lock file when bit is set to true. Otherwise generate a new one specific for this build"
|
|
42
|
-
steps:
|
|
43
|
-
- checkout
|
|
44
|
-
- attach_workspace:
|
|
45
|
-
at: workspace
|
|
46
|
-
- unless:
|
|
47
|
-
condition:
|
|
48
|
-
equal: [ true, << parameters.keep-lock-file >> ]
|
|
49
|
-
steps:
|
|
50
|
-
- run:
|
|
51
|
-
name: Remove Gemfile.lock
|
|
52
|
-
command: rm Gemfile.lock
|
|
53
|
-
- restore_cache:
|
|
54
|
-
key: bundle-<< parameters.ruby-version >>-<< parameters.key-name >>-{{ checksum "Gemfile" }}-<< parameters.cache-breaker >>
|
|
55
|
-
- ruby/install-deps:
|
|
56
|
-
path: vendor/bundle
|
|
57
|
-
with-cache: false
|
|
58
|
-
- run:
|
|
59
|
-
name: "Update dependencies"
|
|
60
|
-
command: bundle update
|
|
61
|
-
- save_cache:
|
|
62
|
-
key: bundle-<< parameters.ruby-version >>-<< parameters.key-name >>-{{ checksum "Gemfile" }}-<< parameters.cache-breaker >>
|
|
63
|
-
paths:
|
|
64
|
-
- vendor/bundle
|
|
65
|
-
|
|
66
|
-
jobs:
|
|
67
|
-
publish-rubygems:
|
|
68
|
-
executor: gem
|
|
69
|
-
steps:
|
|
70
|
-
- bundler-preamble:
|
|
71
|
-
keep-lock-file: true
|
|
72
|
-
- run:
|
|
73
|
-
name: Publish to Ruby Gems
|
|
74
|
-
command: |
|
|
75
|
-
if [ -z "$GEM_HOST_API_KEY" ]; then
|
|
76
|
-
echo 'Environment variable GEM_HOST_API_KEY is not present'
|
|
77
|
-
exit 1
|
|
78
|
-
fi
|
|
79
|
-
gem_output=$(gem build json_schematize.gemspec)
|
|
80
|
-
VERSION=$(printf "$gem_output" | awk '/Version: / {print $2}')
|
|
81
|
-
FILE=$(printf "$gem_output" | awk '/File: / {print $2}')
|
|
82
|
-
|
|
83
|
-
gem push ${FILE}
|
|
84
|
-
|
|
85
|
-
publish-github:
|
|
86
|
-
executor: gem
|
|
87
|
-
steps:
|
|
88
|
-
- bundler-preamble:
|
|
89
|
-
keep-lock-file: true
|
|
90
|
-
- run:
|
|
91
|
-
name: 'Get Go'
|
|
92
|
-
command: |
|
|
93
|
-
sudo apt-get update -qq
|
|
94
|
-
sudo apt-get -y --no-install-recommends install golang-go
|
|
95
|
-
- run:
|
|
96
|
-
name: 'Set Git stats'
|
|
97
|
-
command: |
|
|
98
|
-
git config user.name $GITHUB_USER
|
|
99
|
-
git config user.email $GITHUB_EMAIL
|
|
100
|
-
- run:
|
|
101
|
-
name: Publish Git Release
|
|
102
|
-
command: |
|
|
103
|
-
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
|
|
104
|
-
mv ghr_v0.13.0_linux_amd64/ghr .
|
|
105
|
-
rm -rf ghr_v0.13.0_linux_amd64
|
|
106
|
-
chmod 0755 ghr
|
|
107
|
-
|
|
108
|
-
if [ -z "$GITHUB_TOKEN" ]; then
|
|
109
|
-
echo 'Environment variable GITHUB_TOKEN is not present'
|
|
110
|
-
exit 1
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
if [ -z "$GITHUB_USER" ]; then
|
|
114
|
-
echo 'Environment variable GITHUB_USER is not present'
|
|
115
|
-
exit 1
|
|
116
|
-
fi
|
|
117
|
-
|
|
118
|
-
if [ $(git tag -l "$VERSION") ]; then
|
|
119
|
-
echo "Pre existing version $VERSION, not tagging."
|
|
120
|
-
exit 0
|
|
121
|
-
fi
|
|
122
|
-
|
|
123
|
-
gem_output=$(gem build json_schematize.gemspec)
|
|
124
|
-
VERSION=$(printf "$gem_output" | awk '/Version: / {print $2}')
|
|
125
|
-
FILE=$GEM_PATH$(printf "$gem_output" | awk '/File: / {print $2}')
|
|
126
|
-
|
|
127
|
-
git tag -a $VERSION -m "$VERSION"
|
|
128
|
-
|
|
129
|
-
SHA=$(git rev-parse HEAD)
|
|
130
|
-
./ghr -soft -t ${GITHUB_TOKEN} -u ${GITHUB_USER} -r json_schematize -c ${SHA} ${VERSION} ${FILE}
|
|
131
|
-
|
|
132
|
-
test:
|
|
133
|
-
parameters:
|
|
134
|
-
ruby-version:
|
|
135
|
-
default: "3.0.0"
|
|
136
|
-
type: string
|
|
137
|
-
description: "Ruby version to test against"
|
|
138
|
-
executor:
|
|
139
|
-
name: gem
|
|
140
|
-
ruby-version: << parameters.ruby-version >>
|
|
141
|
-
steps:
|
|
142
|
-
- bundler-preamble:
|
|
143
|
-
ruby-version: "<< parameters.ruby-version >>"
|
|
144
|
-
- run:
|
|
145
|
-
name: Setup Climate Control test-reporter
|
|
146
|
-
command: |
|
|
147
|
-
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
148
|
-
chmod +x ./cc-test-reporter
|
|
149
|
-
- run:
|
|
150
|
-
name: Run and Report tests
|
|
151
|
-
command: |
|
|
152
|
-
./cc-test-reporter before-build
|
|
153
|
-
SIMPLE_COV_RUN=true bundle exec rspec --format RspecJunitFormatter --out test-results/rspec/rspec.xml --format progress --color
|
|
154
|
-
- when:
|
|
155
|
-
condition:
|
|
156
|
-
equal:
|
|
157
|
-
[
|
|
158
|
-
required-test-ruby2.7.5,
|
|
159
|
-
required-test-ruby<< parameters.ruby-version >>,
|
|
160
|
-
]
|
|
161
|
-
steps:
|
|
162
|
-
- run:
|
|
163
|
-
name: Report CodeClimate Coverage
|
|
164
|
-
command: ./cc-test-reporter after-build --coverage-input-type simplecov
|
|
165
8
|
workflows:
|
|
166
9
|
version: 2
|
|
167
10
|
yeet-le-jobs:
|
|
168
11
|
jobs:
|
|
169
|
-
-
|
|
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"
|
|
170
16
|
matrix:
|
|
171
17
|
parameters:
|
|
172
18
|
ruby-version: ["2.7.5" , "3.0.0", "3.0.3"]
|
|
173
19
|
alias: required-matrix-tests
|
|
174
|
-
name:
|
|
175
|
-
- publish-
|
|
20
|
+
name: test-ruby<< matrix.ruby-version >>
|
|
21
|
+
- cst/publish-gem:
|
|
22
|
+
publish-git: true
|
|
23
|
+
publish-default-gem: true
|
|
176
24
|
requires:
|
|
177
25
|
- required-matrix-tests
|
|
178
26
|
filters:
|
|
179
27
|
branches:
|
|
180
28
|
only:
|
|
181
29
|
- main
|
|
182
|
-
- publish-rubygems:
|
|
183
|
-
requires:
|
|
184
|
-
- required-matrix-tests
|
|
185
|
-
filters:
|
|
186
|
-
branches:
|
|
187
|
-
only:
|
|
188
|
-
- main
|
|
189
|
-
|
data/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
## [0.
|
|
10
|
+
## [0.6.0] - 2021-04-01
|
|
11
11
|
|
|
12
12
|
### Added
|
|
13
|
-
-
|
|
13
|
+
- Caching Layer
|
|
14
14
|
- New feature 2
|
|
15
15
|
|
|
16
16
|
### Changed
|
|
@@ -24,3 +24,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
24
24
|
### Fixed
|
|
25
25
|
- Bug fix 1
|
|
26
26
|
- Bug fix 2
|
|
27
|
+
|
|
28
|
+
[//]: # (Added, Changed, Removed, Fixed are the possible headers for each changlog version)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
json_schematize (0.
|
|
4
|
+
json_schematize (0.6.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -23,6 +23,7 @@ GEM
|
|
|
23
23
|
byebug (~> 11.0)
|
|
24
24
|
pry (~> 0.13.0)
|
|
25
25
|
rake (12.3.3)
|
|
26
|
+
redis (4.6.0)
|
|
26
27
|
rspec (3.11.0)
|
|
27
28
|
rspec-core (~> 3.11.0)
|
|
28
29
|
rspec-expectations (~> 3.11.0)
|
|
@@ -54,6 +55,7 @@ DEPENDENCIES
|
|
|
54
55
|
pry
|
|
55
56
|
pry-byebug
|
|
56
57
|
rake (~> 12.0)
|
|
58
|
+
redis
|
|
57
59
|
rspec (~> 3.0)
|
|
58
60
|
rspec_junit_formatter
|
|
59
61
|
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/README.md
CHANGED
|
@@ -110,6 +110,87 @@ class CustomClasses < JsonSchematize::Generator
|
|
|
110
110
|
end
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
### Caching Adapter
|
|
114
|
+
|
|
115
|
+
JsonSchematize is built to be schema for API results. But what happens when you dont expect the result to change? Introducing the caching layer. This layer lets you cache a `JsonSchematize` object that can be queried from later
|
|
116
|
+
|
|
117
|
+
**Note: This requires redis**
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
class CachedClass < JsonSchematize::Generator
|
|
121
|
+
include JsonSchematize::Cache
|
|
122
|
+
cache_options key: ->(instance_of_cached_class, cache_key_from_initialization) { "#{instance_of_cached_class.id}:#{cache_key_from_initialization}" }
|
|
123
|
+
cache_options ttl: 7.days.to_i
|
|
124
|
+
|
|
125
|
+
schema_default option: :dig_type, value: :string
|
|
126
|
+
|
|
127
|
+
add_field name: :id, type: Integer
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
params = { id: 1 }
|
|
131
|
+
CachedClass.new(cache_key: User.first.id, **params)
|
|
132
|
+
###
|
|
133
|
+
params = { "id" => 1 }
|
|
134
|
+
CachedClass.new(params, cache_key: User.first.id)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### Instance methods for Cache
|
|
138
|
+
```ruby
|
|
139
|
+
# optional cache_key added on initialization: Can be used to customize the cache entry for the instance
|
|
140
|
+
item = CachedClass.new(cache_key: User.first.id, **params)
|
|
141
|
+
|
|
142
|
+
# Update the cached item -- Note: This will overwrite the previous cached item IFF the `__cache_key__` remains the same. This is not gaurenteed
|
|
143
|
+
# Optional Param: with_delete, Default true -- Will attempt to delete the original object
|
|
144
|
+
item.__update_cache_item__
|
|
145
|
+
|
|
146
|
+
# Manually delete the cached entry
|
|
147
|
+
item.__clear_entry__!
|
|
148
|
+
|
|
149
|
+
# Cache key for the item
|
|
150
|
+
item.__cache_key__
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Class methods for Cache
|
|
154
|
+
```ruby
|
|
155
|
+
# Retrieve all cached items for the class. Returns an array of CachedClass objects. Only objects that have not expired via TTL
|
|
156
|
+
# Optional: key_includes: "string_expected_in_cache", default is nil and return everthing
|
|
157
|
+
CachedClass.cached_items
|
|
158
|
+
|
|
159
|
+
# Retrieves all valid object keys from the cache
|
|
160
|
+
CachedClass.cached_keys
|
|
161
|
+
|
|
162
|
+
# Clears all cached items for the given class
|
|
163
|
+
CachedClass.clear_cache!
|
|
164
|
+
|
|
165
|
+
# manually clear objects that have expired
|
|
166
|
+
CachedClass.clear_unscored_items!
|
|
167
|
+
```
|
|
168
|
+
### Cache options
|
|
169
|
+
```ruby
|
|
170
|
+
# [Required] false; [Expect] Proc; [Return] String to be used as instance key; [Default] key will be the hash of the object
|
|
171
|
+
cache_options key: ->(instance_of_class, custom_key) { }
|
|
172
|
+
|
|
173
|
+
# [Required] false; [Expect] String; [Default] ENV["CACHE_LAYER_REDIS_URL"] || ENV["REDIS_URL"]
|
|
174
|
+
cache_options redis_url: _redis_url_value
|
|
175
|
+
|
|
176
|
+
# [Required] false; [Expect] Redis Object or Proc that returns value of Redis Client; [Default] Redis.new(url: redis_url)
|
|
177
|
+
cache_options redis_client: redis_client
|
|
178
|
+
|
|
179
|
+
# [Required] false; [Expect] Object that plays with to_s and has no spaces; [Default] Full class name downcased
|
|
180
|
+
cache_options cache_namespace: cache_namespace
|
|
181
|
+
|
|
182
|
+
# [Required] false; [Expect] Integer in seconds; [Default] 1 day
|
|
183
|
+
cache_options ttl: (60 * 60)
|
|
184
|
+
|
|
185
|
+
# [Required] false; [Expect] Boolean; [Default] true
|
|
186
|
+
# Update the cache when a value has been changed manually
|
|
187
|
+
cache_options update_on_change: true
|
|
188
|
+
|
|
189
|
+
# [Required] false; [Expect] Float; [Default] 0.8
|
|
190
|
+
# Expected value to be between 0 and 1. The sample rate that the class will clear oldcache values on retreival
|
|
191
|
+
cache_options stochastic_cache_bust: 0.8
|
|
192
|
+
```
|
|
193
|
+
|
|
113
194
|
## Development
|
|
114
195
|
|
|
115
196
|
This gem can be developed against local machine or while using docker. Simpleified Docker commands can be found in the `Makefile` or execute `make help`
|
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,81 @@
|
|
|
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.compact
|
|
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
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module JsonSchematize
|
|
2
|
+
module Cache
|
|
3
|
+
module InstanceMethods
|
|
4
|
+
def initialize(stringified_params = nil, cache_key: nil, skip_cache_update: false, raise_on_error: true, **params)
|
|
5
|
+
super(stringified_params, raise_on_error: raise_on_error, **params)
|
|
6
|
+
|
|
7
|
+
@__incoming_cache_key__ = cache_key
|
|
8
|
+
if @values_assigned
|
|
9
|
+
__update_cache_item__(with_delete: false) unless skip_cache_update
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def __update_cache_item__(with_delete: true)
|
|
14
|
+
__clear_entry__! if with_delete # needs to get done first in the event the cache_key changes
|
|
15
|
+
client = self.class.redis_client
|
|
16
|
+
ttl = self.class.cache_configuration[:ttl].to_i
|
|
17
|
+
score = Time.now.to_i + ttl
|
|
18
|
+
client.zadd(__cache_namespace__, score, __cache_key__)
|
|
19
|
+
client.set(__cache_key__, Marshal.dump(self), ex: ttl)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def __clear_entry__!
|
|
23
|
+
self.class.redis_client.zrem(__cache_namespace__, __cache_key__)
|
|
24
|
+
self.class.redis_client.unlink(__cache_key__)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def __cache_key__
|
|
28
|
+
"#{__cache_namespace__}:#{self.class.cache_configuration[:key].call(self, @__incoming_cache_key__)}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def __cache_namespace__
|
|
32
|
+
self.class.cache_namespace
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json_schematize/cache/instance_methods"
|
|
4
|
+
require "json_schematize/cache/class_methods"
|
|
5
|
+
|
|
6
|
+
module JsonSchematize
|
|
7
|
+
module Cache
|
|
8
|
+
def self.included(base)
|
|
9
|
+
raise StandardError, "Yikes! JsonSchematize::Cache Needs Redis to work. Include it as a gem" unless defined?(Redis)
|
|
10
|
+
|
|
11
|
+
base.include(JsonSchematize::Cache::InstanceMethods)
|
|
12
|
+
base.extend(JsonSchematize::Cache::ClassMethods)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json_schematize/cache"
|
|
3
4
|
require "json_schematize/field"
|
|
4
5
|
require "json_schematize/introspect"
|
|
5
6
|
|
|
@@ -58,6 +59,12 @@ class JsonSchematize::Generator
|
|
|
58
59
|
@optional_fields ||= []
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
# def self.update_block(&block)
|
|
63
|
+
# @skip_individual_updates = true
|
|
64
|
+
# yield(cloned)
|
|
65
|
+
# @skip_individual_updates = false
|
|
66
|
+
# end
|
|
67
|
+
|
|
61
68
|
def self.convenience_methods(field:)
|
|
62
69
|
unless self.instance_methods.include?(:"#{field.name}=")
|
|
63
70
|
define_method(:"#{field.name}=") do |value|
|
|
@@ -70,6 +77,7 @@ class JsonSchematize::Generator
|
|
|
70
77
|
return false unless validate_value(**validate_params)
|
|
71
78
|
|
|
72
79
|
instance_variable_set(:"@#{field.name}", value)
|
|
80
|
+
__update_cache__!
|
|
73
81
|
return true
|
|
74
82
|
end
|
|
75
83
|
end
|
|
@@ -99,6 +107,13 @@ class JsonSchematize::Generator
|
|
|
99
107
|
|
|
100
108
|
private
|
|
101
109
|
|
|
110
|
+
def __update_cache__!
|
|
111
|
+
return unless self.class.include?(JsonSchematize::Cache)
|
|
112
|
+
return unless self.class.cache_configuration[:update_on_change]
|
|
113
|
+
|
|
114
|
+
__update_cache_item__
|
|
115
|
+
end
|
|
116
|
+
|
|
102
117
|
def assign_values!
|
|
103
118
|
self.class.fields.each do |field|
|
|
104
119
|
value = field.value_from_field(@__params)[:transformed_value]
|
data/lib/json_schematize.rb
CHANGED
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.6.2
|
|
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-04-09 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
|
|
@@ -90,6 +91,9 @@ files:
|
|
|
90
91
|
- lib/json_schematize.rb
|
|
91
92
|
- lib/json_schematize/base.rb
|
|
92
93
|
- lib/json_schematize/boolean.rb
|
|
94
|
+
- lib/json_schematize/cache.rb
|
|
95
|
+
- lib/json_schematize/cache/class_methods.rb
|
|
96
|
+
- lib/json_schematize/cache/instance_methods.rb
|
|
93
97
|
- lib/json_schematize/empty_value.rb
|
|
94
98
|
- lib/json_schematize/field.rb
|
|
95
99
|
- lib/json_schematize/field_transformations.rb
|
|
@@ -118,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
118
122
|
- !ruby/object:Gem::Version
|
|
119
123
|
version: '0'
|
|
120
124
|
requirements: []
|
|
121
|
-
rubygems_version: 3.2.
|
|
125
|
+
rubygems_version: 3.2.32
|
|
122
126
|
signing_key:
|
|
123
127
|
specification_version: 4
|
|
124
128
|
summary: This gem gives you the ability to turn API results into a standardized schema's
|