goon_model_gen 0.1.1 → 0.1.2
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/lib/goon_model_gen/builder/abstract_builder.rb +104 -0
- data/lib/goon_model_gen/builder/model_builder.rb +74 -0
- data/lib/goon_model_gen/builder/store_builder.rb +45 -0
- data/lib/goon_model_gen/builder/validation_builder.rb +32 -0
- data/lib/goon_model_gen/cli.rb +38 -11
- data/lib/goon_model_gen/config.rb +4 -2
- data/lib/goon_model_gen/generator.rb +6 -0
- data/lib/goon_model_gen/golang/field.rb +1 -0
- data/lib/goon_model_gen/golang/packages.rb +5 -0
- data/lib/goon_model_gen/golang/struct.rb +2 -2
- data/lib/goon_model_gen/golang/type.rb +5 -0
- data/lib/goon_model_gen/source/field.rb +1 -2
- data/lib/goon_model_gen/source/file.rb +1 -0
- data/lib/goon_model_gen/source/loader.rb +19 -1
- data/lib/goon_model_gen/source/type.rb +1 -1
- data/lib/goon_model_gen/templates/model/enum/02_Map.go.erb +1 -1
- data/lib/goon_model_gen/templates/store/goon/01_Binder.go.erb +10 -0
- data/lib/goon_model_gen/templates/store/goon/02_Hook.go.erb +10 -0
- data/lib/goon_model_gen/templates/store/goon/03_struct.go.erb +4 -0
- data/lib/goon_model_gen/templates/store/goon/04_KindName.go.erb +3 -0
- data/lib/goon_model_gen/templates/store/goon/05_Query.go.erb +11 -0
- data/lib/goon_model_gen/templates/store/goon/06_Run.go.erb +10 -0
- data/lib/goon_model_gen/templates/store/goon/07_All.go.erb +8 -0
- data/lib/goon_model_gen/templates/store/goon/08_AllBy.go.erb +24 -0
- data/lib/goon_model_gen/templates/store/goon/09_Select.go.erb +9 -0
- data/lib/goon_model_gen/templates/store/goon/10_FirstBy.go.erb +17 -0
- data/lib/goon_model_gen/templates/store/goon/11_CountBy.go.erb +16 -0
- data/lib/goon_model_gen/templates/store/goon/12_ByID.go.erb +20 -0
- data/lib/goon_model_gen/templates/store/goon/13_ByKey.go.erb +15 -0
- data/lib/goon_model_gen/templates/store/goon/14_Get.go.erb +22 -0
- data/lib/goon_model_gen/templates/store/goon/15_IsValidKey.go.erb +20 -0
- data/lib/goon_model_gen/templates/store/goon/16_Exist.go.erb +28 -0
- data/lib/goon_model_gen/templates/store/goon/17_Create.go.erb +24 -0
- data/lib/goon_model_gen/templates/store/goon/18_Update.go.erb +24 -0
- data/lib/goon_model_gen/templates/store/goon/19_PutWith.go.erb +28 -0
- data/lib/goon_model_gen/templates/store/goon/20_Put.go.erb +17 -0
- data/lib/goon_model_gen/templates/store/goon/21_Delete.go.erb +20 -0
- data/lib/goon_model_gen/templates/store/goon/22_ValidateUniqueness.go.erb +35 -0
- data/lib/goon_model_gen/templates/store/goon/23_Validate.go.erb +14 -0
- data/lib/goon_model_gen/templates/validation/error/01_struct.go.erb +4 -0
- data/lib/goon_model_gen/templates/validation/error/02_Error.go.erb +4 -0
- data/lib/goon_model_gen/version.rb +1 -1
- metadata +30 -2
- data/lib/goon_model_gen/model_builder.rb +0 -137
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 316458bf5f2033fb2e803fc8cb74b8a8ef80a44eb2adf8bec57862a9283b19ad
         | 
| 4 | 
            +
              data.tar.gz: 57100fe6b8c389a3f0eb7faa8ea4e7ac063e386c9866d9eb24eeb0c0ea82ef55
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9f52397b1dbb695e7f65826cccb701b9cb171bc861b03c50274fd00d94a3a53b5312022f096bedc2fca6d956c0d18748daa2344c673b47c84cfd0b7bbe7ff582
         | 
| 7 | 
            +
              data.tar.gz: 8226739cfb3a3404a70eb5814e6d0b7ba8169216850ad509f11493bad632bc3ed0392e4b40da811c06f56cdc5378e10a26b7dd8bbbb8cc04557937e4988b2c58
         | 
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            require "goon_model_gen"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "goon_model_gen/golang/packages"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module GoonModelGen
         | 
| 6 | 
            +
              module Builder
         | 
| 7 | 
            +
                class AbstractBuilder
         | 
| 8 | 
            +
                  attr_reader :base_package_path
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  # @param base_package_path [String]
         | 
| 11 | 
            +
                  def initialize(base_package_path)
         | 
| 12 | 
            +
                    @base_package_path = base_package_path
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  # @param context [Source::Context]
         | 
| 16 | 
            +
                  # @return [Golang::Packages]
         | 
| 17 | 
            +
                  def build(context)
         | 
| 18 | 
            +
                    Golang::Packages.new.tap do |r|
         | 
| 19 | 
            +
                      build_sentences = []
         | 
| 20 | 
            +
                      context.files.each do |f|
         | 
| 21 | 
            +
                        package_path = File.join(base_package_path, f.basename)
         | 
| 22 | 
            +
                        pkg, procs = build_package(package_path, f.types)
         | 
| 23 | 
            +
                        r << pkg
         | 
| 24 | 
            +
                        build_sentences.concat(procs)
         | 
| 25 | 
            +
                      end
         | 
| 26 | 
            +
                      resolve_type_names(r)
         | 
| 27 | 
            +
                      build_sentences.each(&:call)
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  # @param package_path [String]
         | 
| 32 | 
            +
                  # @param types [Array<Source::Type>]
         | 
| 33 | 
            +
                  # @return [Golang::Package, Array<Proc>]
         | 
| 34 | 
            +
                  def build_package(package_path, types)
         | 
| 35 | 
            +
                    raise NotImplementedError, "#{self.type.name} doesn't implement build_package method"
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # @param pkgs [Golang::Packages]
         | 
| 39 | 
            +
                  def resolve_type_names(pkgs)
         | 
| 40 | 
            +
                    raise NotImplementedError, "#{self.type.name} doesn't implement resolve_type_names method"
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  # @param action [string] directory name under templates directory. ex. model, store...
         | 
| 44 | 
            +
                  # @param kind [string] directory name under the directory specified by action. ex. goon, struct, enum, slice
         | 
| 45 | 
            +
                  # @param t [Source::Struct]
         | 
| 46 | 
            +
                  # @param go_type [Golang::Type]
         | 
| 47 | 
            +
                  def build_sentences(action, kind, t, go_type)
         | 
| 48 | 
            +
                    template_base = File.join(action, kind)
         | 
| 49 | 
            +
                    build_sentences_with(template_base, go_type, t.generators[action])
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  # @param template_base [string] template directory path from templates directory. ex. model/enum, store/goon...
         | 
| 53 | 
            +
                  # @param generators [Hash<string,Object>]
         | 
| 54 | 
            +
                  # @param go_type [Golang::Type]
         | 
| 55 | 
            +
                  def build_sentences_with(template_base, go_type, generators)
         | 
| 56 | 
            +
                    m2t = method_to_template_for(template_base)
         | 
| 57 | 
            +
                    generators ||= default_generators_for(template_base)
         | 
| 58 | 
            +
                    generators.each do |name, suffix|
         | 
| 59 | 
            +
                      next if !suffix
         | 
| 60 | 
            +
                      template = m2t[name]
         | 
| 61 | 
            +
                      raise "No template found for #{name.inspect}" unless template
         | 
| 62 | 
            +
                      parts = [go_type.name.underscore]
         | 
| 63 | 
            +
                      custom_suffix = false
         | 
| 64 | 
            +
                      if suffix.is_a?(String)
         | 
| 65 | 
            +
                        parts << suffix
         | 
| 66 | 
            +
                        custom_suffix = true
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                      filename = parts.join('_') << '.go'
         | 
| 69 | 
            +
                      go_type.package.find_or_new_file(filename).tap do |file|
         | 
| 70 | 
            +
                        file.custom_suffix = custom_suffix
         | 
| 71 | 
            +
                        file.new_sentence(File.join(template_base, template), go_type)
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  def default_generators_for(template_base)
         | 
| 77 | 
            +
                    method_to_template_for(template_base).keys.
         | 
| 78 | 
            +
                      each_with_object({}){|name, d| d[name] = true }
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def method_to_template_map
         | 
| 82 | 
            +
                    @method_to_template_map ||= {}
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def method_to_template_for(template_base)
         | 
| 86 | 
            +
                    method_to_template_map[template_base] ||=
         | 
| 87 | 
            +
                      begin
         | 
| 88 | 
            +
                        templates_for(template_base).each_with_object({}) do |filename, d|
         | 
| 89 | 
            +
                          m = filename.sub(/\A\d+\_/, '').sub(/\.go\.erb\z/, '')
         | 
| 90 | 
            +
                          d[m] = filename
         | 
| 91 | 
            +
                        end
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def templates_for(template_base)
         | 
| 96 | 
            +
                    base_dir = File.join(File.expand_path('../../templates', __FILE__), template_base)
         | 
| 97 | 
            +
                    Dir.chdir(base_dir) do
         | 
| 98 | 
            +
                      Dir.glob('*.go.erb')
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
            end
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            require "goon_model_gen"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "goon_model_gen/builder/abstract_builder"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "goon_model_gen/source/struct"
         | 
| 6 | 
            +
            require "goon_model_gen/source/enum"
         | 
| 7 | 
            +
            require "goon_model_gen/source/named_slice"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require "goon_model_gen/golang/package"
         | 
| 10 | 
            +
            require "goon_model_gen/golang/packages"
         | 
| 11 | 
            +
            require "goon_model_gen/golang/datastore_supported"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require "active_support/core_ext/string"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            module GoonModelGen
         | 
| 16 | 
            +
              module Builder
         | 
| 17 | 
            +
                class ModelBuilder < AbstractBuilder
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  # @param package_path [String]
         | 
| 20 | 
            +
                  # @param types [Array<Source::Type>]
         | 
| 21 | 
            +
                  # @return [Golang::Package, Array<Proc>]
         | 
| 22 | 
            +
                  def build_package(package_path, types)
         | 
| 23 | 
            +
                    procs = []
         | 
| 24 | 
            +
                    pkg = Golang::Package.new(package_path).tap do |pkg|
         | 
| 25 | 
            +
                      types.each do |t|
         | 
| 26 | 
            +
                        case t
         | 
| 27 | 
            +
                        when Source::Struct then
         | 
| 28 | 
            +
                          go_type = build_struct(t, pkg)
         | 
| 29 | 
            +
                          kind = (t.id_name && t.id_type) ? 'goon' : 'struct'
         | 
| 30 | 
            +
                          procs << Proc.new{ build_sentences('model', kind, t, go_type) }
         | 
| 31 | 
            +
                        when Source::Enum then
         | 
| 32 | 
            +
                          go_type = pkg.new_enum(t.name, t.base_type, t.map)
         | 
| 33 | 
            +
                          procs << Proc.new{ build_sentences('model', 'enum', t, go_type) }
         | 
| 34 | 
            +
                        when Source::NamedSlice then
         | 
| 35 | 
            +
                          go_type = pkg.new_named_slice(t.name, t.base_type_name)
         | 
| 36 | 
            +
                          procs << Proc.new{ build_sentences('model', 'slice', t, go_type) }
         | 
| 37 | 
            +
                        else
         | 
| 38 | 
            +
                          raise "Unsupported type #{t.class.name} #{t.inspect}"
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                      end
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                    return pkg, procs
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  # @param pkgs [Golang::Packages]
         | 
| 46 | 
            +
                  def resolve_type_names(pkgs)
         | 
| 47 | 
            +
                    pkgs.resolve_type_names(Golang::DatastoreSupported.packages)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  # @param t [Source::Struct]
         | 
| 51 | 
            +
                  # @param pkg [Golang::Package]
         | 
| 52 | 
            +
                  # @return [Golang::Struct]
         | 
| 53 | 
            +
                  def build_struct(t, pkg)
         | 
| 54 | 
            +
                    pkg.new_struct(t.name).tap do |s|
         | 
| 55 | 
            +
                      s.ref_name = t.ref_name
         | 
| 56 | 
            +
                      if t.id_name && t.id_type
         | 
| 57 | 
            +
                        tags = {
         | 
| 58 | 
            +
                          'goon' => ['id'],
         | 
| 59 | 
            +
                          'datastore' => ['-'],
         | 
| 60 | 
            +
                          'json' => [t.id_name.underscore],
         | 
| 61 | 
            +
                        }
         | 
| 62 | 
            +
                        s.new_field(t.id_name, t.id_type, tags, goon_id: true)
         | 
| 63 | 
            +
                      end
         | 
| 64 | 
            +
                      t.fields.each do |f|
         | 
| 65 | 
            +
                        s.new_field(f.name, f.type_name, f.build_tags).tap do |field|
         | 
| 66 | 
            +
                          field.unique = f.unique
         | 
| 67 | 
            +
                        end
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require "goon_model_gen"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "goon_model_gen/builder/abstract_builder"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "goon_model_gen/source/struct"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require "goon_model_gen/golang/package"
         | 
| 8 | 
            +
            require "goon_model_gen/golang/datastore_supported"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
             | 
| 11 | 
            +
            module GoonModelGen
         | 
| 12 | 
            +
              module Builder
         | 
| 13 | 
            +
                class StoreBuilder < AbstractBuilder
         | 
| 14 | 
            +
                  attr_reader :model_packages
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  # @param base_package_path [String]
         | 
| 17 | 
            +
                  # @param model_packages [Golang::Packages]
         | 
| 18 | 
            +
                  def initialize(base_package_path, model_packages)
         | 
| 19 | 
            +
                    super(base_package_path)
         | 
| 20 | 
            +
                    @model_packages = model_packages
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  # @param package_path [String]
         | 
| 24 | 
            +
                  # @param types [Array<Source::Type>]
         | 
| 25 | 
            +
                  # @return [Golang::Package, Array<Proc>]
         | 
| 26 | 
            +
                  def build_package(package_path, types)
         | 
| 27 | 
            +
                    procs = []
         | 
| 28 | 
            +
                    pkg = Golang::Package.new(package_path).tap do |pkg|
         | 
| 29 | 
            +
                      types.select{|t| t.is_a?(Source::Struct) && t.id_name && t.id_type }.each do |t|
         | 
| 30 | 
            +
                        store_type = pkg.new_struct(t.name + "Store")
         | 
| 31 | 
            +
                        procs << Proc.new{ build_sentences('store', 'goon', t, store_type) }
         | 
| 32 | 
            +
                        store_type.memo[:model] = model_packages.detect_by(t.file.basename).lookup(t.name)
         | 
| 33 | 
            +
                      end
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                    return pkg, procs
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # @param pkgs [Golang::Packages]
         | 
| 39 | 
            +
                  def resolve_type_names(pkgs)
         | 
| 40 | 
            +
                    pkgs.resolve_type_names(Golang::DatastoreSupported.packages.dup.add(model_packages))
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            require "goon_model_gen"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "goon_model_gen/builder/abstract_builder"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "goon_model_gen/golang/packages"
         | 
| 6 | 
            +
            require "goon_model_gen/golang/datastore_supported"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
             | 
| 9 | 
            +
            module GoonModelGen
         | 
| 10 | 
            +
              module Builder
         | 
| 11 | 
            +
                class ValidationBuilder < AbstractBuilder
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  # @return [Golang::Packages]
         | 
| 14 | 
            +
                  def build(*)
         | 
| 15 | 
            +
                    Golang::Packages.new.tap do |r|
         | 
| 16 | 
            +
                      r.new_package(base_package_path).tap do |pkg|
         | 
| 17 | 
            +
                        t = pkg.new_struct('ValidationError')
         | 
| 18 | 
            +
                        pkg.new_file('validation_error.go').tap do |f|
         | 
| 19 | 
            +
                          build_sentences_with('validation/error', t, nil)
         | 
| 20 | 
            +
                        end
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  # @param pkgs [Golang::Packages]
         | 
| 26 | 
            +
                  def resolve_type_names(pkgs)
         | 
| 27 | 
            +
                    pkgs.resolve_type_names(Golang::DatastoreSupported.packages)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/goon_model_gen/cli.rb
    CHANGED
    
    | @@ -5,7 +5,9 @@ require "yaml" | |
| 5 5 | 
             
            require "thor"
         | 
| 6 6 |  | 
| 7 7 | 
             
            require "goon_model_gen/config"
         | 
| 8 | 
            -
            require "goon_model_gen/model_builder"
         | 
| 8 | 
            +
            require "goon_model_gen/builder/model_builder"
         | 
| 9 | 
            +
            require "goon_model_gen/builder/store_builder"
         | 
| 10 | 
            +
            require "goon_model_gen/builder/validation_builder"
         | 
| 9 11 | 
             
            require "goon_model_gen/source/loader"
         | 
| 10 12 | 
             
            require "goon_model_gen/generator"
         | 
| 11 13 |  | 
| @@ -30,17 +32,29 @@ module GoonModelGen | |
| 30 32 | 
             
                  puts YAML.dump(context)
         | 
| 31 33 | 
             
                end
         | 
| 32 34 |  | 
| 33 | 
            -
                desc "build FILE1...", "Build golang objects from source YAML files"
         | 
| 34 | 
            -
                def build(*paths)
         | 
| 35 | 
            -
                  packages = build_model_objects(paths)
         | 
| 36 | 
            -
                  puts YAML.dump(packages)
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 35 | 
             
                desc "model FILE1...", "Generate model files from source YAML files"
         | 
| 36 | 
            +
                option :inspect, type: :boolean, desc: "Don't generate any file and show package objects if given"
         | 
| 40 37 | 
             
                def model(*paths)
         | 
| 41 38 | 
             
                  packages = build_model_objects(paths)
         | 
| 42 | 
            -
                   | 
| 43 | 
            -
                     | 
| 39 | 
            +
                  if options[:inspect]
         | 
| 40 | 
            +
                    puts YAML.dump(packages)
         | 
| 41 | 
            +
                  else
         | 
| 42 | 
            +
                    packages.map(&:files).flatten.each do |f|
         | 
| 43 | 
            +
                      new_generator(f, packages).run
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                desc "store FILE1...", "Generate store files from source YAML files"
         | 
| 49 | 
            +
                option :inspect, type: :boolean, desc: "Don't generate any file and show package objects if given"
         | 
| 50 | 
            +
                def store(*paths)
         | 
| 51 | 
            +
                  packages = build_store_packages(paths).add(*validation_packages)
         | 
| 52 | 
            +
                  if options[:inspect]
         | 
| 53 | 
            +
                    puts YAML.dump(packages)
         | 
| 54 | 
            +
                  else
         | 
| 55 | 
            +
                    packages.map(&:files).flatten.each do |f|
         | 
| 56 | 
            +
                      new_generator(f, packages).run
         | 
| 57 | 
            +
                    end
         | 
| 44 58 | 
             
                  end
         | 
| 45 59 | 
             
                end
         | 
| 46 60 |  | 
| @@ -59,8 +73,16 @@ module GoonModelGen | |
| 59 73 | 
             
                  # @return [Array<Golang::Package>]
         | 
| 60 74 | 
             
                  def build_model_objects(paths)
         | 
| 61 75 | 
             
                    context = Source::Loader.new.process(paths)
         | 
| 62 | 
            -
                     | 
| 63 | 
            -
             | 
| 76 | 
            +
                    Builder::ModelBuilder.new(cfg.model_package_path).build(context)
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  # @param paths [Array<String>] Source::Context
         | 
| 80 | 
            +
                  # @return [Array<Golang::Package>]
         | 
| 81 | 
            +
                  def build_store_packages(paths)
         | 
| 82 | 
            +
                    context = Source::Loader.new.process(paths)
         | 
| 83 | 
            +
                    model_packages = Builder::ModelBuilder.new(cfg.model_package_path).build(context)
         | 
| 84 | 
            +
                    store_packages = Builder::StoreBuilder.new(cfg.store_package_path, model_packages).build(context)
         | 
| 85 | 
            +
                    return store_packages
         | 
| 64 86 | 
             
                  end
         | 
| 65 87 |  | 
| 66 88 | 
             
                  # @param f [Golang::File]
         | 
| @@ -74,6 +96,11 @@ module GoonModelGen | |
| 74 96 | 
             
                    g.overwrite_custom_file = options[:overwrite_custom_file]
         | 
| 75 97 | 
             
                    return g
         | 
| 76 98 | 
             
                  end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  # @return [Golang::Package]
         | 
| 101 | 
            +
                  def validation_packages
         | 
| 102 | 
            +
                    Builder::ValidationBuilder.new(cfg.validation_package_path).build
         | 
| 103 | 
            +
                  end
         | 
| 77 104 | 
             
                end
         | 
| 78 105 | 
             
              end
         | 
| 79 106 | 
             
            end
         | 
| @@ -14,8 +14,8 @@ module GoonModelGen | |
| 14 14 | 
             
                  base_package_path
         | 
| 15 15 | 
             
                  model_dir
         | 
| 16 16 | 
             
                  model_package_path
         | 
| 17 | 
            -
                   | 
| 18 | 
            -
                   | 
| 17 | 
            +
                  validation_dir
         | 
| 18 | 
            +
                  validation_package_path
         | 
| 19 19 | 
             
                  store_dir
         | 
| 20 20 | 
             
                  store_package_path
         | 
| 21 21 | 
             
                  converter_dir
         | 
| @@ -31,11 +31,13 @@ module GoonModelGen | |
| 31 31 | 
             
                  @gofmt_disabled ||= false
         | 
| 32 32 | 
             
                  @model_dir      ||= "./model"
         | 
| 33 33 | 
             
                  @store_dir      ||= "./stores"
         | 
| 34 | 
            +
                  @validation_dir ||= "./validation"
         | 
| 34 35 | 
             
                  @converter_dir  ||= "./converters"
         | 
| 35 36 | 
             
                  @goa_gen_dir    ||= "./gen"
         | 
| 36 37 | 
             
                  @base_package_path  ||= default_go_package
         | 
| 37 38 | 
             
                  @model_package_path ||= join_paths(@base_package_path, @model_dir)
         | 
| 38 39 | 
             
                  @store_package_path ||= join_paths(@base_package_path, @store_dir)
         | 
| 40 | 
            +
                  @validation_package_path ||= join_paths(@base_package_path, @validation_dir)
         | 
| 39 41 | 
             
                  @converter_package_path ||= join_paths(@base_package_path, @converter_dir)
         | 
| 40 42 | 
             
                  @goa_gen_package_path   ||= join_paths(@base_package_path, @goa_gen_dir)
         | 
| 41 43 | 
             
                  @structs_gen_dir ||= "./cmd/structs"
         | 
| @@ -41,12 +41,15 @@ module GoonModelGen | |
| 41 41 | 
             
                  end
         | 
| 42 42 |  | 
| 43 43 | 
             
                  content = execute(variables)
         | 
| 44 | 
            +
                  return unless content
         | 
| 44 45 |  | 
| 45 46 | 
             
                  options = {skip: skip, force: force}
         | 
| 46 47 | 
             
                  thor.create_file(output_path, content, options)
         | 
| 47 48 | 
             
                end
         | 
| 48 49 |  | 
| 49 50 | 
             
                def execute(variables = {})
         | 
| 51 | 
            +
                  return nil if file.sentences.empty?
         | 
| 52 | 
            +
             | 
| 50 53 | 
             
                  variables.each do |key, val|
         | 
| 51 54 | 
             
                    define_singleton_method(key){ val }
         | 
| 52 55 | 
             
                  end
         | 
| @@ -57,6 +60,9 @@ module GoonModelGen | |
| 57 60 | 
             
                    # local variables used in tempaltes
         | 
| 58 61 | 
             
                    type = sentence.type
         | 
| 59 62 | 
             
                    package = type.package
         | 
| 63 | 
            +
                    type.memo.each do |key, val|
         | 
| 64 | 
            +
                      define_singleton_method(key){ val }
         | 
| 65 | 
            +
                    end
         | 
| 60 66 |  | 
| 61 67 | 
             
                    erb = ERB.new(File.read(template_path), nil, "-")
         | 
| 62 68 | 
             
                    erb.filename = template_path
         | 
| @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            require "goon_model_gen"
         | 
| 2 2 |  | 
| 3 | 
            +
            require "goon_model_gen/golang/package"
         | 
| 3 4 | 
             
            require "goon_model_gen/golang/modifier"
         | 
| 4 5 |  | 
| 5 6 | 
             
            require "active_support/core_ext/string"
         | 
| @@ -25,6 +26,10 @@ module GoonModelGen | |
| 25 26 | 
             
                    self
         | 
| 26 27 | 
             
                  end
         | 
| 27 28 |  | 
| 29 | 
            +
                  def new_package(path)
         | 
| 30 | 
            +
                    Package.new(path).tap{|pkg| add(pkg)}
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 28 33 | 
             
                  def detect_by(basename)
         | 
| 29 34 | 
             
                    detect{|pkg| pkg.basename == basename}
         | 
| 30 35 | 
             
                  end
         | 
| @@ -12,8 +12,8 @@ module GoonModelGen | |
| 12 12 | 
             
                    @fields ||= []
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 | 
            -
                  # @param name [ | 
| 16 | 
            -
                  # @param t [ | 
| 15 | 
            +
                  # @param name [String]
         | 
| 16 | 
            +
                  # @param t [String]
         | 
| 17 17 | 
             
                  # @param tags [Hash<String,Array<String>>]
         | 
| 18 18 | 
             
                  def new_field(name, t, tags, options = {})
         | 
| 19 19 | 
             
                    Field.new(name, t, tags, options).tap do |f|
         | 
| @@ -48,7 +48,25 @@ module GoonModelGen | |
| 48 48 | 
             
                        else
         | 
| 49 49 | 
             
                          raise "Unsupported type definition named '#{name}': #{t.inspect}"
         | 
| 50 50 | 
             
                        end
         | 
| 51 | 
            -
             | 
| 51 | 
            +
             | 
| 52 | 
            +
                      source_type.generators =
         | 
| 53 | 
            +
                        case t['generates']
         | 
| 54 | 
            +
                        when false then Hash.new({}) # Return empty Hash not to generate any file
         | 
| 55 | 
            +
                        when nil, true then Hash.new(nil) # Fulfill by default methods
         | 
| 56 | 
            +
                        when Hash then
         | 
| 57 | 
            +
                          t['generates'].each_with_object({}) do |(k,v), d|
         | 
| 58 | 
            +
                            d[k] =
         | 
| 59 | 
            +
                              case v
         | 
| 60 | 
            +
                              when false then {}
         | 
| 61 | 
            +
                              when nil, true then nil
         | 
| 62 | 
            +
                              when Array then v.each_with_object({}){|i,d| d[i] = true}
         | 
| 63 | 
            +
                              when Hash then v
         | 
| 64 | 
            +
                              else raise "Invalid generates value in #{k.inspect}: #{v.inspect}"
         | 
| 65 | 
            +
                              end
         | 
| 66 | 
            +
                          end
         | 
| 67 | 
            +
                        when Array then t['generates'].each_with_object({}){|i,d| d[i] = true}
         | 
| 68 | 
            +
                        else raise "Invalid generates: #{t['generates'].inspect}"
         | 
| 69 | 
            +
                        end
         | 
| 52 70 | 
             
                    end
         | 
| 53 71 | 
             
                  end
         | 
| 54 72 |  | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            -%>
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            type <%= type.name %>Binder interface {
         | 
| 7 | 
            +
            	Query(q *datastore.Query) *datastore.Query
         | 
| 8 | 
            +
            	Visible(m *<%= model.qualified_name %>) bool
         | 
| 9 | 
            +
            	Prepare(m *<%= model.qualified_name %>)
         | 
| 10 | 
            +
            }
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            -%>
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            type <%= type.name %>Hook interface {
         | 
| 7 | 
            +
            	AfterQuery(ctx context.Context, m *[]*<%= model.qualified_name %>) error
         | 
| 8 | 
            +
            	AfterGet(ctx context.Context, m *<%= model.qualified_name %>) error
         | 
| 9 | 
            +
            	BeforeValidation(ctx context.Context, m *<%= model.qualified_name %>) error
         | 
| 10 | 
            +
            }
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 6 | 
            +
            -%>
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            func (s *<%= type.name %>) AllBy(ctx context.Context, q *datastore.Query) ([]*<%= model.qualified_name %>, error) {
         | 
| 9 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 10 | 
            +
            	r := []*<%= model.qualified_name %>{}
         | 
| 11 | 
            +
            	_, err := g.GetAll(q.EventualConsistency(), &r)
         | 
| 12 | 
            +
            	if err != nil {
         | 
| 13 | 
            +
            		log.Errorf(ctx, "Failed to AllBy <%= model.qualified_name %> because of %v\n", err)
         | 
| 14 | 
            +
            		return nil, err
         | 
| 15 | 
            +
            	}
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	if s.Hook != nil {
         | 
| 18 | 
            +
            		if err := s.Hook.AfterQuery(ctx, &r); err != nil {
         | 
| 19 | 
            +
            			return nil, err
         | 
| 20 | 
            +
            		}
         | 
| 21 | 
            +
            	}
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            	return r, nil
         | 
| 24 | 
            +
            }
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            -%>
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            func (s *<%= type.name %>) FirstBy(ctx context.Context, q *datastore.Query) (*<%= model.qualified_name %>, error) {
         | 
| 8 | 
            +
            	r, err := s.AllBy(ctx, q.Limit(1))
         | 
| 9 | 
            +
            	if err != nil {
         | 
| 10 | 
            +
            		return nil, err
         | 
| 11 | 
            +
            	}
         | 
| 12 | 
            +
            	if len(r) > 0 {
         | 
| 13 | 
            +
            		return r[0], nil
         | 
| 14 | 
            +
            	} else {
         | 
| 15 | 
            +
            		return nil, nil
         | 
| 16 | 
            +
            	}
         | 
| 17 | 
            +
            }
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 5 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 6 | 
            +
            -%>
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            func (s *<%= type.name %>) CountBy(ctx context.Context, q *datastore.Query) (int, error) {
         | 
| 9 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 10 | 
            +
            	c, err := g.Count(q)
         | 
| 11 | 
            +
            	if err != nil {
         | 
| 12 | 
            +
            		log.Errorf(ctx, "Failed to count <%= model.qualified_name %> with %v because of %v\n", q, err)
         | 
| 13 | 
            +
            		return 0, err
         | 
| 14 | 
            +
            	}
         | 
| 15 | 
            +
            	return c, nil
         | 
| 16 | 
            +
            }
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            -%>
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            func (s *<%= type.name %>) ByID(ctx context.Context, iD int64) (*<%= model.qualified_name %>, error) {
         | 
| 7 | 
            +
            	r := <%= model.qualified_name %>{ID: iD}
         | 
| 8 | 
            +
            	err := s.Get(ctx, &r)
         | 
| 9 | 
            +
            	if err != nil {
         | 
| 10 | 
            +
            		return nil, err
         | 
| 11 | 
            +
            	}
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            	if s.Hook != nil {
         | 
| 14 | 
            +
            		if err := s.Hook.AfterGet(ctx, &r); err != nil {
         | 
| 15 | 
            +
            			return nil, err
         | 
| 16 | 
            +
            		}
         | 
| 17 | 
            +
            	}
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            	return &r, nil
         | 
| 20 | 
            +
            }
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 6 | 
            +
            -%>
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            func (s *<%= type.name %>) ByKey(ctx context.Context, key *datastore.Key) (*<%= model.qualified_name %>, error) {
         | 
| 9 | 
            +
            	if err := s.IsValidKey(ctx, key); err != nil {
         | 
| 10 | 
            +
            		log.Errorf(ctx, "<%= type.name %>.ByKey got Invalid key: %v because of %v\n", key, err)
         | 
| 11 | 
            +
            		return nil, err
         | 
| 12 | 
            +
            	}
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            	return s.ByID(ctx, key.IntID())
         | 
| 15 | 
            +
            }
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 6 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 7 | 
            +
            -%>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            func (s *<%= type.name %>) Get(ctx context.Context, m *<%= model.qualified_name %>) error {
         | 
| 10 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 11 | 
            +
            	err := g.Get(m)
         | 
| 12 | 
            +
            	if err != nil {
         | 
| 13 | 
            +
            		log.Errorf(ctx, "Failed to Get <%= model.qualified_name %> because of %v\n", err)
         | 
| 14 | 
            +
            		return err
         | 
| 15 | 
            +
            	}
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	if s.Binder != nil && !s.Binder.Visible(m) {
         | 
| 18 | 
            +
            		return datastore.ErrNoSuchEntity
         | 
| 19 | 
            +
            	}
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            	return nil
         | 
| 22 | 
            +
            }
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import 'fmt'
         | 
| 4 | 
            +
            import model.package
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 6 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 7 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 8 | 
            +
            -%>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            func (s *<%= type.name %>) IsValidKey(ctx context.Context, key *datastore.Key) error {
         | 
| 11 | 
            +
            	if key == nil {
         | 
| 12 | 
            +
            		return fmt.Errorf("key is nil")
         | 
| 13 | 
            +
            	}
         | 
| 14 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 15 | 
            +
            	expected := g.Kind(&<%= model.qualified_name %>{})
         | 
| 16 | 
            +
            	if key.Kind() != expected {
         | 
| 17 | 
            +
            		return fmt.Errorf("key kind must be %s but was %s", expected, key.Kind())
         | 
| 18 | 
            +
            	}
         | 
| 19 | 
            +
            	return nil
         | 
| 20 | 
            +
            }
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 6 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 7 | 
            +
            -%>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            func (s *<%= type.name %>) Exist(ctx context.Context, m *<%= model.qualified_name %>) (bool, error) {
         | 
| 10 | 
            +
            	if m.ID == 0 {
         | 
| 11 | 
            +
            		return false, nil
         | 
| 12 | 
            +
            	}
         | 
| 13 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 14 | 
            +
            	key, err := g.KeyError(m)
         | 
| 15 | 
            +
            	if err != nil {
         | 
| 16 | 
            +
            		log.Errorf(ctx, "Failed to Get Key of %v because of %v\n", m, err)
         | 
| 17 | 
            +
            		return false, err
         | 
| 18 | 
            +
            	}
         | 
| 19 | 
            +
            	_, err = s.ByKey(ctx, key)
         | 
| 20 | 
            +
            	if err == datastore.ErrNoSuchEntity {
         | 
| 21 | 
            +
            		return false, nil
         | 
| 22 | 
            +
            	} else if err != nil {
         | 
| 23 | 
            +
            		log.Errorf(ctx, "Failed to get existance of %v because of %v\n", m, err)
         | 
| 24 | 
            +
            		return false, err
         | 
| 25 | 
            +
            	} else {
         | 
| 26 | 
            +
            		return true, nil
         | 
| 27 | 
            +
            	}
         | 
| 28 | 
            +
            }
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import 'fmt'
         | 
| 4 | 
            +
            import model.package
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 6 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 7 | 
            +
            -%>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            func (s *<%= type.name %>) Create(ctx context.Context, m *<%= model.qualified_name %>) (*datastore.Key, error) {
         | 
| 10 | 
            +
            	if err := m.PrepareToCreate(); err != nil {
         | 
| 11 | 
            +
            		return nil, err
         | 
| 12 | 
            +
            	}
         | 
| 13 | 
            +
            	return s.PutWith(ctx, m, func() error {
         | 
| 14 | 
            +
            		exist, err := s.Exist(ctx, m)
         | 
| 15 | 
            +
            		if err != nil {
         | 
| 16 | 
            +
            			return err
         | 
| 17 | 
            +
            		}
         | 
| 18 | 
            +
            		if exist {
         | 
| 19 | 
            +
            			log.Errorf(ctx, "Failed to create %v because of another entity has same key\n", m)
         | 
| 20 | 
            +
            			return fmt.Errorf("Duplicate ID error: %q of %v\n", m.ID, m)
         | 
| 21 | 
            +
            		}
         | 
| 22 | 
            +
            		return nil
         | 
| 23 | 
            +
            	})
         | 
| 24 | 
            +
            }
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import 'fmt'
         | 
| 4 | 
            +
            import model.package
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 6 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 7 | 
            +
            -%>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            func (s *<%= type.name %>) Update(ctx context.Context, m *<%= model.qualified_name %>) (*datastore.Key, error) {
         | 
| 10 | 
            +
            	if err := m.PrepareToUpdate(); err != nil {
         | 
| 11 | 
            +
            		return nil, err
         | 
| 12 | 
            +
            	}
         | 
| 13 | 
            +
            	return s.PutWith(ctx, m, func() error {
         | 
| 14 | 
            +
            		exist, err := s.Exist(ctx, m)
         | 
| 15 | 
            +
            		if err != nil {
         | 
| 16 | 
            +
            			return err
         | 
| 17 | 
            +
            		}
         | 
| 18 | 
            +
            		if !exist {
         | 
| 19 | 
            +
            			log.Errorf(ctx, "Failed to update %v because it doesn't exist\n", m)
         | 
| 20 | 
            +
            			return fmt.Errorf("No data to update %q of %v\n", m.ID, m)
         | 
| 21 | 
            +
            		}
         | 
| 22 | 
            +
            		return nil
         | 
| 23 | 
            +
            	})
         | 
| 24 | 
            +
            }
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            -%>
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            func (s *<%= type.name %>) PutWith(ctx context.Context, m *<%= model.qualified_name %>, f func() error) (*datastore.Key, error) {
         | 
| 8 | 
            +
            	if s.Binder != nil {
         | 
| 9 | 
            +
            		s.Binder.Prepare(m)
         | 
| 10 | 
            +
            	}
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            	if s.Hook != nil {
         | 
| 13 | 
            +
            		if err := s.Hook.BeforeValidation(ctx, m); err != nil {
         | 
| 14 | 
            +
            			return nil, err
         | 
| 15 | 
            +
            		}
         | 
| 16 | 
            +
            	}
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            	if err := s.Validate(ctx, m); err != nil {
         | 
| 19 | 
            +
            		return nil, err
         | 
| 20 | 
            +
            	}
         | 
| 21 | 
            +
            	if f != nil {
         | 
| 22 | 
            +
            		if err := f(); err != nil {
         | 
| 23 | 
            +
            			return nil, err
         | 
| 24 | 
            +
            		}
         | 
| 25 | 
            +
            	}
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            	return s.Put(ctx, m)
         | 
| 28 | 
            +
            }
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/datastore'
         | 
| 5 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 6 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 7 | 
            +
            -%>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            func (s *<%= type.name %>) Put(ctx context.Context, m *<%= model.qualified_name %>) (*datastore.Key, error) {
         | 
| 10 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 11 | 
            +
            	key, err := g.Put(m)
         | 
| 12 | 
            +
            	if err != nil {
         | 
| 13 | 
            +
            		log.Errorf(ctx, "Failed to Put %v because of %v\n", m, err)
         | 
| 14 | 
            +
            		return nil, err
         | 
| 15 | 
            +
            	}
         | 
| 16 | 
            +
            	return key, nil
         | 
| 17 | 
            +
            }
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            import 'google.golang.org/appengine/log'
         | 
| 5 | 
            +
            import 'github.com/mjibson/goon'
         | 
| 6 | 
            +
            -%>
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            func (s *<%= type.name %>) Delete(ctx context.Context, m *<%= model.qualified_name %>) error {
         | 
| 9 | 
            +
            	g := goon.FromContext(ctx)
         | 
| 10 | 
            +
            	key, err := g.KeyError(m)
         | 
| 11 | 
            +
            	if err != nil {
         | 
| 12 | 
            +
            		log.Errorf(ctx, "Failed to Get key of %v because of %v\n", m, err)
         | 
| 13 | 
            +
            		return err
         | 
| 14 | 
            +
            	}
         | 
| 15 | 
            +
            	if err := g.Delete(key); err != nil {
         | 
| 16 | 
            +
            		log.Errorf(ctx, "Failed to Delete %v because of %v\n", m, err)
         | 
| 17 | 
            +
            		return err
         | 
| 18 | 
            +
            	}
         | 
| 19 | 
            +
            	return nil
         | 
| 20 | 
            +
            }
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import 'fmt'
         | 
| 4 | 
            +
            import model.package
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            validation_error = packages.type_for('ValidationError')
         | 
| 7 | 
            +
            raise "ValidationError not found" unless validation_error
         | 
| 8 | 
            +
            import validation_error.package
         | 
| 9 | 
            +
            -%>
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            func (s *<%= type.name %>) ValidateUniqueness(ctx context.Context, m *<%= model.qualified_name %>) error {
         | 
| 12 | 
            +
            	conditions := map[string]interface{}{
         | 
| 13 | 
            +
            <%- model.fields.select(&:unique).each do |field| -%>
         | 
| 14 | 
            +
            		"<%= field.name %>": m.<%= field.name %>,
         | 
| 15 | 
            +
            <%- end -%>
         | 
| 16 | 
            +
              }
         | 
| 17 | 
            +
            	for field, value := range conditions {
         | 
| 18 | 
            +
            		q := s.Query().Filter(field+" =", value)
         | 
| 19 | 
            +
            		c, err := s.CountBy(ctx, q)
         | 
| 20 | 
            +
            		if err != nil {
         | 
| 21 | 
            +
            			return err
         | 
| 22 | 
            +
            		}
         | 
| 23 | 
            +
            		b := 0
         | 
| 24 | 
            +
            		if m.IsPersisted() {
         | 
| 25 | 
            +
            			b = 1
         | 
| 26 | 
            +
            		}
         | 
| 27 | 
            +
            		if c > b {
         | 
| 28 | 
            +
            			return &<%= validation_error.qualified_name %>{
         | 
| 29 | 
            +
            				Field:   field,
         | 
| 30 | 
            +
            				Message: fmt.Sprintf("%v has already been taken", value),
         | 
| 31 | 
            +
            			}
         | 
| 32 | 
            +
            		}
         | 
| 33 | 
            +
            	}
         | 
| 34 | 
            +
            	return nil
         | 
| 35 | 
            +
            }
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            <%-
         | 
| 2 | 
            +
            import 'context'
         | 
| 3 | 
            +
            import model.package
         | 
| 4 | 
            +
            -%>
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            func (s *<%= type.name %>) Validate(ctx context.Context, m *<%= model.qualified_name %>) error {
         | 
| 7 | 
            +
            	if err := m.Validate(ctx); err != nil {
         | 
| 8 | 
            +
            		return err
         | 
| 9 | 
            +
            	}
         | 
| 10 | 
            +
            	if err := s.ValidateUniqueness(ctx, m); err != nil {
         | 
| 11 | 
            +
            		return err
         | 
| 12 | 
            +
            	}
         | 
| 13 | 
            +
            	return nil
         | 
| 14 | 
            +
            }
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: goon_model_gen
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - akm
         | 
| @@ -143,6 +143,10 @@ files: | |
| 143 143 | 
             
            - exe/goon_model_gen
         | 
| 144 144 | 
             
            - goon_model_gen.gemspec
         | 
| 145 145 | 
             
            - lib/goon_model_gen.rb
         | 
| 146 | 
            +
            - lib/goon_model_gen/builder/abstract_builder.rb
         | 
| 147 | 
            +
            - lib/goon_model_gen/builder/model_builder.rb
         | 
| 148 | 
            +
            - lib/goon_model_gen/builder/store_builder.rb
         | 
| 149 | 
            +
            - lib/goon_model_gen/builder/validation_builder.rb
         | 
| 146 150 | 
             
            - lib/goon_model_gen/cli.rb
         | 
| 147 151 | 
             
            - lib/goon_model_gen/config.rb
         | 
| 148 152 | 
             
            - lib/goon_model_gen/generator.rb
         | 
| @@ -160,7 +164,6 @@ files: | |
| 160 164 | 
             
            - lib/goon_model_gen/golang/sentence.rb
         | 
| 161 165 | 
             
            - lib/goon_model_gen/golang/struct.rb
         | 
| 162 166 | 
             
            - lib/goon_model_gen/golang/type.rb
         | 
| 163 | 
            -
            - lib/goon_model_gen/model_builder.rb
         | 
| 164 167 | 
             
            - lib/goon_model_gen/source/context.rb
         | 
| 165 168 | 
             
            - lib/goon_model_gen/source/contextual.rb
         | 
| 166 169 | 
             
            - lib/goon_model_gen/source/enum.rb
         | 
| @@ -187,6 +190,31 @@ files: | |
| 187 190 | 
             
            - lib/goon_model_gen/templates/model/goon/06_IsPersisted.go.erb
         | 
| 188 191 | 
             
            - lib/goon_model_gen/templates/model/slice/01_base.go.erb
         | 
| 189 192 | 
             
            - lib/goon_model_gen/templates/model/struct/01_struct.go.erb
         | 
| 193 | 
            +
            - lib/goon_model_gen/templates/store/goon/01_Binder.go.erb
         | 
| 194 | 
            +
            - lib/goon_model_gen/templates/store/goon/02_Hook.go.erb
         | 
| 195 | 
            +
            - lib/goon_model_gen/templates/store/goon/03_struct.go.erb
         | 
| 196 | 
            +
            - lib/goon_model_gen/templates/store/goon/04_KindName.go.erb
         | 
| 197 | 
            +
            - lib/goon_model_gen/templates/store/goon/05_Query.go.erb
         | 
| 198 | 
            +
            - lib/goon_model_gen/templates/store/goon/06_Run.go.erb
         | 
| 199 | 
            +
            - lib/goon_model_gen/templates/store/goon/07_All.go.erb
         | 
| 200 | 
            +
            - lib/goon_model_gen/templates/store/goon/08_AllBy.go.erb
         | 
| 201 | 
            +
            - lib/goon_model_gen/templates/store/goon/09_Select.go.erb
         | 
| 202 | 
            +
            - lib/goon_model_gen/templates/store/goon/10_FirstBy.go.erb
         | 
| 203 | 
            +
            - lib/goon_model_gen/templates/store/goon/11_CountBy.go.erb
         | 
| 204 | 
            +
            - lib/goon_model_gen/templates/store/goon/12_ByID.go.erb
         | 
| 205 | 
            +
            - lib/goon_model_gen/templates/store/goon/13_ByKey.go.erb
         | 
| 206 | 
            +
            - lib/goon_model_gen/templates/store/goon/14_Get.go.erb
         | 
| 207 | 
            +
            - lib/goon_model_gen/templates/store/goon/15_IsValidKey.go.erb
         | 
| 208 | 
            +
            - lib/goon_model_gen/templates/store/goon/16_Exist.go.erb
         | 
| 209 | 
            +
            - lib/goon_model_gen/templates/store/goon/17_Create.go.erb
         | 
| 210 | 
            +
            - lib/goon_model_gen/templates/store/goon/18_Update.go.erb
         | 
| 211 | 
            +
            - lib/goon_model_gen/templates/store/goon/19_PutWith.go.erb
         | 
| 212 | 
            +
            - lib/goon_model_gen/templates/store/goon/20_Put.go.erb
         | 
| 213 | 
            +
            - lib/goon_model_gen/templates/store/goon/21_Delete.go.erb
         | 
| 214 | 
            +
            - lib/goon_model_gen/templates/store/goon/22_ValidateUniqueness.go.erb
         | 
| 215 | 
            +
            - lib/goon_model_gen/templates/store/goon/23_Validate.go.erb
         | 
| 216 | 
            +
            - lib/goon_model_gen/templates/validation/error/01_struct.go.erb
         | 
| 217 | 
            +
            - lib/goon_model_gen/templates/validation/error/02_Error.go.erb
         | 
| 190 218 | 
             
            - lib/goon_model_gen/version.rb
         | 
| 191 219 | 
             
            homepage: https://github.com/akm/goon_model_gen
         | 
| 192 220 | 
             
            licenses:
         | 
| @@ -1,137 +0,0 @@ | |
| 1 | 
            -
            require "goon_model_gen"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require "goon_model_gen/source/context"
         | 
| 4 | 
            -
            require "goon_model_gen/source/struct"
         | 
| 5 | 
            -
            require "goon_model_gen/source/enum"
         | 
| 6 | 
            -
            require "goon_model_gen/source/named_slice"
         | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
            require "goon_model_gen/golang/package"
         | 
| 10 | 
            -
            require "goon_model_gen/golang/packages"
         | 
| 11 | 
            -
            require "goon_model_gen/golang/datastore_supported"
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            require "active_support/core_ext/string"
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            module GoonModelGen
         | 
| 16 | 
            -
              class ModelBuilder
         | 
| 17 | 
            -
                attr_reader :base_package_path
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                def initialize(base_package_path)
         | 
| 20 | 
            -
                  @base_package_path = base_package_path
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
                # @param context [Source::Context]
         | 
| 25 | 
            -
                # @return [Golang::Packages]
         | 
| 26 | 
            -
                def build(context)
         | 
| 27 | 
            -
                  Golang::Packages.new.tap do |r|
         | 
| 28 | 
            -
                    build_sentences = []
         | 
| 29 | 
            -
                    context.files.each do |f|
         | 
| 30 | 
            -
                      package_path = File.join(base_package_path, f.basename)
         | 
| 31 | 
            -
                      pkg, procs = build_package(package_path, f.types)
         | 
| 32 | 
            -
                      r << pkg
         | 
| 33 | 
            -
                      build_sentences.concat(procs)
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
                    r.resolve_type_names(Golang::DatastoreSupported.packages)
         | 
| 36 | 
            -
                    build_sentences.each(&:call)
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                # @param package_path [String]
         | 
| 41 | 
            -
                # @param types [Array<Source::Type>]
         | 
| 42 | 
            -
                # @return [Golang::Package, Array<Proc>]
         | 
| 43 | 
            -
                def build_package(package_path, types)
         | 
| 44 | 
            -
                  procs = []
         | 
| 45 | 
            -
                  pkg = Golang::Package.new(package_path).tap do |pkg|
         | 
| 46 | 
            -
                    types.each do |t|
         | 
| 47 | 
            -
                      case t
         | 
| 48 | 
            -
                      when Source::Struct then
         | 
| 49 | 
            -
                        go_type = build_struct(t, pkg)
         | 
| 50 | 
            -
                        template = (t.id_name && t.id_type) ? "model/goon" : "model/struct"
         | 
| 51 | 
            -
                        procs << Proc.new{ build_sentences(template, t, go_type) }
         | 
| 52 | 
            -
                      when Source::Enum then
         | 
| 53 | 
            -
                        go_type = pkg.new_enum(t.name, t.base_type, t.map)
         | 
| 54 | 
            -
                        procs << Proc.new{ build_sentences("model/enum", t, go_type) }
         | 
| 55 | 
            -
                      when Source::NamedSlice then
         | 
| 56 | 
            -
                        go_type = pkg.new_named_slice(t.name, t.base_type_name)
         | 
| 57 | 
            -
                        procs << Proc.new{ build_sentences("model/slice", t, go_type) }
         | 
| 58 | 
            -
                      else
         | 
| 59 | 
            -
                        raise "Unsupported type #{t.class.name} #{t.inspect}"
         | 
| 60 | 
            -
                      end
         | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
                  end
         | 
| 63 | 
            -
                  return pkg, procs
         | 
| 64 | 
            -
                end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                # @param t [Source::Struct]
         | 
| 67 | 
            -
                # @param pkg [Golang::Package]
         | 
| 68 | 
            -
                # @return [Golang::Struct]
         | 
| 69 | 
            -
                def build_struct(t, pkg)
         | 
| 70 | 
            -
                  pkg.new_struct(t.name).tap do |s|
         | 
| 71 | 
            -
                    s.ref_name = t.ref_name
         | 
| 72 | 
            -
                    if t.id_name && t.id_type
         | 
| 73 | 
            -
                      tags = {
         | 
| 74 | 
            -
                        'goon' => ['id'],
         | 
| 75 | 
            -
                        'datastore' => ['-'],
         | 
| 76 | 
            -
                        'json' => [t.id_name.underscore],
         | 
| 77 | 
            -
                      }
         | 
| 78 | 
            -
                      s.new_field(t.id_name, t.id_type, tags, goon_id: true)
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
                    t.fields.each do |f|
         | 
| 81 | 
            -
                      s.new_field(f.name, f.type_name, f.build_tags)
         | 
| 82 | 
            -
                    end
         | 
| 83 | 
            -
                  end
         | 
| 84 | 
            -
                end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
                # @param template_base [string]
         | 
| 88 | 
            -
                # @param t [Source::Struct]
         | 
| 89 | 
            -
                # @param go_type [Golang::Type]
         | 
| 90 | 
            -
                def build_sentences(template_base, t, go_type)
         | 
| 91 | 
            -
                  m2t = method_to_template_for(template_base)
         | 
| 92 | 
            -
                  t.generators ||= default_generators_for(template_base)
         | 
| 93 | 
            -
                  t.generators.each do |name, suffix|
         | 
| 94 | 
            -
                    next if !suffix
         | 
| 95 | 
            -
                    template = m2t[name]
         | 
| 96 | 
            -
                    parts = [t.name.underscore]
         | 
| 97 | 
            -
                    custom_suffix = false
         | 
| 98 | 
            -
                    if suffix.is_a?(String)
         | 
| 99 | 
            -
                      parts << suffix
         | 
| 100 | 
            -
                      custom_suffix = true
         | 
| 101 | 
            -
                    end
         | 
| 102 | 
            -
                    filename = parts.join('_') << '.go'
         | 
| 103 | 
            -
                    go_type.package.find_or_new_file(filename).tap do |file|
         | 
| 104 | 
            -
                      file.custom_suffix = custom_suffix
         | 
| 105 | 
            -
                      file.new_sentence(File.join(template_base, template), go_type)
         | 
| 106 | 
            -
                    end
         | 
| 107 | 
            -
                  end
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                def default_generators_for(template_base)
         | 
| 111 | 
            -
                  method_to_template_for(template_base).keys.
         | 
| 112 | 
            -
                    each_with_object({}){|name, d| d[name] = true }
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                def method_to_template_map
         | 
| 116 | 
            -
                  @method_to_template_map ||= {}
         | 
| 117 | 
            -
                end
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                def method_to_template_for(template_base)
         | 
| 120 | 
            -
                  method_to_template_map[template_base] ||=
         | 
| 121 | 
            -
                    begin
         | 
| 122 | 
            -
                      templates_for(template_base).each_with_object({}) do |filename, d|
         | 
| 123 | 
            -
                        m = filename.sub(/\A\d+\_/, '').sub(/\.go\.erb\z/, '')
         | 
| 124 | 
            -
                        d[m] = filename
         | 
| 125 | 
            -
                      end
         | 
| 126 | 
            -
                    end
         | 
| 127 | 
            -
                end
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                def templates_for(template_base)
         | 
| 130 | 
            -
                  base_dir = File.join(File.expand_path('../templates', __FILE__), template_base)
         | 
| 131 | 
            -
                  Dir.chdir(base_dir) do
         | 
| 132 | 
            -
                    Dir.glob('*.go.erb')
         | 
| 133 | 
            -
                  end
         | 
| 134 | 
            -
                end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
              end
         | 
| 137 | 
            -
            end
         |