picatrix 0.5.0 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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