jason-rails 0.7.1 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e0d37099f467ff5bd4ab868732ce57c53bf055e6ecb8d0f0506bb14ee723d77
4
- data.tar.gz: 6912d141317dbc95edb96bc11ed29235a90fc6dd8575a4dcba18017b81a9964f
3
+ metadata.gz: 592a7eab8028ae28815abbf0d401d98b2ceabc0009f30713f68795da21adb165
4
+ data.tar.gz: 315f5088e258dcab9755dc92f4de03f3f2f016cf6698d3619f022c1e7d601e9d
5
5
  SHA512:
6
- metadata.gz: 3cce0310a94bba9c73237d3d18bcd7aa949fb35905b7dd76c69c05b6d8259f1fc6d0b79da2a01b3db34b372cf438ea96777c14d2bd3bdbfacf9ba27578e81f19
7
- data.tar.gz: f2460fea5f459d24966741cce29855b97b9361a900a848e8655ccdfb4cbaa03aa4d47135b2fa661961f7c8d46d37f5e9bc821ff97a6f5cdd22265f7a8d755758
6
+ metadata.gz: a33fdc1d57462a97b7dd571222ff314cc77338e5172fcfc662f3e1fd5f008deed299abcd870900d0b50805944af822b462f6adee46953895499ce49f69df6680
7
+ data.tar.gz: 8ec1a59761856754f09bb7b6431d3d45d319daf9d4c7f030b8c7c2301c28ab2d0393952c4d7339a4d6310da2689c3cba8c71048deed931e0d3c4b0cf5c2fc2f1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## v0.8.0
2
+ - Cold cache handling:
3
+ - Expiry is now set on all cached models of one week
4
+ - Code now handles case where cached model is missing and repopulates the cache
5
+
6
+ ## v0.7.5
7
+ - Fixed JS errors when payloads arrive on websockets after the subscription has been unmounted
8
+ - Fixed errors during initialization due to calling `cache_all` on a Rails model before it had fully initialized.
9
+
10
+ ## v0.7.3
11
+ - Added: Add JasonContext to exports, for use in scenarios where you need to forward the context into some other React reconciler (e.g. `react-three-fiber`)
12
+ - Fixed: Unneeded `reload` in Publisher resulting in extra database calls
13
+
1
14
  ## v0.7.1
2
15
  - Added: Authorization for REST endpoints. Previously these just inherited logic from ApplicationController. Pass a `update_authorization_service` option to the Jason initializer to use this.
3
16
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- jason-rails (0.7.0)
4
+ jason-rails (0.7.5)
5
5
  connection_pool (>= 2.2.3)
6
6
  jsondiff
7
7
  rails (>= 5)
@@ -89,9 +89,10 @@ GEM
89
89
  marcel (0.3.3)
90
90
  mimemagic (~> 0.3.2)
91
91
  method_source (1.0.0)
92
- mimemagic (0.3.8)
92
+ mimemagic (0.3.10)
93
93
  nokogiri (~> 1)
94
- mini_mime (1.0.2)
94
+ rake
95
+ mini_mime (1.1.0)
95
96
  mini_portile2 (2.5.0)
96
97
  minitest (5.14.3)
97
98
  nio4r (2.5.7)
data/README.md CHANGED
@@ -21,7 +21,7 @@ An alternative way of thinking about Jason is "what if we applied the Flux/Redux
21
21
  Add the gem and the NPM package
22
22
 
23
23
  ```ruby
24
- gem 'jason-rails'
24
+ gem 'jason-rails', require: 'jason'
25
25
  ```
26
26
 
27
27
  ```bash
@@ -52,6 +52,11 @@ Jason.setup do |config|
52
52
  end
53
53
  ```
54
54
 
55
+ Mount the Jason engine in `routes.rb`
56
+ ```ruby
57
+ mount Jason::Engine => "/jason"
58
+ ```
59
+
55
60
  ### In your frontend code
56
61
 
57
62
  First you need to wrap your root component in a `JasonProvider`.
@@ -173,6 +178,15 @@ Development is primarily driven by the needs of projects we're using Jason in. I
173
178
  - Assess using RedisGraph for the graph diffing functionality, to see if this would provide a performance boost
174
179
  - Improve the Typescript definitions (ie remove the abundant `any` typing currently used)
175
180
 
181
+ ## Publishing a new version
182
+ - Update `version.rb`
183
+ - Update CHANGELOG
184
+ - `gem build`
185
+ - `gem push`
186
+ - `npm version [major/minor/patch]`
187
+ - `npm publish`
188
+ - Push new version to Github
189
+
176
190
  ## License
177
191
 
178
192
  The gem, npm package and source code in the git repository are available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
- declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
2
+ declare const JasonProvider: ({ reducers, middleware, enhancers, extraActions, transportOptions, children }: {
3
3
  reducers?: any;
4
4
  middleware?: any;
5
+ enhancers?: any;
5
6
  extraActions?: any;
7
+ transportOptions?: any;
6
8
  children?: React.FC<{}> | undefined;
7
9
  }) => JSX.Element;
8
10
  export default JasonProvider;
@@ -7,8 +7,8 @@ const react_1 = __importDefault(require("react"));
7
7
  const useJason_1 = __importDefault(require("./useJason"));
8
8
  const react_redux_1 = require("react-redux");
9
9
  const JasonContext_1 = __importDefault(require("./JasonContext"));
10
- const JasonProvider = ({ reducers, middleware, extraActions, children }) => {
11
- const [store, value] = useJason_1.default({ reducers, middleware, extraActions });
10
+ const JasonProvider = ({ reducers, middleware, enhancers, extraActions, transportOptions = {}, children }) => {
11
+ const [store, value] = useJason_1.default({ reducers, middleware, enhancers, extraActions, transportOptions });
12
12
  if (!(store && value))
13
13
  return react_1.default.createElement("div", null); // Wait for async fetch of schema to complete
14
14
  return react_1.default.createElement(react_redux_1.Provider, { store: store },
@@ -1,4 +1,4 @@
1
- export default function createTransportAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnect: any): {
1
+ export default function createTransportAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnect: any, transportOptions: any): {
2
2
  getPayload: (config: any, options: any) => void;
3
3
  createSubscription: (config: any) => void;
4
4
  removeSubscription: (config: any) => void;
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const actionCableAdapter_1 = __importDefault(require("./transportAdapters/actionCableAdapter"));
7
7
  const pusherAdapter_1 = __importDefault(require("./transportAdapters/pusherAdapter"));
8
- function createTransportAdapter(jasonConfig, handlePayload, dispatch, onConnect) {
8
+ function createTransportAdapter(jasonConfig, handlePayload, dispatch, onConnect, transportOptions) {
9
9
  const { transportService } = jasonConfig;
10
10
  if (transportService === 'action_cable') {
11
- return actionCableAdapter_1.default(jasonConfig, handlePayload, dispatch, onConnect);
11
+ return actionCableAdapter_1.default(jasonConfig, handlePayload, dispatch, onConnect, transportOptions);
12
12
  }
13
13
  else if (transportService === 'pusher') {
14
14
  return pusherAdapter_1.default(jasonConfig, handlePayload, dispatch);
@@ -2,10 +2,17 @@
2
2
  import _useAct from './useAct';
3
3
  import _useSub from './useSub';
4
4
  import _useEager from './useEager';
5
- export declare const JasonProvider: ({ reducers, middleware, extraActions, children }: {
5
+ export declare const JasonContext: import("react").Context<{
6
+ actions: any;
7
+ subscribe: null;
8
+ eager: (entity: any, id: any, relations: any) => void;
9
+ }>;
10
+ export declare const JasonProvider: ({ reducers, middleware, enhancers, extraActions, transportOptions, children }: {
6
11
  reducers?: any;
7
12
  middleware?: any;
13
+ enhancers?: any;
8
14
  extraActions?: any;
15
+ transportOptions?: any;
9
16
  children?: import("react").FC<{}> | undefined;
10
17
  }) => JSX.Element;
11
18
  export declare const useAct: typeof _useAct;
data/client/lib/index.js CHANGED
@@ -3,11 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.useEager = exports.useSub = exports.useAct = exports.JasonProvider = void 0;
6
+ exports.useEager = exports.useSub = exports.useAct = exports.JasonProvider = exports.JasonContext = void 0;
7
+ const JasonContext_1 = __importDefault(require("./JasonContext"));
7
8
  const JasonProvider_1 = __importDefault(require("./JasonProvider"));
8
9
  const useAct_1 = __importDefault(require("./useAct"));
9
10
  const useSub_1 = __importDefault(require("./useSub"));
10
11
  const useEager_1 = __importDefault(require("./useEager"));
12
+ exports.JasonContext = JasonContext_1.default;
11
13
  exports.JasonProvider = JasonProvider_1.default;
12
14
  exports.useAct = useAct_1.default;
13
15
  exports.useSub = useSub_1.default;
@@ -1,4 +1,4 @@
1
- export default function actionCableAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnected: any): {
1
+ export default function actionCableAdapter(jasonConfig: any, handlePayload: any, dispatch: any, onConnected: any, transportOptions: any): {
2
2
  getPayload: (config: any, options: any) => void;
3
3
  createSubscription: (config: any) => void;
4
4
  removeSubscription: (config: any) => void;
@@ -7,9 +7,10 @@ const actioncable_1 = require("@rails/actioncable");
7
7
  const restClient_1 = __importDefault(require("../restClient"));
8
8
  const uuid_1 = require("uuid");
9
9
  const lodash_1 = __importDefault(require("lodash"));
10
- function actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnected) {
10
+ function actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnected, transportOptions) {
11
11
  const consumerId = uuid_1.v4();
12
- const consumer = actioncable_1.createConsumer();
12
+ const { cableUrl } = transportOptions;
13
+ const consumer = cableUrl ? actioncable_1.createConsumer(cableUrl) : actioncable_1.createConsumer();
13
14
  const subscription = (consumer.subscriptions.create({
14
15
  channel: 'Jason::Channel'
15
16
  }, {
@@ -1,5 +1,7 @@
1
- export default function useJason({ reducers, middleware, extraActions }: {
1
+ export default function useJason({ reducers, middleware, enhancers, transportOptions, extraActions }: {
2
2
  reducers?: any;
3
3
  middleware?: any[];
4
+ enhancers?: any[];
4
5
  extraActions?: any;
6
+ transportOptions?: any;
5
7
  }): any[];
@@ -16,7 +16,7 @@ const humps_1 = require("humps");
16
16
  const blueimp_md5_1 = __importDefault(require("blueimp-md5"));
17
17
  const lodash_1 = __importDefault(require("lodash"));
18
18
  const react_1 = require("react");
19
- function useJason({ reducers, middleware = [], extraActions }) {
19
+ function useJason({ reducers, middleware = [], enhancers = [], transportOptions = {}, extraActions }) {
20
20
  const [store, setStore] = react_1.useState(null);
21
21
  const [value, setValue] = react_1.useState(null);
22
22
  react_1.useEffect(() => {
@@ -28,7 +28,7 @@ function useJason({ reducers, middleware = [], extraActions }) {
28
28
  const serverActionQueue = createServerActionQueue_1.default();
29
29
  const allReducers = Object.assign(Object.assign({}, reducers), createJasonReducers_1.default(schema));
30
30
  console.debug({ allReducers });
31
- const store = toolkit_1.configureStore({ reducer: allReducers, middleware: [...middleware, pruneIdsMiddleware_1.default(schema)] });
31
+ const store = toolkit_1.configureStore({ reducer: allReducers, middleware: [...middleware, pruneIdsMiddleware_1.default(schema)], enhancers });
32
32
  const dispatch = store.dispatch;
33
33
  const optDis = createOptDis_1.default(schema, dispatch, restClient_1.default, serverActionQueue);
34
34
  const actions = createActions_1.default(schema, store, restClient_1.default, optDis, extraActions);
@@ -37,7 +37,7 @@ function useJason({ reducers, middleware = [], extraActions }) {
37
37
  let subOptions = {};
38
38
  function handlePayload(payload) {
39
39
  const { md5Hash } = payload;
40
- const { handlePayload } = payloadHandlers[md5Hash];
40
+ const { handlePayload } = payloadHandlers[md5Hash] || {};
41
41
  if (handlePayload) {
42
42
  handlePayload(payload);
43
43
  }
@@ -45,7 +45,7 @@ function useJason({ reducers, middleware = [], extraActions }) {
45
45
  console.warn("Payload arrived with no handler", payload, payloadHandlers);
46
46
  }
47
47
  }
48
- const transportAdapter = createTransportAdapter_1.default(jasonConfig, handlePayload, dispatch, () => lodash_1.default.keys(configs).forEach(md5Hash => createSubscription(configs[md5Hash], subOptions[md5Hash])));
48
+ const transportAdapter = createTransportAdapter_1.default(jasonConfig, handlePayload, dispatch, () => lodash_1.default.keys(configs).forEach(md5Hash => createSubscription(configs[md5Hash], subOptions[md5Hash])), transportOptions);
49
49
  function createSubscription(config, options = {}) {
50
50
  // We need the hash to be consistent in Ruby / Javascript
51
51
  const hashableConfig = lodash_1.default(Object.assign({ conditions: {}, includes: {} }, config)).toPairs().sortBy(0).fromPairs().value();
data/client/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jamesr2323/jason",
3
- "version": "0.7.1",
3
+ "version": "0.7.5",
4
4
  "module": "./lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "scripts": {
@@ -3,8 +3,8 @@ import useJason from './useJason'
3
3
  import { Provider } from 'react-redux'
4
4
  import JasonContext from './JasonContext'
5
5
 
6
- const JasonProvider = ({ reducers, middleware, extraActions, children }: { reducers?: any, middleware?: any, extraActions?: any, children?: React.FC }) => {
7
- const [store, value] = useJason({ reducers, middleware, extraActions })
6
+ const JasonProvider = ({ reducers, middleware, enhancers, extraActions, transportOptions = {}, children }: { reducers?: any, middleware?: any, enhancers?: any, extraActions?: any, transportOptions?: any, children?: React.FC }) => {
7
+ const [store, value] = useJason({ reducers, middleware, enhancers, extraActions, transportOptions })
8
8
 
9
9
  if(!(store && value)) return <div /> // Wait for async fetch of schema to complete
10
10
 
@@ -1,10 +1,10 @@
1
1
  import actionCableAdapter from './transportAdapters/actionCableAdapter'
2
2
  import pusherAdapter from './transportAdapters/pusherAdapter'
3
3
 
4
- export default function createTransportAdapter(jasonConfig, handlePayload, dispatch, onConnect) {
4
+ export default function createTransportAdapter(jasonConfig, handlePayload, dispatch, onConnect, transportOptions) {
5
5
  const { transportService } = jasonConfig
6
6
  if (transportService === 'action_cable') {
7
- return actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnect)
7
+ return actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnect, transportOptions)
8
8
  } else if (transportService === 'pusher') {
9
9
  return pusherAdapter(jasonConfig, handlePayload, dispatch)
10
10
  } else {
data/client/src/index.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import _JasonContext from './JasonContext'
1
2
  import _JasonProvider from './JasonProvider'
2
3
  import _useAct from './useAct'
3
4
  import _useSub from './useSub'
4
5
  import _useEager from './useEager'
5
6
 
7
+ export const JasonContext = _JasonContext
6
8
  export const JasonProvider = _JasonProvider
7
9
  export const useAct = _useAct
8
10
  export const useSub = _useSub
@@ -3,10 +3,12 @@ import restClient from '../restClient'
3
3
  import { v4 as uuidv4 } from 'uuid'
4
4
  import _ from 'lodash'
5
5
 
6
- export default function actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnected) {
6
+ export default function actionCableAdapter(jasonConfig, handlePayload, dispatch, onConnected, transportOptions) {
7
7
  const consumerId = uuidv4()
8
8
 
9
- const consumer = createConsumer()
9
+ const { cableUrl } = transportOptions
10
+ const consumer = cableUrl ? createConsumer(cableUrl) : createConsumer()
11
+
10
12
  const subscription = (consumer.subscriptions.create({
11
13
  channel: 'Jason::Channel'
12
14
  }, {
@@ -14,7 +14,7 @@ import md5 from 'blueimp-md5'
14
14
  import _ from 'lodash'
15
15
  import React, { useState, useEffect } from 'react'
16
16
 
17
- export default function useJason({ reducers, middleware = [], extraActions }: { reducers?: any, middleware?: any[], extraActions?: any }) {
17
+ export default function useJason({ reducers, middleware = [], enhancers = [], transportOptions = {}, extraActions }: { reducers?: any, middleware?: any[], enhancers?: any[], extraActions?: any, transportOptions?: any }) {
18
18
  const [store, setStore] = useState(null as any)
19
19
  const [value, setValue] = useState(null as any)
20
20
 
@@ -35,7 +35,7 @@ export default function useJason({ reducers, middleware = [], extraActions }: {
35
35
 
36
36
  console.debug({ allReducers })
37
37
 
38
- const store = configureStore({ reducer: allReducers, middleware: [...middleware, pruneIdsMiddleware(schema)] })
38
+ const store = configureStore({ reducer: allReducers, middleware: [...middleware, pruneIdsMiddleware(schema)], enhancers })
39
39
  const dispatch = store.dispatch
40
40
 
41
41
  const optDis = createOptDis(schema, dispatch, restClient, serverActionQueue)
@@ -48,7 +48,7 @@ export default function useJason({ reducers, middleware = [], extraActions }: {
48
48
  function handlePayload(payload) {
49
49
  const { md5Hash } = payload
50
50
 
51
- const { handlePayload } = payloadHandlers[md5Hash]
51
+ const { handlePayload } = payloadHandlers[md5Hash] || {}
52
52
  if (handlePayload) {
53
53
  handlePayload(payload)
54
54
  } else {
@@ -56,7 +56,13 @@ export default function useJason({ reducers, middleware = [], extraActions }: {
56
56
  }
57
57
  }
58
58
 
59
- const transportAdapter = createTransportAdapater(jasonConfig, handlePayload, dispatch, () => _.keys(configs).forEach(md5Hash => createSubscription(configs[md5Hash], subOptions[md5Hash])))
59
+ const transportAdapter = createTransportAdapater(
60
+ jasonConfig,
61
+ handlePayload,
62
+ dispatch,
63
+ () => _.keys(configs).forEach(md5Hash => createSubscription(configs[md5Hash], subOptions[md5Hash])),
64
+ transportOptions
65
+ )
60
66
 
61
67
  function createSubscription(config, options = {}) {
62
68
  // We need the hash to be consistent in Ruby / Javascript
@@ -21,6 +21,10 @@ class Jason::ConsistencyChecker
21
21
  check_all(fix: true)
22
22
  end
23
23
 
24
+ def wipe_all_subs
25
+
26
+ end
27
+
24
28
  def initialize(subscription)
25
29
  @subscription = subscription
26
30
  @inconsistent = false
@@ -1,10 +1,13 @@
1
1
  class Jason::LuaGenerator
2
2
  ## TODO load these scripts and evalsha
3
3
  def cache_json(model_name, id, payload)
4
+ expiry = 7*24*60*60 + rand(6*60*60)
5
+
6
+ # ensure the content expires first
4
7
  cmd = <<~LUA
5
8
  local gidx = redis.call('INCR', 'jason:gidx')
6
- redis.call( 'set', 'jason:cache:' .. ARGV[1] .. ':' .. ARGV[2] .. ':gidx', gidx )
7
- redis.call( 'hset', 'jason:cache:' .. ARGV[1], ARGV[2], ARGV[3] )
9
+ redis.call( 'setex', 'jason:cache:' .. ARGV[1] .. ':' .. ARGV[2] .. ':gidx', #{expiry}, gidx )
10
+ redis.call( 'setex', 'jason:cache:' .. ARGV[1] .. ':' .. ARGV[2], #{expiry - 60}, ARGV[3] )
8
11
  return gidx
9
12
  LUA
10
13
 
@@ -15,15 +18,26 @@ class Jason::LuaGenerator
15
18
  # If value has changed, return old value and new idx. Otherwise do nothing.
16
19
  cmd = <<~LUA
17
20
  local t = {}
18
- local models = {}
21
+ local insts = {}
22
+ local miss_ids = {}
19
23
  local ids = redis.call('smembers', 'jason:subscriptions:' .. ARGV[2] .. ':ids:' .. ARGV[1])
20
24
 
21
25
  for k,id in pairs(ids) do
22
- models[#models+1] = redis.call( 'hget', 'jason:cache:' .. ARGV[1], id)
26
+ local result = redis.call( 'get', 'jason:cache:' .. ARGV[1] .. ':' .. id)
27
+ if (result == false) then
28
+ miss_ids[#miss_ids+1] = id
29
+ else
30
+ insts[#insts+1] = result
31
+ end
23
32
  end
24
33
 
25
- t[#t+1] = models
26
- t[#t+1] = redis.call( 'get', 'jason:subscription:' .. ARGV[2] .. ':' .. ARGV[1] .. ':idx' )
34
+ if next(miss_ids) == nil then
35
+ t[#t+1] = insts
36
+ t[#t+1] = redis.call( 'get', 'jason:subscription:' .. ARGV[2] .. ':' .. ARGV[1] .. ':idx' )
37
+ else
38
+ t[#t+1] = miss_ids
39
+ t[#t+1] = 'missing'
40
+ end
27
41
 
28
42
  return t
29
43
  LUA
@@ -16,7 +16,7 @@ module Jason::Publisher
16
16
 
17
17
  # Exists
18
18
  if self.persisted? && (scope.blank? || self.class.unscoped.send(scope).exists?(self.id))
19
- payload = self.reload.as_json(as_json_config)
19
+ payload = self.as_json(as_json_config)
20
20
  gidx = Jason::LuaGenerator.new.cache_json(self.class.name.underscore, self.id, payload)
21
21
  return [payload, gidx]
22
22
  # Has been destroyed
@@ -124,12 +124,16 @@ module Jason::Publisher
124
124
  end
125
125
 
126
126
  def jason_cached_value
127
- JSON.parse($redis_jason.hget("jason:cache:#{self.class.name.underscore}", id) || '{}')
127
+ JSON.parse($redis_jason.get("jason:cache:#{self.class.name.underscore}:#{id}") || '{}')
128
128
  end
129
129
 
130
130
  class_methods do
131
131
  def cache_all
132
- all.each(&:cache_json)
132
+ all.find_each(&:cache_json)
133
+ end
134
+
135
+ def cache_for(ids)
136
+ where(id: ids).find_each(&:cache_json)
133
137
  end
134
138
 
135
139
  def has_jason?
@@ -399,16 +399,17 @@ class Jason::Subscription
399
399
  end
400
400
 
401
401
  def get_for_model(model_name)
402
- if $redis_jason.sismember("jason:models:#{model_name}:all:subscriptions", id)
403
- instance_jsons_hash, idx = $redis_jason.multi do |r|
404
- r.hgetall("jason:cache:#{model_name}")
405
- r.get("jason:subscription:#{id}:#{model_name}:idx")
406
- end
407
- instance_jsons = instance_jsons_hash.values
408
- else
402
+ instance_jsons, idx = Jason::LuaGenerator.new.get_payload(model_name, id)
403
+ if idx == 'missing'
404
+ # warm cache and then retry
405
+ model_klass(model_name).cache_for(instance_jsons)
409
406
  instance_jsons, idx = Jason::LuaGenerator.new.get_payload(model_name, id)
410
407
  end
411
408
 
409
+ if instance_jsons.any? { |json| json.blank? }
410
+ raise Jason::MissingCacheError
411
+ end
412
+
412
413
  payload = instance_jsons.map do |instance_json|
413
414
  instance_json ? JSON.parse(instance_json) : {}
414
415
  end
@@ -437,7 +438,7 @@ class Jason::Subscription
437
438
 
438
439
  def add(model_name, instance_id)
439
440
  idx = $redis_jason.incr("jason:subscription:#{id}:#{model_name}:idx")
440
- payload = JSON.parse($redis_jason.hget("jason:cache:#{model_name}", instance_id) || '{}')
441
+ payload = JSON.parse($redis_jason.get("jason:cache:#{model_name}:#{instance_id}") || '{}')
441
442
 
442
443
  payload = {
443
444
  id: instance_id,
@@ -479,3 +480,5 @@ class Jason::Subscription
479
480
  broadcaster.broadcast(payload)
480
481
  end
481
482
  end
483
+
484
+ class Jason::MissingCacheError < StandardError; end
data/lib/jason/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jason
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
data/lib/jason.rb CHANGED
@@ -51,7 +51,11 @@ module Jason
51
51
  puts "Old config was #{previous_schema[model]}"
52
52
  puts "New config is #{config}"
53
53
  puts "Rebuilding cache for #{model}"
54
- model.classify.constantize.cache_all
54
+
55
+ # This is necessary to ensure all Rails methods have been added to model before we attempt to cache.
56
+ Rails.configuration.after_initialize do
57
+ model.classify.constantize.cache_all
58
+ end
55
59
  puts "Done"
56
60
  end
57
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jason-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Rees
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-05 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails