picatrix 0.5.0 → 0.5.5

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +17 -37
  4. data/Rakefile +35 -0
  5. data/bin/console +8 -4
  6. data/bin/post-receive.sh +3 -0
  7. data/bin/setup +7 -1
  8. data/generated/zoo.dot +37 -0
  9. data/generated/zoo.dot.png +0 -0
  10. data/{lib/picatrix/generated/view_submissions.rb → generated/zoo/resources/animals.rb} +10 -13
  11. data/generated/zoo/support/mason.rb +114 -0
  12. data/generated/zoo/support/namespaces.json +7 -0
  13. data/generated/zoo/support/picatrix.mason.pb.rb +95 -0
  14. data/generated/zoo/support/zoo.pb.rb +76 -0
  15. data/generated/zoo/support/zoo.proto +65 -0
  16. data/generated/zoo/zoo.rb +116 -0
  17. data/lib/picatrix.rb +25 -10
  18. data/lib/picatrix/buffy.rb +38 -40
  19. data/lib/picatrix/cruddy.rb +18 -16
  20. data/lib/picatrix/jenny.rb +31 -5
  21. data/lib/picatrix/link_relation_index.rb +1 -1
  22. data/lib/picatrix/pacman.rb +12 -6
  23. data/lib/picatrix/protoc.rb +7 -0
  24. data/lib/picatrix/prototyper.rb +56 -0
  25. data/lib/picatrix/routes.rb +40 -11
  26. data/{definitions/mason.proto → lib/picatrix/support/picatrix.mason.proto} +16 -13
  27. data/lib/picatrix/templates/app.proto +42 -0
  28. data/lib/picatrix/templates/app.rb +24 -136
  29. data/lib/picatrix/templates/mason.rb +114 -0
  30. data/lib/picatrix/templates/namespaces.json +7 -0
  31. data/lib/picatrix/templates/type.rb +6 -3
  32. data/lib/picatrix/transform_to_hash.rb +2 -2
  33. data/lib/picatrix/version.rb +1 -1
  34. data/notes.md +34 -0
  35. metadata +20 -10
  36. data/definitions/app.proto +0 -47
  37. data/lib/picatrix/fixtures/view_submission.rb +0 -19
  38. data/lib/picatrix/generated/app.pb.rb +0 -79
  39. data/lib/picatrix/generated/app.rb +0 -209
  40. data/lib/picatrix/generated/mason.pb.rb +0 -90
  41. data/lib/picatrix/generated/mason/namespaces.json +0 -7
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # This file is auto-generated. DO NOT EDIT!
5
+ #
6
+ require 'protobuf/message'
7
+
8
+
9
+ ##
10
+ # Imports
11
+ #
12
+ require 'picatrix.mason.pb'
13
+
14
+
15
+ ##
16
+ # Message Classes
17
+ #
18
+ class Animals < ::Protobuf::Message
19
+ class Controls < ::Protobuf::Message; end
20
+
21
+ end
22
+
23
+ class Animal < ::Protobuf::Message
24
+ class Controls < ::Protobuf::Message; end
25
+
26
+ end
27
+
28
+ class AnimalEditTemplate < ::Protobuf::Message; end
29
+ class AnimalRemoveTemplate < ::Protobuf::Message; end
30
+ class AnimalsCreateTemplate < ::Protobuf::Message; end
31
+ class AnimalsFilterTemplate < ::Protobuf::Message; end
32
+ class NewestAnimals < ::Protobuf::Message; end
33
+
34
+
35
+ ##
36
+ # Message Fields
37
+ #
38
+ class Animals
39
+ class Controls
40
+ optional ::Picatrix::Mason::Self, :self, 1
41
+ end
42
+
43
+ optional :int32, :id, 1
44
+ optional ::Animals::Controls, :controls, 2
45
+ repeated ::Animal, :collection, 3
46
+ end
47
+
48
+ class Animal
49
+ class Controls
50
+ optional ::Picatrix::Mason::Self, :self, 1
51
+ end
52
+
53
+ optional :int32, :id, 1
54
+ optional ::Animal::Controls, :controls, 2
55
+ end
56
+
57
+
58
+ ##
59
+ # Extended Message Fields
60
+ #
61
+ class ::Picatrix::Mason::Edit < ::Protobuf::Message
62
+ optional ::AnimalEditTemplate, :edit_template, 10, :extension => true
63
+ end
64
+
65
+ class ::Picatrix::Mason::Remove < ::Protobuf::Message
66
+ optional ::AnimalRemoveTemplate, :remove_template, 10, :extension => true
67
+ end
68
+
69
+ class ::Picatrix::Mason::Create < ::Protobuf::Message
70
+ optional ::AnimalsCreateTemplate, :create_template, 10, :extension => true
71
+ end
72
+
73
+ class ::Picatrix::Mason::Filter < ::Protobuf::Message
74
+ optional ::AnimalsFilterTemplate, :filter_template, 10, :extension => true
75
+ end
76
+
@@ -0,0 +1,65 @@
1
+ import "picatrix.mason.proto";
2
+
3
+ // representation objects
4
+
5
+ message Animals {
6
+ optional int32 id = 1;
7
+
8
+ message Controls {
9
+ optional picatrix.mason.Self self = 1;
10
+ }
11
+
12
+ optional Controls controls = 2;
13
+
14
+ repeated Animal collection = 3;
15
+
16
+ }
17
+
18
+ message Animal {
19
+ optional int32 id = 1;
20
+
21
+ message Controls {
22
+ optional picatrix.mason.Self self = 1;
23
+ }
24
+
25
+ optional Controls controls = 2;
26
+
27
+ }
28
+
29
+
30
+ // generic CRUFD controls to extend
31
+ // per item representation
32
+
33
+ message AnimalEditTemplate {
34
+ }
35
+ extend picatrix.mason.Edit {
36
+ optional AnimalEditTemplate edit_template = 10;
37
+ }
38
+
39
+ message AnimalRemoveTemplate {
40
+ }
41
+ extend picatrix.mason.Remove {
42
+ optional AnimalRemoveTemplate remove_template = 10;
43
+ }
44
+
45
+
46
+ // per collection representation
47
+
48
+ message AnimalsCreateTemplate {
49
+ }
50
+ extend picatrix.mason.Create {
51
+ optional AnimalsCreateTemplate create_template = 10;
52
+ }
53
+
54
+ message AnimalsFilterTemplate {
55
+ }
56
+ extend picatrix.mason.Filter {
57
+ optional AnimalsFilterTemplate filter_template = 10;
58
+ }
59
+
60
+
61
+ // totally custom controls
62
+
63
+ message NewestAnimals {
64
+ }
65
+
@@ -0,0 +1,116 @@
1
+ require 'sinatra'
2
+ require 'sinatra/json'
3
+ require 'protobuf'
4
+ require 'require_all'
5
+
6
+ $:.unshift(File.join(File.dirname(__FILE__)))
7
+ $:.unshift(File.join(File.dirname(__FILE__), 'support'))
8
+ $:.unshift(File.join(File.dirname(__FILE__), 'resources'))
9
+
10
+ require("./generated/zoo/support/picatrix.mason.pb")
11
+ require("./generated/zoo/support/mason")
12
+ require("./generated/zoo/support/zoo.pb")
13
+ require_all("generated/zoo/resources/*.rb")
14
+
15
+ class Zoo < Sinatra::Base
16
+ include Picatrix::Mason
17
+
18
+ set :public_folder => "public", :static => true
19
+
20
+ get '/rels' do
21
+ json({:@controls=>{:up=>"http://localhost:9292/", :self=>"http://localhost:9292/rels"}, :link_relations=>{:newest=>["root -(GET)-> animals", "animal -(GET)-> animals", "animals -(DELETE)-> animals"], :":item_id"=>["animals -(GET)-> animal"], :filter=>["animals -(GET)-> animals"], :create=>["animals -(POST)-> animal"], :edit=>["animal -(PATCH)-> animal"]}})
22
+ end
23
+
24
+ get '/' do
25
+ status, headers, body = call env.merge("PATH_INFO" => "/animals")
26
+ [status, headers, body]
27
+ end
28
+
29
+ def json(hash = {})
30
+ # anything set here will be sent in all responses
31
+ super({"@namespaces"=>{"z"=>{"name"=>"http://localhost:9292/rels#"}}}.merge!(hash))
32
+ end
33
+
34
+
35
+ get "/animals" do
36
+
37
+ response_body = {"animals" => AnimalsResource.as_hashes}
38
+
39
+ controls = {}
40
+
41
+
42
+ controls.merge!(send("create".to_sym, Animals).call("animals".pluralize, params))
43
+
44
+ controls.merge!(send("filter".to_sym, Animals).call("animals".pluralize, params))
45
+
46
+ controls.merge!(send("mason_self".to_sym, Animals).call("animals".pluralize, params))
47
+
48
+ controls.merge!(send("mason_up".to_sym, Animals).call("animals".pluralize, params))
49
+
50
+
51
+ json({
52
+ :@controls => controls
53
+ }.merge!(response_body))
54
+ end
55
+
56
+ get "/animals/:item_id" do
57
+
58
+ response_body = AnimalsResource.find(params[:item_id]).to_hash.except(:controls)
59
+
60
+ controls = {}
61
+
62
+
63
+ controls.merge!(send("edit".to_sym, Animal).call("animal".pluralize, params))
64
+
65
+ controls.merge!(send("remove".to_sym, Animal).call("animal".pluralize, params))
66
+
67
+ controls.merge!(send("mason_self".to_sym, Animal).call("animal".pluralize, params))
68
+
69
+ controls.merge!(send("mason_up".to_sym, Animal).call("animal".pluralize, params))
70
+
71
+
72
+ json({
73
+ :@controls => controls
74
+ }.merge!(response_body))
75
+ end
76
+
77
+ post "/animals" do
78
+
79
+ response_body = AnimalsResource.create(params[:item_id]).to_hash.except(:controls)
80
+
81
+ controls = {}
82
+
83
+ json({
84
+ :@controls => controls
85
+ }.merge!(response_body))
86
+ end
87
+
88
+ delete "/animals/:item_id" do
89
+
90
+ response_body = {"animals" => AnimalsResource.as_hashes}
91
+
92
+ controls = {}
93
+
94
+ json({
95
+ :@controls => controls
96
+ }.merge!(response_body))
97
+ end
98
+
99
+ patch "/animals/:item_id" do
100
+
101
+ response_body = AnimalsResource.find(params[:item_id]).to_hash.except(:controls)
102
+
103
+ controls = {}
104
+
105
+
106
+ controls.merge!(send("mason_self".to_sym, Animal).call("animal".pluralize, params))
107
+
108
+ controls.merge!(send("mason_up".to_sym, Animal).call("animal".pluralize, params))
109
+
110
+
111
+ json({
112
+ :@controls => controls
113
+ }.merge!(response_body))
114
+ end
115
+
116
+ end
data/lib/picatrix.rb CHANGED
@@ -1,3 +1,5 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib/picatrix/generated', __FILE__)
2
+
1
3
  require "picatrix/version"
2
4
  require "protobuf"
3
5
  require "parslet"
@@ -9,31 +11,39 @@ require "thor"
9
11
  require "picatrix/pacman"
10
12
  require "picatrix/digraph_parser"
11
13
  require "picatrix/transform_to_hash"
14
+ require "picatrix/buffy"
12
15
  require "picatrix/link_relation_index"
13
16
  require "picatrix/routes"
17
+ require "picatrix/protoc"
14
18
  require "picatrix/cruddy"
15
- require "picatrix/buffy"
19
+ require "picatrix/prototyper"
16
20
  require "picatrix/jenny"
17
21
 
18
22
  module Picatrix
19
23
  class CLI < Thor
20
- desc "g <dot file name> <output file name>", "generate <dot file name> <output file name>"
24
+ desc "g <dot file name> <optional: app name>",
25
+ "generates Sinatra app, uses dot file name for app name if none given"
21
26
  option :force, :type => :boolean
22
27
 
23
- def g(dot_file_name, output=nil)
28
+ def g(dot_file_name, app_name = nil)
29
+ app_name = File.basename(dot_file_name, ".dot") if app_name.nil?
30
+
24
31
  puts "using: #{dot_file_name}"
25
- puts "output: #{output}" if output
32
+ puts "output: #{app_name}"
26
33
 
27
34
  Jenny.new(
28
35
  Pacman.new(
29
36
  dot_file_name
30
- ).hash,
31
- options
37
+ ),
38
+ options,
39
+ app_name
32
40
  ).just_do_it
33
41
  end
34
42
 
35
- desc "prep <dot file name>", "outputs an image and sets up fixtures necessary to generate your app"
36
- def prep(dot_file_name)
43
+ desc "prep <dot file name> <app name>", "outputs an image and protobuf templates"
44
+ def prep(dot_file_name, app_name = nil)
45
+ app_name = File.basename(dot_file_name, ".dot") if app_name.nil?
46
+
37
47
  GraphViz.parse(dot_file_name, :path => "/usr/local/bin").
38
48
  output(:png => "#{dot_file_name}.png")
39
49
  puts "output to #{dot_file_name}.png"
@@ -41,9 +51,14 @@ module Picatrix
41
51
  Buffy.new(
42
52
  Pacman.new(
43
53
  dot_file_name
44
- ).nodes
45
- )
54
+ ),
55
+ options,
56
+ app_name
57
+ ).slay
58
+
46
59
  puts "output to generated/"
60
+ puts "You will need to edit your #{app_name}.proto file to match your schema." +
61
+ " Then you can run `picapica g <app_name>` to generate your application."
47
62
  end
48
63
  end
49
64
  end
@@ -1,56 +1,54 @@
1
- require 'protobuf'
2
- require 'faker'
3
-
4
1
  module Picatrix
5
2
  class Buffy
6
3
  include Thor::Base
7
4
  include Thor::Actions
8
5
 
9
- attr_accessor :destination_stack, :options,
10
- :resources, :id
6
+ attr_accessor :resources, :link_relations, :representation_klasses,
7
+ :app_name
11
8
 
12
- source_root File.dirname(__FILE__)
9
+ # must be disjoint due to nature of protobuf
10
+ ITEM_ACTIONS = %w{ Edit Remove }
11
+ COL_ACTIONS = %w{ Create Filter }
12
+ CRUFD = %w{ Create Edit Remove Filter }
13
13
 
14
- PROTOBUF_FIXTURES = {
15
- Protobuf::Field::Int32Field => "Faker::Number.number(6)",
16
- Protobuf::Field::StringField => "Faker::Lorem.word"
17
- }
14
+ argument :name
15
+ source_root File.dirname(__FILE__)
18
16
 
19
- def initialize(nodes, options = {})
17
+ def initialize(pacman, options = {}, app_name = "app")
20
18
  # thor related
21
19
  @options = options
22
20
  @destination_stack = [self.class.source_root]
21
+ @app_name = app_name
22
+
23
+ @representation_klasses = pacman.nodes.keys.map(&:camelize)
24
+
25
+ @item_representations = @representation_klasses.map(&:singularize).uniq
26
+ @col_representations = @representation_klasses.map(&:pluralize).uniq
27
+ @resources = @item_representations + @col_representations
23
28
 
24
- @resources = nodes.keys.select {|n| n if n.pluralize == n}
25
- resources.each do |resource|
26
- @resource_name = resource.camelize
27
- @fields = @resource_name.singularize.
28
- constantize.fields.inject({}) do |memo, field|
29
-
30
- field_value =
31
- if PROTOBUF_FIXTURES[field.type_class]
32
- # TODO this is too general need some way to signal
33
- # primary key which is addressable
34
- if field.name.to_s.include?("id")
35
- "id = #{PROTOBUF_FIXTURES[field.type_class]}"
36
- else
37
- PROTOBUF_FIXTURES[field.type_class]
38
- end
39
- elsif field.type_class.to_s.demodulize == "Controls"
40
- "#{field.type_class}.new(minimal_controls_for(item_id))"
41
- else
42
- # TODO recursively gen these relations
43
- "[#{field.type_class}.new(params = {})]"
44
- end
45
-
46
- memo[field.name] = field_value
47
- memo
29
+ @link_relations = pacman.edges.collect do |edge|
30
+ target = edge[edge.keys.first][:target]
31
+ link_relation = edge[edge.keys.first][:link_relation]
32
+ if link_relation[0] != ':' && !CRUFD.map(&:downcase).include?(link_relation)
33
+ "#{link_relation.camelize}" + "#{target.camelize}"
48
34
  end
49
- template(
50
- 'templates/type.rb',
51
- File.join("generated/#{resource}.rb")
52
- )
53
- end
35
+ end.compact.uniq
36
+ end
37
+
38
+ def slay
39
+ # TODO need to make prefix setter
40
+ @prefix = app_name[0]
41
+ @host = "http://localhost:9292/"
42
+
43
+ template(
44
+ 'templates/namespaces.json',
45
+ File.join("../../generated/#{app_name}/support/namespaces.json")
46
+ )
47
+
48
+ template(
49
+ 'templates/app.proto',
50
+ File.join("../../generated/#{app_name}/support/#{app_name}.proto")
51
+ )
54
52
  end
55
53
  end
56
54
  end
@@ -2,6 +2,9 @@ module Picatrix
2
2
  class Cruddy
3
3
  attr_accessor :controls
4
4
 
5
+ # iow if it is addressable it has a self
6
+ DEFAULT_CONTROLS = [:mason_self, :mason_up]
7
+
5
8
  def initialize(edges)
6
9
  @controls = edges.inject({}) do |memo, edge|
7
10
  source = edge.keys.first
@@ -16,30 +19,29 @@ module Picatrix
16
19
 
17
20
  private
18
21
  def appropriate_controls_for(source)
19
- #TODO unless these become more diff again, should combine
20
- if source.pluralize == source # collection?
21
- {
22
- source => template_map(:collection)
23
- }
24
- else
25
- {
26
- source => template_map(:item)
27
- }
28
- end
22
+ by_size = collection?(source) ? :collection : :item
23
+ {
24
+ source => template_map(by_size)
25
+ }
29
26
  end
30
27
  def template_map(type)
31
28
  {
29
+ # what controls do you want to get back
30
+ # from a given method on a item/collection
32
31
  item: {
33
- get: :mason_self,
34
- patch: :edit,
35
- put: :edit,
36
- delete: :remove
32
+ get: [:edit, :remove] + DEFAULT_CONTROLS,
33
+ patch: DEFAULT_CONTROLS,
34
+ put: DEFAULT_CONTROLS,
35
+ delete: [:mason_up]
37
36
  },
38
37
  collection: {
39
- post: :create,
40
- get: :filter
38
+ get: [:create, :filter] + DEFAULT_CONTROLS,
39
+ post: [:mason_self]
41
40
  }
42
41
  }[type]
43
42
  end
43
+ def collection?(source)
44
+ source.pluralize == source
45
+ end
44
46
  end
45
47
  end