picatrix 0.2.0 → 0.5.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/Gemfile.lock +12 -2
- data/README.md +46 -30
- data/Rakefile +1 -0
- data/bin/console +7 -1
- data/definitions/app.proto +47 -0
- data/definitions/mason.proto +63 -0
- data/lib/picatrix/buffy.rb +56 -0
- data/lib/picatrix/cruddy.rb +45 -0
- data/lib/picatrix/digraph_parser.rb +7 -0
- data/lib/picatrix/fixtures/view_submission.rb +19 -0
- data/lib/picatrix/generated/app.pb.rb +79 -0
- data/lib/picatrix/generated/app.rb +171 -60
- data/lib/picatrix/generated/mason/namespaces.json +7 -0
- data/lib/picatrix/generated/mason.pb.rb +90 -0
- data/lib/picatrix/generated/view_submissions.rb +49 -0
- data/lib/picatrix/jenny.rb +30 -155
- data/lib/picatrix/link_relation_index.rb +36 -0
- data/lib/picatrix/pacman.rb +8 -5
- data/lib/picatrix/routes.rb +40 -0
- data/lib/picatrix/templates/app.rb +138 -22
- data/lib/picatrix/templates/control.rb +15 -0
- data/lib/picatrix/templates/type.rb +35 -21
- data/lib/picatrix/transform_to_hash.rb +0 -10
- data/lib/picatrix/version.rb +1 -1
- data/lib/picatrix.rb +22 -1
- data/picatrix.gemspec +2 -0
- metadata +42 -9
- data/lib/picatrix/generated/view_submission.rb +0 -27
- data/lib/picatrix/schemas/view_submission_item.json +0 -12
- data/lib/picatrix/templates/mason/submission_filter_template.json +0 -4
- data/lib/picatrix/templates/mason/view_submission.json +0 -35
- data/lib/picatrix/templates/mason/view_submission_min.json +0 -11
- data/lib/picatrix/templates/mason/view_submissions.json +0 -36
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'sinatra'
|
2
2
|
require 'sinatra/json'
|
3
|
+
require 'protobuf'
|
3
4
|
require 'require_all'
|
4
5
|
|
5
6
|
require_all("./lib/picatrix/generated/*.rb")
|
@@ -8,91 +9,201 @@ class App < Sinatra::Base
|
|
8
9
|
set :public_folder => "public", :static => true
|
9
10
|
|
10
11
|
get '/rels' do
|
11
|
-
json(
|
12
|
+
json({:@controls=>{:up=>"http://localhost:9292/", :self=>"http://localhost:9292/rels"}, :link_relations=>{:newest=>["root -(GET)-> view_submissions", "view_submission -(GET)-> view_submissions", "view_submissions -(DELETE)-> view_submissions"], :":item_id"=>["view_submissions -(GET)-> view_submission"], :filter=>["view_submissions -(GET)-> view_submissions"], :submit=>["view_submissions -(POST)-> view_submission"], :edit=>["view_submission -(PATCH)-> view_submission"]}})
|
12
13
|
end
|
13
14
|
|
14
15
|
get '/' do
|
15
|
-
status, headers, body = call env.merge("PATH_INFO" => "/view_submissions
|
16
|
+
status, headers, body = call env.merge("PATH_INFO" => "/view_submissions")
|
16
17
|
[status, headers, body]
|
17
18
|
end
|
18
19
|
|
20
|
+
def json(hash = {})
|
21
|
+
# anything set here will be sent in all responses
|
22
|
+
super({"@namespaces"=>{"s"=>{"name"=>"http://localhost:9292/rels#"}}}.merge!(hash))
|
23
|
+
end
|
19
24
|
|
20
|
-
|
21
|
-
get "/view_submissions/newest" do
|
22
|
-
# get collection
|
23
|
-
items = ViewSubmission.all
|
24
|
-
# render collection into templates
|
25
|
-
hashed_items = items.collect do |item|
|
26
|
-
{"@controls"=>{"self"=>{"title"=>"submission #{item.id}", "href"=>"http://localhost:9292/view_submission/#{item.id}"}}, "id"=>"#{item.id}", "category"=>"#{item.category}", "photo"=>"#{item.photo}"}
|
27
|
-
end
|
28
|
-
# return that collection
|
29
|
-
json({"title"=>"View submissions", "description"=>"idk yet", "@meta"=>{"@title"=>"Submissions", "@description"=>"This resource represents submissions."}, "@namespaces"=>{"s"=>{"name"=>"http://localhost:9292/rels#"}}, "@controls"=>{"self"=>{"href"=>"http://localhost:9292/view_submissions/newest"}, "s:filter"=>{"href"=>"http://localhost:9292/view_submissions/filter?category={category}&has_photo={has_photo}", "isHrefTemplate"=>true, "title"=>"filter submissions by category", "description"=>"in addition to category, you can ensure the submission has a photo"}, "s:add"=>{"title"=>"add new submission", "encoding"=>"json", "href"=>"http://localhost:9292/submission_add_template/submit", "method"=>"POST", "template"=>{"title"=>"default title", "category"=>"cats", "photo_url"=>"http://cats.com"}}}}.merge({"view_submissions" => hashed_items}))
|
30
|
-
end
|
31
|
-
|
32
25
|
|
33
|
-
|
34
|
-
get "/view_submissions
|
35
|
-
|
36
|
-
|
37
|
-
# render collection into templates
|
38
|
-
hashed_items = items.collect do |item|
|
39
|
-
{"@controls"=>{"self"=>{"title"=>"submission #{item.id}", "href"=>"http://localhost:9292/view_submission/#{item.id}"}}, "id"=>"#{item.id}", "category"=>"#{item.category}", "photo"=>"#{item.photo}"}
|
26
|
+
|
27
|
+
get "/view_submissions" do
|
28
|
+
items = ViewSubmissionsResource.all.collection.collect do |r|
|
29
|
+
r.to_hash
|
40
30
|
end
|
41
|
-
|
42
|
-
|
31
|
+
|
32
|
+
|
33
|
+
controls = send(:filter, ViewSubmissions).call("view_submissions", params)
|
34
|
+
|
35
|
+
|
36
|
+
json(
|
37
|
+
{:@controls => controls}.
|
38
|
+
merge!({"view_submissions" => items})
|
39
|
+
)
|
43
40
|
end
|
44
41
|
|
45
42
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
|
44
|
+
get "/view_submission/:item_id" do
|
45
|
+
item = ViewSubmissionsResource.find(params[:item_id])
|
46
|
+
|
47
|
+
|
48
|
+
controls = send(:mason_self, ViewSubmission).call("view_submission", params)
|
49
|
+
|
50
|
+
|
51
|
+
json(
|
52
|
+
{:@controls => controls}.
|
53
|
+
merge!(item.to_hash.except(:controls))
|
54
|
+
)
|
52
55
|
end
|
53
56
|
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
58
|
+
|
59
|
+
post "/view_submission/:item_id" do
|
60
|
+
item = ViewSubmissionsResource.create(params[:item_id])
|
61
|
+
|
62
|
+
|
63
|
+
controls = {}
|
64
|
+
|
65
|
+
|
66
|
+
json(
|
67
|
+
{:@controls => controls}.
|
68
|
+
merge!(item.to_hash.except(:controls))
|
69
|
+
)
|
65
70
|
end
|
66
71
|
|
67
72
|
|
68
|
-
|
69
|
-
delete "/view_submissions
|
70
|
-
|
71
|
-
|
72
|
-
# render collection into templates
|
73
|
-
hashed_items = items.collect do |item|
|
74
|
-
{"@controls"=>{"self"=>{"title"=>"submission #{item.id}", "href"=>"http://localhost:9292/view_submission/#{item.id}"}}, "id"=>"#{item.id}", "category"=>"#{item.category}", "photo"=>"#{item.photo}"}
|
73
|
+
|
74
|
+
delete "/view_submissions" do
|
75
|
+
items = ViewSubmissionsResource.all.collection.collect do |r|
|
76
|
+
r.to_hash
|
75
77
|
end
|
76
|
-
# return that collection
|
77
|
-
json({"title"=>"View submissions", "description"=>"idk yet", "@meta"=>{"@title"=>"Submissions", "@description"=>"This resource represents submissions."}, "@namespaces"=>{"s"=>{"name"=>"http://localhost:9292/rels#"}}, "@controls"=>{"self"=>{"href"=>"http://localhost:9292/view_submissions/newest"}, "s:filter"=>{"href"=>"http://localhost:9292/view_submissions/filter?category={category}&has_photo={has_photo}", "isHrefTemplate"=>true, "title"=>"filter submissions by category", "description"=>"in addition to category, you can ensure the submission has a photo"}, "s:add"=>{"title"=>"add new submission", "encoding"=>"json", "href"=>"http://localhost:9292/submission_add_template/submit", "method"=>"POST", "template"=>{"title"=>"default title", "category"=>"cats", "photo_url"=>"http://cats.com"}}}, :message=>0}.merge({"view_submissions" => hashed_items}))
|
78
|
-
end
|
79
|
-
|
80
78
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
79
|
+
|
80
|
+
controls = {}
|
81
|
+
|
82
|
+
|
83
|
+
json(
|
84
|
+
{:@controls => controls}.
|
85
|
+
merge!({"view_submissions" => items})
|
86
|
+
)
|
87
87
|
end
|
88
88
|
|
89
89
|
|
90
90
|
|
91
|
+
patch "/view_submission/:item_id" do
|
92
|
+
item = ViewSubmissionsResource.find(params[:item_id])
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
94
|
+
|
95
|
+
controls = send(:edit, ViewSubmission).call("view_submission", params)
|
96
|
+
|
97
|
+
|
98
|
+
json(
|
99
|
+
{:@controls => controls}.
|
100
|
+
merge!(item.to_hash.except(:controls))
|
101
|
+
)
|
96
102
|
end
|
103
|
+
|
97
104
|
|
105
|
+
|
106
|
+
def mason_up(type)
|
107
|
+
if type == collection
|
108
|
+
proc do |path, params|
|
109
|
+
{
|
110
|
+
up: Mason::Up.new(
|
111
|
+
{
|
112
|
+
href: "http://localhost:9292/#{view_submissions}"
|
113
|
+
}
|
114
|
+
).to_hash
|
115
|
+
}
|
116
|
+
end
|
117
|
+
else
|
118
|
+
proc do |path, params|
|
119
|
+
{
|
120
|
+
up: Mason::Up.new(
|
121
|
+
{
|
122
|
+
href: "http://localhost:9292/#{path}"
|
123
|
+
}
|
124
|
+
).to_hash
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
def mason_self(item)
|
130
|
+
proc do |path, params|
|
131
|
+
if params[:item_id]
|
132
|
+
{
|
133
|
+
self: Mason::Self.new(
|
134
|
+
{
|
135
|
+
href: "http://localhost:9292/#{path}/#{params[:item_id]}"
|
136
|
+
}
|
137
|
+
).to_hash
|
138
|
+
}
|
139
|
+
else
|
140
|
+
{
|
141
|
+
self: Mason::Self.new(
|
142
|
+
{
|
143
|
+
href: "http://localhost:9292/#{path}"
|
144
|
+
}
|
145
|
+
).to_hash
|
146
|
+
}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
def edit(item)
|
151
|
+
proc do |path, params|
|
152
|
+
{
|
153
|
+
edit: ("Edit" + item.to_s.singularize.camelize).constantize.new(
|
154
|
+
{
|
155
|
+
form: Mason::Edit.new(
|
156
|
+
href: "http://localhost:9292/#{path}/#{params[:item_id]}"
|
157
|
+
)
|
158
|
+
}
|
159
|
+
).to_hash
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
def remove(item)
|
164
|
+
proc do |path, params|
|
165
|
+
{
|
166
|
+
remove: Mason::Remove.new(
|
167
|
+
{
|
168
|
+
href: "http://localhost:9292/#{path}/#{params[:item_id]}"
|
169
|
+
}
|
170
|
+
).to_hash
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
def create(item)
|
175
|
+
proc do |path, params|
|
176
|
+
{
|
177
|
+
create: ("Create" + item.to_s.singularize.camelize).constantize.new(
|
178
|
+
{
|
179
|
+
form: Mason::Create.new(
|
180
|
+
href: ""
|
181
|
+
)
|
182
|
+
}
|
183
|
+
)
|
184
|
+
}
|
185
|
+
end
|
186
|
+
end
|
187
|
+
def filter(collection)
|
188
|
+
# TODO this prob cant really work here
|
189
|
+
proc do |path, params|
|
190
|
+
if params[:item_id]
|
191
|
+
{
|
192
|
+
"s:filter": Mason::Filter.new(
|
193
|
+
{
|
194
|
+
href: "http://localhost:9292/#{path}/#{params[:item_id]}"
|
195
|
+
}
|
196
|
+
).to_hash
|
197
|
+
}
|
198
|
+
else
|
199
|
+
{
|
200
|
+
"s:filter": Mason::Filter.new(
|
201
|
+
{
|
202
|
+
href: "http://localhost:9292/#{path}"
|
203
|
+
}
|
204
|
+
).to_hash
|
205
|
+
}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
98
209
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# This file is auto-generated. DO NOT EDIT!
|
5
|
+
#
|
6
|
+
require 'protobuf/message'
|
7
|
+
|
8
|
+
module Mason
|
9
|
+
|
10
|
+
##
|
11
|
+
# Enum Classes
|
12
|
+
#
|
13
|
+
class HTTPVerb < ::Protobuf::Enum
|
14
|
+
define :GET, 1
|
15
|
+
define :PUT, 2
|
16
|
+
define :PATCH, 3
|
17
|
+
define :DELETE, 4
|
18
|
+
define :POST, 5
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
##
|
23
|
+
# Message Classes
|
24
|
+
#
|
25
|
+
class Self < ::Protobuf::Message; end
|
26
|
+
class Up < ::Protobuf::Message; end
|
27
|
+
class Filter < ::Protobuf::Message
|
28
|
+
class HrefTemplate < ::Protobuf::Enum
|
29
|
+
define :TRUE, 0
|
30
|
+
define :FALSE, 1
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class Create < ::Protobuf::Message; end
|
36
|
+
class Edit < ::Protobuf::Message; end
|
37
|
+
class Remove < ::Protobuf::Message; end
|
38
|
+
class Controls < ::Protobuf::Message; end
|
39
|
+
|
40
|
+
|
41
|
+
##
|
42
|
+
# Message Fields
|
43
|
+
#
|
44
|
+
class Self
|
45
|
+
optional :string, :href, 1
|
46
|
+
optional :string, :title, 2
|
47
|
+
end
|
48
|
+
|
49
|
+
class Up
|
50
|
+
optional :string, :href, 1
|
51
|
+
optional :string, :title, 2
|
52
|
+
end
|
53
|
+
|
54
|
+
class Filter
|
55
|
+
optional :string, :href, 1
|
56
|
+
optional ::Mason::HTTPVerb, :method, 2, :default => ::Mason::HTTPVerb::GET
|
57
|
+
optional ::Mason::Filter::HrefTemplate, :isHrefTemplate, 3, :default => ::Mason::Filter::HrefTemplate::TRUE
|
58
|
+
end
|
59
|
+
|
60
|
+
class Create
|
61
|
+
optional :string, :href, 1
|
62
|
+
optional ::Mason::HTTPVerb, :method, 2, :default => ::Mason::HTTPVerb::POST
|
63
|
+
optional :string, :title, 3
|
64
|
+
optional :string, :encoding, 4
|
65
|
+
end
|
66
|
+
|
67
|
+
class Edit
|
68
|
+
optional :string, :href, 1
|
69
|
+
optional ::Mason::HTTPVerb, :method, 2, :default => ::Mason::HTTPVerb::PATCH
|
70
|
+
optional :string, :title, 3
|
71
|
+
optional :string, :encoding, 4
|
72
|
+
end
|
73
|
+
|
74
|
+
class Remove
|
75
|
+
optional :string, :href, 1
|
76
|
+
optional ::Mason::HTTPVerb, :method, 2, :default => ::Mason::HTTPVerb::DELETE
|
77
|
+
optional :string, :title, 3
|
78
|
+
end
|
79
|
+
|
80
|
+
class Controls
|
81
|
+
optional ::Mason::Self, :self, 2
|
82
|
+
optional ::Mason::Up, :up, 3
|
83
|
+
optional ::Mason::Edit, :edit, 4
|
84
|
+
optional ::Mason::Remove, :remove, 5
|
85
|
+
optional ::Mason::Create, :create, 6
|
86
|
+
optional ::Mason::Filter, :filter, 7
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# you can remove this if you don't use faker
|
2
|
+
# for your fixture data
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
# the resource is the thing actually persisted
|
6
|
+
# technically, this is just an interface to it
|
7
|
+
# so long as your persistance layer is able to implement
|
8
|
+
# the methods in this fixture, the app will generate
|
9
|
+
class ViewSubmissionsResource
|
10
|
+
# method used to return single item from a collection
|
11
|
+
# creates an instance on the fly
|
12
|
+
# both the find and collection methods use this
|
13
|
+
def self.create(item_id)
|
14
|
+
ViewSubmission.new(
|
15
|
+
{
|
16
|
+
# any "bare" Proto type will be given an associated Faker
|
17
|
+
|
18
|
+
:id => id = Faker::Number.number(6),
|
19
|
+
|
20
|
+
:category => Faker::Lorem.word,
|
21
|
+
|
22
|
+
:photo => Faker::Lorem.word,
|
23
|
+
|
24
|
+
:controls => ViewSubmission::Controls.new(minimal_controls_for(item_id)),
|
25
|
+
|
26
|
+
:attachments => [ViewSubmission::Attachment.new(params = {})],
|
27
|
+
|
28
|
+
}
|
29
|
+
)
|
30
|
+
end
|
31
|
+
def self.find(params)
|
32
|
+
self.create(params)
|
33
|
+
end
|
34
|
+
def self.all
|
35
|
+
collection = []
|
36
|
+
rand(10).times {
|
37
|
+
collection << self.find(rand(1000))
|
38
|
+
}
|
39
|
+
ViewSubmissions.new(collection: collection)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.minimal_controls_for(item_id)
|
43
|
+
host = "http://localhost:9292"
|
44
|
+
{
|
45
|
+
self: Mason::Self.new(href: "#{host}/view_submission/#{item_id}"),
|
46
|
+
up: Mason::Up.new(href: "#{host}/view_submissions")
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
data/lib/picatrix/jenny.rb
CHANGED
@@ -7,184 +7,59 @@ module Picatrix
|
|
7
7
|
include Thor::Actions
|
8
8
|
|
9
9
|
attr_accessor :app_name, :routes, :root_path, :rels,
|
10
|
-
:destination_stack, :options
|
11
|
-
:default_response, :assets, :generated,
|
12
|
-
:addressable_items, :collectable_items
|
10
|
+
:destination_stack, :options
|
13
11
|
|
14
12
|
argument :name
|
15
13
|
source_root File.dirname(__FILE__)
|
16
14
|
|
17
|
-
def initialize(
|
15
|
+
def initialize(pacman, options = {}, app_name = "app")
|
18
16
|
# thor related
|
19
17
|
@options = options
|
20
18
|
@destination_stack = [self.class.source_root]
|
21
19
|
|
22
|
-
|
23
|
-
@
|
24
|
-
@edges = hash[:edge].flat_map {|e| e[:edge]}
|
20
|
+
@nodes = pacman.nodes
|
21
|
+
@edges = pacman.edges
|
25
22
|
|
26
23
|
@app_name = app_name
|
27
|
-
@rels = @edges
|
28
|
-
|
24
|
+
@rels = LinkRelationIndex.new(@edges).masoned
|
25
|
+
# TODO
|
26
|
+
@meta = {}
|
27
|
+
|
28
|
+
if File.exist?(
|
29
|
+
mason_path = "lib/picatrix/generated/mason/namespaces.json"
|
30
|
+
) #TODO this should be coming in from graph instead
|
31
|
+
@namespaces = JSON.parse(
|
32
|
+
File.read(
|
33
|
+
mason_path
|
34
|
+
)
|
35
|
+
)
|
36
|
+
@prefix = "#{@namespaces["@namespaces"].keys.first}:"
|
37
|
+
else
|
38
|
+
puts "no generated/mason/namespaces.json file"
|
39
|
+
@namespaces = {}
|
40
|
+
@prefix = ""
|
41
|
+
end
|
29
42
|
|
30
|
-
@
|
31
|
-
@
|
32
|
-
#
|
33
|
-
@
|
34
|
-
@collectable_items = collectable_items
|
35
|
-
@routes = routes
|
43
|
+
@control_templates = Cruddy.new(@edges).controls
|
44
|
+
@routes = Routes.new(@edges, @control_templates)
|
45
|
+
# make this available to the app scope
|
46
|
+
@root_path = @routes.root_path
|
36
47
|
end
|
37
48
|
|
38
49
|
def just_do_it
|
39
|
-
@generated.each do |node_name|
|
40
|
-
# bring in defined objects
|
41
|
-
require "./lib/picatrix/generated/#{node_name}.rb"
|
42
|
-
end
|
43
|
-
generate_app_file
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
def generate_app_file
|
48
50
|
template(
|
49
51
|
'templates/app.rb',
|
50
52
|
File.join("generated/#{app_name}.rb")
|
51
53
|
)
|
52
54
|
end
|
53
|
-
def assets
|
54
|
-
@assets ||= @edges.collect do | edge|
|
55
|
-
source = edge.keys.first
|
56
|
-
properties = edge[source]
|
57
|
-
# if you dont have an inline asset, ignore
|
58
|
-
next unless properties[:inline]
|
59
|
-
|
60
|
-
mason_path = "lib/picatrix/templates/mason/#{properties[:target]}.json"
|
61
|
-
|
62
|
-
if File.exist?(mason_path)
|
63
|
-
body = JSON.parse(
|
64
|
-
File.read(
|
65
|
-
mason_path
|
66
|
-
)
|
67
|
-
)
|
68
|
-
else
|
69
|
-
body = default_response
|
70
|
-
end
|
71
|
-
{
|
72
|
-
"#{properties[:target]}" => body
|
73
|
-
}
|
74
|
-
end.compact.reduce({}, :merge)
|
75
|
-
end
|
76
|
-
def routes
|
77
|
-
@routes ||= @edges.collect do |edge|
|
78
|
-
source = edge.keys.first
|
79
|
-
target = edge.values.first[:target]
|
80
|
-
properties = edge[source]
|
81
|
-
|
82
|
-
# we dont need a route if it is inline represented
|
83
|
-
next if properties[:inline]
|
84
|
-
|
85
|
-
link_relation = properties[:link_relation]
|
86
|
-
path = "#{target}/#{link_relation.delete('"')}"
|
87
|
-
|
88
|
-
if source == "root"
|
89
|
-
@root_path = path
|
90
|
-
end
|
91
|
-
|
92
|
-
mason_path = "lib/picatrix/templates/mason/#{edge[source][:target]}.json"
|
93
|
-
|
94
|
-
if File.exist?(mason_path)
|
95
|
-
body = JSON.parse(
|
96
|
-
File.read(
|
97
|
-
mason_path
|
98
|
-
)
|
99
|
-
)
|
100
|
-
else
|
101
|
-
body = default_response
|
102
|
-
end
|
103
|
-
|
104
|
-
if (asset = assets[source]) && body.is_a?(Hash)
|
105
|
-
body.merge!(asset)
|
106
|
-
end
|
107
|
-
|
108
|
-
{
|
109
|
-
path: path,
|
110
|
-
method: properties[:method],
|
111
|
-
# danger danger danger will robinson we are unescaping here!
|
112
|
-
body: body.to_s.delete("\\"),
|
113
|
-
collection: (collectable_items[target.singularize] || [])
|
114
|
-
}
|
115
|
-
end.compact!
|
116
|
-
end
|
117
|
-
def addressable_items
|
118
|
-
@addressable_items ||= @nodes.collect do |node|
|
119
|
-
node_name = node.first
|
120
|
-
node_properties = node.last
|
121
55
|
|
122
|
-
|
123
|
-
item_path = "#{node_name}/:item_id"
|
124
|
-
mason_path = "lib/picatrix/templates/mason/#{node_name}.json"
|
125
|
-
schema_path = "lib/picatrix/schemas/#{node_name}_item.json"
|
126
|
-
|
127
|
-
if File.exist?(mason_path)
|
128
|
-
body = JSON.parse(
|
129
|
-
File.read(
|
130
|
-
mason_path
|
131
|
-
)
|
132
|
-
)
|
133
|
-
else
|
134
|
-
body = default_response
|
135
|
-
end
|
136
|
-
|
137
|
-
if File.exist?(schema_path)
|
138
|
-
schema = JSON.parse(
|
139
|
-
File.read(
|
140
|
-
schema_path
|
141
|
-
)
|
142
|
-
)
|
143
|
-
|
144
|
-
# thor doesnt take locals in
|
145
|
-
@node_name = node_name
|
146
|
-
template(
|
147
|
-
'templates/type.rb',
|
148
|
-
File.join("generated/#{node_name}.rb")
|
149
|
-
)
|
150
|
-
@generated = generated << @node_name
|
151
|
-
else
|
152
|
-
schema = {}
|
153
|
-
end
|
154
|
-
{
|
155
|
-
path: item_path,
|
156
|
-
type: node_name,
|
157
|
-
schema: schema,
|
158
|
-
# danger danger danger will robinson we are unescaping here!
|
159
|
-
body: body.to_s.delete("\\")
|
160
|
-
}
|
161
|
-
end
|
162
|
-
end.compact!
|
163
|
-
end
|
164
|
-
def collectable_items
|
165
|
-
@collectable_items ||= @addressable_items.inject({}) do |memo, item|
|
166
|
-
memo[item[:type]] = {
|
167
|
-
name: "#{item[:type].pluralize}",
|
168
|
-
resource_name: "#{item[:type].camelcase}",
|
169
|
-
template: JSON.parse(
|
170
|
-
File.read("lib/picatrix/templates/mason/#{item[:type]}_min.json")
|
171
|
-
)
|
172
|
-
}
|
173
|
-
memo
|
174
|
-
end
|
175
|
-
end
|
176
|
-
def return_mapping_of(method)
|
177
|
-
{
|
178
|
-
post: :single_return,
|
179
|
-
get: :collection_return,
|
180
|
-
patch: :single_return,
|
181
|
-
delete: :collection_return
|
182
|
-
}[method]
|
183
|
-
end
|
56
|
+
private
|
184
57
|
def send_method_for(method)
|
185
58
|
{
|
186
59
|
post: :create,
|
187
|
-
patch: :find
|
60
|
+
patch: :find,
|
61
|
+
get: :find,
|
62
|
+
delete: :find
|
188
63
|
}[method]
|
189
64
|
end
|
190
65
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Picatrix
|
2
|
+
class LinkRelationIndex
|
3
|
+
attr_accessor :as_hash
|
4
|
+
def initialize(edges)
|
5
|
+
@as_hash = {
|
6
|
+
link_relations: edges.flat_map do |e|
|
7
|
+
source = e.first.at(0)
|
8
|
+
link_relation = e.first.at(1)[:link_relation].delete('"')
|
9
|
+
|
10
|
+
{
|
11
|
+
link_relation.to_sym => "#{source} -(#{e.first.at(1)[:method].upcase})-> #{e.first.at(1)[:target]}"
|
12
|
+
}
|
13
|
+
end.inject(Hash.new([])) do |h, a|
|
14
|
+
h[a.keys.first] += [a.values].flatten; h
|
15
|
+
end
|
16
|
+
}
|
17
|
+
|
18
|
+
@controls = {
|
19
|
+
"@controls": {
|
20
|
+
up: up_href,
|
21
|
+
self: self_href
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
def masoned
|
26
|
+
@controls.merge!(@as_hash)
|
27
|
+
end
|
28
|
+
private
|
29
|
+
def up_href
|
30
|
+
"http://localhost:9292/"
|
31
|
+
end
|
32
|
+
def self_href
|
33
|
+
"http://localhost:9292/rels"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|