goon_model_gen 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +10 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +44 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/exe/goon_model_gen +10 -0
  13. data/goon_model_gen.gemspec +41 -0
  14. data/lib/goon_model_gen.rb +6 -0
  15. data/lib/goon_model_gen/cli.rb +79 -0
  16. data/lib/goon_model_gen/config.rb +83 -0
  17. data/lib/goon_model_gen/generator.rb +111 -0
  18. data/lib/goon_model_gen/golang.rb +22 -0
  19. data/lib/goon_model_gen/golang/builtin.rb +31 -0
  20. data/lib/goon_model_gen/golang/datastore_supported.rb +48 -0
  21. data/lib/goon_model_gen/golang/enum.rb +26 -0
  22. data/lib/goon_model_gen/golang/field.rb +41 -0
  23. data/lib/goon_model_gen/golang/file.rb +27 -0
  24. data/lib/goon_model_gen/golang/modifier.rb +65 -0
  25. data/lib/goon_model_gen/golang/named_slice.rb +24 -0
  26. data/lib/goon_model_gen/golang/package.rb +83 -0
  27. data/lib/goon_model_gen/golang/packages.rb +64 -0
  28. data/lib/goon_model_gen/golang/predeclared_type.rb +16 -0
  29. data/lib/goon_model_gen/golang/sentence.rb +17 -0
  30. data/lib/goon_model_gen/golang/struct.rb +38 -0
  31. data/lib/goon_model_gen/golang/type.rb +29 -0
  32. data/lib/goon_model_gen/model_builder.rb +137 -0
  33. data/lib/goon_model_gen/source/context.rb +17 -0
  34. data/lib/goon_model_gen/source/contextual.rb +9 -0
  35. data/lib/goon_model_gen/source/enum.rb +20 -0
  36. data/lib/goon_model_gen/source/field.rb +41 -0
  37. data/lib/goon_model_gen/source/file.rb +58 -0
  38. data/lib/goon_model_gen/source/loader.rb +71 -0
  39. data/lib/goon_model_gen/source/named_slice.rb +18 -0
  40. data/lib/goon_model_gen/source/struct.rb +26 -0
  41. data/lib/goon_model_gen/source/type.rb +21 -0
  42. data/lib/goon_model_gen/templates/dsl.rb +60 -0
  43. data/lib/goon_model_gen/templates/model/enum/01_base.go.erb +7 -0
  44. data/lib/goon_model_gen/templates/model/enum/02_All.go.erb +5 -0
  45. data/lib/goon_model_gen/templates/model/enum/02_Map.go.erb +5 -0
  46. data/lib/goon_model_gen/templates/model/enum/03_String.go.erb +3 -0
  47. data/lib/goon_model_gen/templates/model/enum/04_NameToValue.go.erb +5 -0
  48. data/lib/goon_model_gen/templates/model/enum/05_StringTo.go.erb +19 -0
  49. data/lib/goon_model_gen/templates/model/enum/06_ToString.go.erb +3 -0
  50. data/lib/goon_model_gen/templates/model/enum/07_Valid.go.erb +4 -0
  51. data/lib/goon_model_gen/templates/model/goon/01_struct.go.erb +6 -0
  52. data/lib/goon_model_gen/templates/model/goon/02_Assign.go.erb +16 -0
  53. data/lib/goon_model_gen/templates/model/goon/03_PrepareToCreate.go.erb +16 -0
  54. data/lib/goon_model_gen/templates/model/goon/04_PrepareToUpdate.go.erb +8 -0
  55. data/lib/goon_model_gen/templates/model/goon/05_PrepareFields.go.erb +8 -0
  56. data/lib/goon_model_gen/templates/model/goon/06_IsPersisted.go.erb +3 -0
  57. data/lib/goon_model_gen/templates/model/slice/01_base.go.erb +1 -0
  58. data/lib/goon_model_gen/templates/model/struct/01_struct.go.erb +6 -0
  59. data/lib/goon_model_gen/version.rb +3 -0
  60. metadata +189 -0
@@ -0,0 +1,71 @@
1
+ require "goon_model_gen"
2
+
3
+ require "erb"
4
+ require "yaml"
5
+
6
+ require "goon_model_gen/source/context"
7
+ require "goon_model_gen/source/file"
8
+
9
+ module GoonModelGen
10
+ module Source
11
+ class Loader
12
+ # @param filepaths [Array<String>]
13
+ # @return [Context]
14
+ def process(filepaths)
15
+ context = Context.new
16
+ filepaths.each do |filepath|
17
+ load_source_yaml(context, filepath)
18
+ end
19
+ return context
20
+ end
21
+
22
+ # @param context [Context]
23
+ # @param path [string]
24
+ def load_source_yaml(context, path)
25
+ erb = ERB.new(::File.read(path), nil, "-")
26
+ erb.filename = path
27
+ txt = erb.result
28
+ raw = YAML.load(txt)
29
+
30
+ f = File.new(path).tap do |f|
31
+ f.context = context
32
+ context.files.push(f)
33
+ end
34
+
35
+ (raw['types'] || {}).each do |name, t|
36
+ source_type =
37
+ if t['fields'].is_a?(Hash)
38
+ load_struct(f, name, t).tap do |s|
39
+ if g = t['goon']
40
+ s.id_name = g['id_name']
41
+ s.id_type = g['id_type']
42
+ end
43
+ end
44
+ elsif t['enum_map'].is_a?(Hash) && t['base']
45
+ f.new_enum(name, t['base'], t['enum_map'])
46
+ elsif t['slice_of'].is_a?(String)
47
+ f.new_named_slice(name, t['slice_of'])
48
+ else
49
+ raise "Unsupported type definition named '#{name}': #{t.inspect}"
50
+ end
51
+ source_type.generators = t['generates']
52
+ end
53
+ end
54
+
55
+ # @param f [File]
56
+ # @param name [String]
57
+ # @param t [Hash<String,Hash>|Hash<String,String>] definition of struct from YAML
58
+ # @return [Struct]
59
+ def load_struct(f, name, t)
60
+ f.new_struct(name).tap do |s|
61
+ s.ref_name = t['ref_name']
62
+ t['fields'].each do |field_name, attrs|
63
+ attrs = {'type' => attrs} unless attrs.is_a?(Hash)
64
+ s.new_field(field_name, attrs)
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,18 @@
1
+ require "goon_model_gen"
2
+
3
+ require "goon_model_gen/source/type"
4
+
5
+ module GoonModelGen
6
+ module Source
7
+ class NamedSlice < Type
8
+ attr_reader :base_type_name
9
+
10
+ # @param name [String]
11
+ # @param base_type [String]
12
+ def initialize(name, base_type_name)
13
+ super(name)
14
+ @base_type_name = base_type_name
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require "goon_model_gen"
2
+
3
+ require "goon_model_gen/source/type"
4
+ require "goon_model_gen/source/field"
5
+
6
+ module GoonModelGen
7
+ module Source
8
+ class Struct < Type
9
+ attr_accessor :id_name, :id_type
10
+ attr_accessor :ref_name
11
+
12
+ def fields
13
+ @fields ||= []
14
+ end
15
+
16
+ # @param name [string]
17
+ # @param attrs [Hash<String,Object>]
18
+ def new_field(name, attrs)
19
+ Field.new(name, attrs).tap do |f|
20
+ f.context = self.context
21
+ self.fields.push(f)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require "goon_model_gen"
2
+
3
+ require "goon_model_gen/source/contextual"
4
+
5
+ module GoonModelGen
6
+ module Source
7
+ class Type
8
+ include Contextual
9
+
10
+ attr_reader :name
11
+ attr_accessor :package
12
+ attr_accessor :generators # key: method_name, value: true|false|string(file_suffix)
13
+
14
+ # @param name [string]
15
+ def initialize(name)
16
+ @name = name
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ require "goon_model_gen"
2
+
3
+ require "active_support/core_ext/string"
4
+
5
+ module GoonModelGen
6
+ module Templates
7
+ module DSL
8
+ def dependencies
9
+ @dependencies ||= {}
10
+ end
11
+
12
+ def import(alias_or_package, package_or_nil = nil)
13
+ package_path = package_or_nil || alias_or_package
14
+ new_alias = package_or_nil ? alias_or_package.to_s : nil
15
+ package_path = package_path.path if package_path.respond_to?(:path)
16
+ return if package_path.blank?
17
+ if dependencies.key?(package_path)
18
+ old_alias = dependencies[package_path]
19
+ raise "Conflict alias #{old_alias.inspect} and #{new_alias.inspect}" if old_alias != new_alias
20
+ end
21
+ dependencies[package_path] ||= new_alias
22
+ end
23
+
24
+ def partitioned_imports(except: [])
25
+ pkg_paths = dependencies.keys - except
26
+ import_contents = partition(pkg_paths).map do |group|
27
+ group.map do |path|
28
+ ailas_name = dependencies[path]
29
+ ailas_name ? "\t#{ailas_name} \"#{path}\"" : "\t\"#{path}\""
30
+ end.join("\n")
31
+ end
32
+ import_contents.empty? ? '' : "import (\n%s\n)\n" % import_contents.join("\n\n")
33
+ end
34
+
35
+ PARTITION_PATTERNS = [
36
+ /\A[^\.\/]+(?:\/.+)?\z/,
37
+ /\Agopkg\.in\//,
38
+ /\Agolang\.org\//,
39
+ /\Agoogle\.golang\.org\//,
40
+ /\Agithub\.com\//,
41
+ ].freeze
42
+
43
+ def partition(paths)
44
+ groups = paths.group_by do |path|
45
+ PARTITION_PATTERNS.index{|ptn| ptn =~ path} || PARTITION_PATTERNS.length
46
+ end
47
+ groups.keys.sort.map{|k| groups[k].sort }
48
+ end
49
+
50
+ def user_editable(value: true)
51
+ @user_editable = value
52
+ end
53
+
54
+ def user_editable?
55
+ @user_editable
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,7 @@
1
+ type <%= type.name %> <%= type.base_type.qualified_name %>
2
+
3
+ const (
4
+ <%- type.map.each do |key, name| -%>
5
+ <%= name.camelize %> <%= type.name %> = <%= key.inspect %>
6
+ <%- end -%>
7
+ )
@@ -0,0 +1,5 @@
1
+ var All<%= type.name %> = []<%= type.name %>{
2
+ <%- type.map.each do |key, name| -%>
3
+ <%= name.camelize %>,
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,5 @@
1
+ var <%= type.name %>Map = map[<%= type.name %>]string{
2
+ <%- type.map.each do |key, name| -%>
3
+ <%= key.inspect %>: <%= name.inspect %>,
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,3 @@
1
+ func (t <%= type.name %>) String() string {
2
+ return <%= type.name %>Map[t]
3
+ }
@@ -0,0 +1,5 @@
1
+ var <%= type.name %>NameToValue = map[string]<%= type.name %>{
2
+ <%- type.map.each do |key, name| -%>
3
+ <%= name.inspect %>: <%= key.inspect %>,
4
+ <%- end -%>
5
+ }
@@ -0,0 +1,19 @@
1
+ <%-
2
+ err_type_name = "InvalidEnumName"
3
+ err_type = packages.type_for(err_type_name)
4
+ if err_type
5
+ import err_type.package
6
+ -%>
7
+
8
+ func StringTo<%= type.name %>(s string) (<%= type.name %>, error) {
9
+ val, ok := <%= type.name %>NameToValue[s]
10
+ if ok {
11
+ return val, nil
12
+ } else {
13
+ err := &<%= err_type.qualified_name %>{Name: s}
14
+ return <%= type.name %>(0), err
15
+ }
16
+ }
17
+ <%-
18
+ end
19
+ -%>
@@ -0,0 +1,3 @@
1
+ func <%= type.name %>ToString(v <%= type.name %>) string {
2
+ return v.String()
3
+ }
@@ -0,0 +1,4 @@
1
+ func (t <%= type.name %>) Valid() bool {
2
+ _, ok := <%= type.name %>Map[t]
3
+ return ok
4
+ }
@@ -0,0 +1,6 @@
1
+ type <%= type.name %> struct {
2
+ <%- type.fields.each do |field| -%>
3
+ <%- import field.type.package -%>
4
+ <%= field.definition_in(type.package) %>
5
+ <%- end -%>
6
+ }
@@ -0,0 +1,16 @@
1
+ <%-
2
+ ref_type_name = "*Ref#{type.id_field.type.name.camelize}"
3
+ ref_type = packages.type_for(ref_type_name)
4
+ if ref_type
5
+ import ref_type.package
6
+ -%>
7
+ func (m *<%= type.name %>) Assign(r <%= ref_type.qualified_name %>) error {
8
+ r.ID = m.ID
9
+ <%- if type.ref_name.present? -%>
10
+ r.Name = m.<%= type.ref_name %>
11
+ <%- end -%>
12
+ return nil
13
+ }
14
+ <%-
15
+ end
16
+ -%>
@@ -0,0 +1,16 @@
1
+ func (m *<%= type.name %>) PrepareToCreate() error {
2
+ m.PrepareFields()
3
+ <%- if type.fields.any?{|f| f.name == "CreatedAt"} -%>
4
+ <%- import "time" -%>
5
+ if m.CreatedAt.IsZero() {
6
+ m.CreatedAt = time.Now()
7
+ }
8
+ <%- end -%>
9
+ <%- if type.fields.any?{|f| f.name == "UpdatedAt"} -%>
10
+ <%- import "time" -%>
11
+ if m.UpdatedAt.IsZero() {
12
+ m.UpdatedAt = time.Now()
13
+ }
14
+ <%- end -%>
15
+ return nil
16
+ }
@@ -0,0 +1,8 @@
1
+ func (m *<%= type.name %>) PrepareToUpdate() error {
2
+ m.PrepareFields()
3
+ <%- if type.fields.any?{|f| f.name == "UpdatedAt"} -%>
4
+ <%- import "time" -%>
5
+ m.UpdatedAt = time.Now()
6
+ <%- end -%>
7
+ return nil
8
+ }
@@ -0,0 +1,8 @@
1
+ func (m *<%= type.name %>) PrepareFields() error {
2
+ <%- type.fields.each do |field| -%>
3
+ <%- if field.prepare_method.present? -%>
4
+ m.<%= field.name %> = m.<%= field.name %>.<%= field.prepare_method %>()
5
+ <%- end -%>
6
+ <%- end -%>
7
+ return nil
8
+ }
@@ -0,0 +1,3 @@
1
+ func (m *<%= type.name %>) IsPersisted() bool {
2
+ return m.ID != <%= type.id_field.type.qualified_name %>(0)
3
+ }
@@ -0,0 +1 @@
1
+ type <%= type.name %> []<%= type.qualified_name %>
@@ -0,0 +1,6 @@
1
+ type <%= type.name %> struct {
2
+ <%- type.fields.each do |field| -%>
3
+ <%- import field.type.package -%>
4
+ <%= field.definition_in(type.package) %>
5
+ <%- end -%>
6
+ }
@@ -0,0 +1,3 @@
1
+ module GoonModelGen
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: goon_model_gen
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - akm
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-stack_explorer
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Generate model source files with datastore in Golang
98
+ email:
99
+ - akm2000@gmail.com
100
+ executables:
101
+ - goon_model_gen
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".travis.yml"
108
+ - CODE_OF_CONDUCT.md
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/setup
115
+ - exe/goon_model_gen
116
+ - goon_model_gen.gemspec
117
+ - lib/goon_model_gen.rb
118
+ - lib/goon_model_gen/cli.rb
119
+ - lib/goon_model_gen/config.rb
120
+ - lib/goon_model_gen/generator.rb
121
+ - lib/goon_model_gen/golang.rb
122
+ - lib/goon_model_gen/golang/builtin.rb
123
+ - lib/goon_model_gen/golang/datastore_supported.rb
124
+ - lib/goon_model_gen/golang/enum.rb
125
+ - lib/goon_model_gen/golang/field.rb
126
+ - lib/goon_model_gen/golang/file.rb
127
+ - lib/goon_model_gen/golang/modifier.rb
128
+ - lib/goon_model_gen/golang/named_slice.rb
129
+ - lib/goon_model_gen/golang/package.rb
130
+ - lib/goon_model_gen/golang/packages.rb
131
+ - lib/goon_model_gen/golang/predeclared_type.rb
132
+ - lib/goon_model_gen/golang/sentence.rb
133
+ - lib/goon_model_gen/golang/struct.rb
134
+ - lib/goon_model_gen/golang/type.rb
135
+ - lib/goon_model_gen/model_builder.rb
136
+ - lib/goon_model_gen/source/context.rb
137
+ - lib/goon_model_gen/source/contextual.rb
138
+ - lib/goon_model_gen/source/enum.rb
139
+ - lib/goon_model_gen/source/field.rb
140
+ - lib/goon_model_gen/source/file.rb
141
+ - lib/goon_model_gen/source/loader.rb
142
+ - lib/goon_model_gen/source/named_slice.rb
143
+ - lib/goon_model_gen/source/struct.rb
144
+ - lib/goon_model_gen/source/type.rb
145
+ - lib/goon_model_gen/templates/dsl.rb
146
+ - lib/goon_model_gen/templates/model/enum/01_base.go.erb
147
+ - lib/goon_model_gen/templates/model/enum/02_All.go.erb
148
+ - lib/goon_model_gen/templates/model/enum/02_Map.go.erb
149
+ - lib/goon_model_gen/templates/model/enum/03_String.go.erb
150
+ - lib/goon_model_gen/templates/model/enum/04_NameToValue.go.erb
151
+ - lib/goon_model_gen/templates/model/enum/05_StringTo.go.erb
152
+ - lib/goon_model_gen/templates/model/enum/06_ToString.go.erb
153
+ - lib/goon_model_gen/templates/model/enum/07_Valid.go.erb
154
+ - lib/goon_model_gen/templates/model/goon/01_struct.go.erb
155
+ - lib/goon_model_gen/templates/model/goon/02_Assign.go.erb
156
+ - lib/goon_model_gen/templates/model/goon/03_PrepareToCreate.go.erb
157
+ - lib/goon_model_gen/templates/model/goon/04_PrepareToUpdate.go.erb
158
+ - lib/goon_model_gen/templates/model/goon/05_PrepareFields.go.erb
159
+ - lib/goon_model_gen/templates/model/goon/06_IsPersisted.go.erb
160
+ - lib/goon_model_gen/templates/model/slice/01_base.go.erb
161
+ - lib/goon_model_gen/templates/model/struct/01_struct.go.erb
162
+ - lib/goon_model_gen/version.rb
163
+ homepage: https://github.com/akm/goon_model_gen
164
+ licenses:
165
+ - MIT
166
+ metadata:
167
+ homepage_uri: https://github.com/akm/goon_model_gen
168
+ source_code_uri: https://github.com/akm/goon_model_gen
169
+ changelog_uri: https://github.com/akm/goon_model_gen
170
+ post_install_message:
171
+ rdoc_options: []
172
+ require_paths:
173
+ - lib
174
+ required_ruby_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubygems_version: 3.0.3
186
+ signing_key:
187
+ specification_version: 4
188
+ summary: Generate model source files with datastore in Golang
189
+ test_files: []