jason-rails 0.3.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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/client/lib/JasonContext.d.ts +2 -0
- data/client/lib/JasonContext.js +5 -0
- data/client/lib/JasonProvider.d.ts +7 -0
- data/client/lib/JasonProvider.js +109 -0
- data/client/lib/actionFactory.d.ts +5 -0
- data/client/lib/actionFactory.js +33 -0
- data/client/lib/createActions.d.ts +2 -0
- data/client/lib/createActions.js +46 -0
- data/client/lib/createJasonReducers.d.ts +1 -0
- data/client/lib/createJasonReducers.js +36 -0
- data/client/lib/createPayloadHandler.d.ts +1 -0
- data/client/lib/createPayloadHandler.js +87 -0
- data/client/lib/index.d.ts +10 -0
- data/client/lib/index.js +12 -0
- data/client/lib/makeEager.d.ts +1 -0
- data/client/lib/makeEager.js +51 -0
- data/client/lib/useAct.d.ts +1 -0
- data/client/lib/useAct.js +12 -0
- data/client/lib/useSub.d.ts +1 -0
- data/client/lib/useSub.js +14 -0
- data/client/package.json +27 -0
- data/client/src/JasonContext.ts +5 -0
- data/client/src/JasonProvider.tsx +108 -0
- data/client/src/actionFactory.ts +34 -0
- data/client/src/createActions.ts +50 -0
- data/client/src/createJasonReducers.ts +34 -0
- data/client/src/createPayloadHandler.ts +95 -0
- data/client/src/index.ts +7 -0
- data/client/src/makeEager.ts +46 -0
- data/client/src/useAct.ts +9 -0
- data/client/src/useSub.ts +10 -0
- data/client/tsconfig.json +15 -0
- data/client/yarn.lock +140 -0
- data/jason-rails.gemspec +25 -0
- data/lib/jason.rb +10 -0
- data/lib/jason/api_model.rb +47 -0
- data/lib/jason/channel.rb +37 -0
- data/lib/jason/publisher.rb +79 -0
- data/lib/jason/subscription.rb +172 -0
- data/lib/jason/version.rb +3 -0
- metadata +96 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'
|
2
|
+
import pluralize from 'pluralize'
|
3
|
+
import _ from 'lodash'
|
4
|
+
|
5
|
+
function generateSlices(schema) {
|
6
|
+
const sliceNames = schema.map(k => pluralize(k))
|
7
|
+
const adapter = createEntityAdapter()
|
8
|
+
|
9
|
+
return _.fromPairs(_.map(sliceNames, name => {
|
10
|
+
return [name, createSlice({
|
11
|
+
name,
|
12
|
+
initialState: adapter.getInitialState(),
|
13
|
+
reducers: {
|
14
|
+
upsert: adapter.upsertOne,
|
15
|
+
upsertMany: adapter.upsertMany,
|
16
|
+
add: adapter.addOne,
|
17
|
+
setAll: adapter.setAll,
|
18
|
+
remove: adapter.removeOne,
|
19
|
+
movePriority: (s, { payload: { id, priority, parentFilter } }) => {
|
20
|
+
// Get IDs and insert our item at the new index
|
21
|
+
var affectedIds = _.orderBy(_.filter(_.values(s.entities), parentFilter).filter(e => e.id !== id), 'priority').map(e => e.id)
|
22
|
+
affectedIds.splice(priority, 0, id)
|
23
|
+
|
24
|
+
// Apply update
|
25
|
+
affectedIds.forEach((id, i) => (s.entities[id] as any).priority = i)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}).reducer]
|
29
|
+
}))
|
30
|
+
}
|
31
|
+
|
32
|
+
export default function createJasonReducers(schema) {
|
33
|
+
return generateSlices(_.keys(schema))
|
34
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import { apply_patch } from 'jsonpatch'
|
2
|
+
import { camelizeKeys } from 'humps'
|
3
|
+
import pluralize from 'pluralize'
|
4
|
+
import _ from 'lodash'
|
5
|
+
|
6
|
+
function diffSeconds(dt2, dt1) {
|
7
|
+
var diff =(dt2.getTime() - dt1.getTime()) / 1000
|
8
|
+
return Math.abs(Math.round(diff))
|
9
|
+
}
|
10
|
+
|
11
|
+
export default function createPayloadHandler(dispatch, subscription, model, config) {
|
12
|
+
console.log({ model, config })
|
13
|
+
let payload = {}
|
14
|
+
let idx = 0
|
15
|
+
let patchQueue = {}
|
16
|
+
|
17
|
+
let lastCheckAt = new Date()
|
18
|
+
let updateDeadline = null as Date | null
|
19
|
+
let checkInterval
|
20
|
+
|
21
|
+
function getPayload() {
|
22
|
+
console.log({ getPayload: model, subscription })
|
23
|
+
subscription.send({ getPayload: { model, config } })
|
24
|
+
}
|
25
|
+
|
26
|
+
const tGetPayload = _.throttle(getPayload, 10000)
|
27
|
+
|
28
|
+
function dispatchPayload() {
|
29
|
+
const includeModels = (config.includeModels || []).map(m => _.camelCase(m))
|
30
|
+
|
31
|
+
console.log("Dispatching", { payload, includeModels })
|
32
|
+
|
33
|
+
includeModels.forEach(m => {
|
34
|
+
const subPayload = _.flatten(_.compact(camelizeKeys(payload).map(instance => instance[m])))
|
35
|
+
console.log({ type: `${pluralize(m)}/upsertMany`, payload: subPayload })
|
36
|
+
dispatch({ type: `${pluralize(m)}/upsertMany`, payload: subPayload })
|
37
|
+
})
|
38
|
+
|
39
|
+
dispatch({ type: `${pluralize(model)}/upsertMany`, payload: camelizeKeys(payload) })
|
40
|
+
}
|
41
|
+
|
42
|
+
function processQueue() {
|
43
|
+
console.log({ idx, patchQueue })
|
44
|
+
lastCheckAt = new Date()
|
45
|
+
if (patchQueue[idx]) {
|
46
|
+
payload = apply_patch(payload, patchQueue[idx])
|
47
|
+
if (patchQueue[idx]) {
|
48
|
+
dispatchPayload()
|
49
|
+
}
|
50
|
+
delete patchQueue[idx]
|
51
|
+
idx++
|
52
|
+
updateDeadline = null
|
53
|
+
processQueue()
|
54
|
+
// If there are updates in the queue that are ahead of the index, some have arrived out of order
|
55
|
+
// Set a deadline for new updates before it declares the update missing and refetches.
|
56
|
+
} else if (_.keys(patchQueue).length > 0 && !updateDeadline) {
|
57
|
+
var t = new Date()
|
58
|
+
t.setSeconds(t.getSeconds() + 3)
|
59
|
+
updateDeadline = t
|
60
|
+
setTimeout(processQueue, 3100)
|
61
|
+
// If more than 10 updates in queue, or deadline has passed, restart
|
62
|
+
} else if (_.keys(patchQueue).length > 10 || (updateDeadline && diffSeconds(updateDeadline, new Date()) < 0)) {
|
63
|
+
tGetPayload()
|
64
|
+
updateDeadline = null
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
function handlePayload(data) {
|
69
|
+
const { value, idx: newIdx, diff, latency, type } = data
|
70
|
+
console.log({ data })
|
71
|
+
|
72
|
+
if (type === 'payload') {
|
73
|
+
if (!value) return null;
|
74
|
+
|
75
|
+
payload = value
|
76
|
+
dispatchPayload()
|
77
|
+
idx = newIdx + 1
|
78
|
+
// Clear any old changes left in the queue
|
79
|
+
patchQueue= _.pick(patchQueue, _.keys(patchQueue).filter(k => k > newIdx + 1))
|
80
|
+
return
|
81
|
+
}
|
82
|
+
|
83
|
+
patchQueue[newIdx] = diff
|
84
|
+
|
85
|
+
processQueue()
|
86
|
+
|
87
|
+
if (diffSeconds((new Date()), lastCheckAt) >= 3) {
|
88
|
+
lastCheckAt = new Date()
|
89
|
+
console.log('Interval lost. Pulling from server')
|
90
|
+
tGetPayload()
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
return handlePayload
|
95
|
+
}
|
data/client/src/index.ts
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
import pluralize from 'pluralize'
|
2
|
+
import _ from 'lodash'
|
3
|
+
import { useSelector } from 'react-redux'
|
4
|
+
|
5
|
+
export default function (schema) {
|
6
|
+
function addRelations(s, objects, objectType, relations) {
|
7
|
+
// first find out relation name
|
8
|
+
if (_.isArray(relations)) {
|
9
|
+
relations.forEach(relation => {
|
10
|
+
objects = addRelations(s, objects, objectType, relation)
|
11
|
+
})
|
12
|
+
} else if (typeof(relations) === 'object') {
|
13
|
+
const relation = Object.keys(relations)[0]
|
14
|
+
const subRelations = relations[relation]
|
15
|
+
|
16
|
+
objects = addRelations(s, objects, objectType, relation)
|
17
|
+
objects[relation] = addRelations(s, objects[relation], pluralize(relation), subRelations)
|
18
|
+
// #
|
19
|
+
} else if (typeof(relations) === 'string') {
|
20
|
+
const relation = relations
|
21
|
+
if (_.isArray(objects)) {
|
22
|
+
objects = objects.map(obj => addRelations(s, obj, objectType, relation))
|
23
|
+
} else {
|
24
|
+
const relatedObjects = _.values(s[pluralize(relation)].entities)
|
25
|
+
|
26
|
+
if(pluralize.isSingular(relation)) {
|
27
|
+
objects = { ...objects, [relation]: _.find(relatedObjects, { id: objects[relation + 'Id'] }) }
|
28
|
+
} else {
|
29
|
+
objects = { ...objects, [relation]: relatedObjects.filter(e => e[pluralize.singular(objectType) + 'Id'] === objects.id) }
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
return objects
|
35
|
+
}
|
36
|
+
|
37
|
+
function useEager(entity, id = null, relations = []) {
|
38
|
+
if (id) {
|
39
|
+
return useSelector(s => addRelations(s, { ...s[entity].entities[String(id)] }, entity, relations))
|
40
|
+
} else {
|
41
|
+
return useSelector(s => addRelations(s, _.values(s[entity].entities), entity, relations))
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
return useEager
|
46
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"target": "es2015",
|
4
|
+
"module": "es2015",
|
5
|
+
"module": "commonjs",
|
6
|
+
"declaration": true,
|
7
|
+
"outDir": "./lib",
|
8
|
+
"strict": true,
|
9
|
+
"noImplicitAny": false,
|
10
|
+
"jsx": "react",
|
11
|
+
"esModuleInterop": true
|
12
|
+
},
|
13
|
+
"include": ["src"],
|
14
|
+
"exclude": ["node_modules", "**/__tests__/*"]
|
15
|
+
}
|
data/client/yarn.lock
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
2
|
+
# yarn lockfile v1
|
3
|
+
|
4
|
+
|
5
|
+
"@rails/actioncable@^6.0.3-4":
|
6
|
+
version "6.0.3-4"
|
7
|
+
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.3-4.tgz#f17c0ef2235d1624d6052b749005608260bd55ef"
|
8
|
+
integrity sha512-uie5McTpl69vHnXCVzKj7iYpVKFfLuE7aqul/I7MX5zVd+yVyyC/g75T1Q10GofyqHYNYWgPiIxgQIoYPyyeKw==
|
9
|
+
|
10
|
+
axios-case-converter@^0.6.0:
|
11
|
+
version "0.6.0"
|
12
|
+
resolved "https://registry.yarnpkg.com/axios-case-converter/-/axios-case-converter-0.6.0.tgz#7a99120138046ad6faaf1fc2b638fea0fe63f26f"
|
13
|
+
integrity sha512-mlpaFFTBlv+o+NL2YPSWfC8BQv3qUesxTYD0N11/8dgrg0aDbxUaAglromCBI+0NUcfenM42xMGEUhzTtWZqKg==
|
14
|
+
dependencies:
|
15
|
+
camel-case "^4.1.1"
|
16
|
+
header-case "^2.0.3"
|
17
|
+
snake-case "^3.0.3"
|
18
|
+
|
19
|
+
axios@^0.21.0:
|
20
|
+
version "0.21.0"
|
21
|
+
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca"
|
22
|
+
integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==
|
23
|
+
dependencies:
|
24
|
+
follow-redirects "^1.10.0"
|
25
|
+
|
26
|
+
blueimp-md5@^2.18.0:
|
27
|
+
version "2.18.0"
|
28
|
+
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.18.0.tgz#1152be1335f0c6b3911ed9e36db54f3e6ac52935"
|
29
|
+
integrity sha512-vE52okJvzsVWhcgUHOv+69OG3Mdg151xyn41aVQN/5W5S+S43qZhxECtYLAEHMSFWX6Mv5IZrzj3T5+JqXfj5Q==
|
30
|
+
|
31
|
+
camel-case@^4.1.1:
|
32
|
+
version "4.1.2"
|
33
|
+
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
|
34
|
+
integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
|
35
|
+
dependencies:
|
36
|
+
pascal-case "^3.1.2"
|
37
|
+
tslib "^2.0.3"
|
38
|
+
|
39
|
+
capital-case@^1.0.4:
|
40
|
+
version "1.0.4"
|
41
|
+
resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669"
|
42
|
+
integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==
|
43
|
+
dependencies:
|
44
|
+
no-case "^3.0.4"
|
45
|
+
tslib "^2.0.3"
|
46
|
+
upper-case-first "^2.0.2"
|
47
|
+
|
48
|
+
dot-case@^3.0.4:
|
49
|
+
version "3.0.4"
|
50
|
+
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
|
51
|
+
integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
|
52
|
+
dependencies:
|
53
|
+
no-case "^3.0.4"
|
54
|
+
tslib "^2.0.3"
|
55
|
+
|
56
|
+
follow-redirects@^1.10.0:
|
57
|
+
version "1.13.0"
|
58
|
+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
|
59
|
+
integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
|
60
|
+
|
61
|
+
header-case@^2.0.3:
|
62
|
+
version "2.0.4"
|
63
|
+
resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063"
|
64
|
+
integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==
|
65
|
+
dependencies:
|
66
|
+
capital-case "^1.0.4"
|
67
|
+
tslib "^2.0.3"
|
68
|
+
|
69
|
+
humps@^2.0.1:
|
70
|
+
version "2.0.1"
|
71
|
+
resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa"
|
72
|
+
integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=
|
73
|
+
|
74
|
+
jsonpatch@^3.0.1:
|
75
|
+
version "3.0.1"
|
76
|
+
resolved "https://registry.yarnpkg.com/jsonpatch/-/jsonpatch-3.0.1.tgz#97225367c1c3c5bf1641be59b2f73be19759f06f"
|
77
|
+
integrity sha1-lyJTZ8HDxb8WQb5Zsvc74ZdZ8G8=
|
78
|
+
|
79
|
+
lodash@^4.17.20:
|
80
|
+
version "4.17.20"
|
81
|
+
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
82
|
+
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
83
|
+
|
84
|
+
lower-case@^2.0.2:
|
85
|
+
version "2.0.2"
|
86
|
+
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
87
|
+
integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
|
88
|
+
dependencies:
|
89
|
+
tslib "^2.0.3"
|
90
|
+
|
91
|
+
no-case@^3.0.4:
|
92
|
+
version "3.0.4"
|
93
|
+
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
94
|
+
integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
|
95
|
+
dependencies:
|
96
|
+
lower-case "^2.0.2"
|
97
|
+
tslib "^2.0.3"
|
98
|
+
|
99
|
+
pascal-case@^3.1.2:
|
100
|
+
version "3.1.2"
|
101
|
+
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
|
102
|
+
integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
|
103
|
+
dependencies:
|
104
|
+
no-case "^3.0.4"
|
105
|
+
tslib "^2.0.3"
|
106
|
+
|
107
|
+
pluralize@^8.0.0:
|
108
|
+
version "8.0.0"
|
109
|
+
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
|
110
|
+
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
|
111
|
+
|
112
|
+
snake-case@^3.0.3:
|
113
|
+
version "3.0.4"
|
114
|
+
resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c"
|
115
|
+
integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==
|
116
|
+
dependencies:
|
117
|
+
dot-case "^3.0.4"
|
118
|
+
tslib "^2.0.3"
|
119
|
+
|
120
|
+
tslib@^2.0.3:
|
121
|
+
version "2.0.3"
|
122
|
+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
|
123
|
+
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
|
124
|
+
|
125
|
+
typescript@^4.1.2:
|
126
|
+
version "4.1.2"
|
127
|
+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9"
|
128
|
+
integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==
|
129
|
+
|
130
|
+
upper-case-first@^2.0.2:
|
131
|
+
version "2.0.2"
|
132
|
+
resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324"
|
133
|
+
integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==
|
134
|
+
dependencies:
|
135
|
+
tslib "^2.0.3"
|
136
|
+
|
137
|
+
uuid@^8.3.1:
|
138
|
+
version "8.3.1"
|
139
|
+
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
|
140
|
+
integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
|
data/jason-rails.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'lib/jason/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "jason-rails"
|
5
|
+
spec.version = Jason::VERSION
|
6
|
+
spec.authors = ["James Rees"]
|
7
|
+
spec.email = ["jarees@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = "Reactive user interfaces with minimal boilerplate, using Rails + Redux"
|
10
|
+
spec.homepage = "https://github.com/jamesr2323/jason"
|
11
|
+
spec.license = "MIT"
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
13
|
+
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = "https://github.com/jamesr2323/jason"
|
16
|
+
spec.metadata["changelog_uri"] = "https://github.com/jamesr2323/jason"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.executables = []
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
end
|
data/lib/jason.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
class Jason::ApiModel
|
2
|
+
cattr_accessor :models
|
3
|
+
attr_accessor :model, :name
|
4
|
+
|
5
|
+
def self.configure(models)
|
6
|
+
@@models = models
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
@model = OpenStruct.new(JASON_API_MODEL[name.to_sym])
|
12
|
+
end
|
13
|
+
|
14
|
+
def allowed_params
|
15
|
+
model.allowed_params || []
|
16
|
+
end
|
17
|
+
|
18
|
+
def include_models
|
19
|
+
model.include_models || []
|
20
|
+
end
|
21
|
+
|
22
|
+
def include_methods
|
23
|
+
model.include_methods || []
|
24
|
+
end
|
25
|
+
|
26
|
+
def priority_scope
|
27
|
+
model.priority_scope || []
|
28
|
+
end
|
29
|
+
|
30
|
+
def subscribed_fields
|
31
|
+
model.subscribed_fields || []
|
32
|
+
end
|
33
|
+
|
34
|
+
def scope
|
35
|
+
model.scope
|
36
|
+
end
|
37
|
+
|
38
|
+
def as_json_config
|
39
|
+
include_configs = include_models.map do |assoc|
|
40
|
+
reflection = name.classify.constantize.reflect_on_association(assoc.to_sym)
|
41
|
+
api_model = Jason::ApiModel.new(reflection.klass.name.underscore)
|
42
|
+
{ assoc => { only: api_model.subscribed_fields, methods: api_model.include_methods } }
|
43
|
+
end
|
44
|
+
|
45
|
+
{ only: subscribed_fields, include: include_configs, methods: include_methods }
|
46
|
+
end
|
47
|
+
end
|