go-on-rails 0.0.1 → 0.0.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/README.md +44 -18
- data/lib/generators/gor/go_on_rails/association.rb +35 -35
- data/lib/generators/gor/go_on_rails/converter.rb +77 -77
- data/lib/generators/gor/gor_generator.rb +73 -66
- data/lib/generators/gor/templates/gor_model.go.erb +82 -34
- data/lib/tasks/gor.rake +14 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2839e5d56004e5a3974cb77427e5c3438ef3c5df
|
4
|
+
data.tar.gz: 24a489fcc1fac898832b6d1269a287d0c88d7a89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6107aa404f72156d23e5191b0414c5d5c6d391eaca61e68cf48031f17d55c627fe4c30e8f46a2aeb6939c850835e2c83504354155ad369ffd03f7a64f443a7c5
|
7
|
+
data.tar.gz: 3a3a53bc94bbc3d8ce3b9d48b8d6140b8e1e2b19699843d13ed97206cdc9345b809330092b350cbf66c5afa97de2bba5ee99b5b582cd2cfde5c456f3edbe9032
|
data/README.md
CHANGED
@@ -1,41 +1,67 @@
|
|
1
1
|
go-on-rails
|
2
2
|
====
|
3
3
|
|
4
|
+
## Prerequisites
|
5
|
+
|
6
|
+
* Rails development environment
|
7
|
+
* Golang development environment
|
8
|
+
|
4
9
|
## Installation
|
5
10
|
|
6
11
|
Add this line to your application's Gemfile:
|
7
12
|
|
8
|
-
|
13
|
+
```ruby
|
9
14
|
gem 'go-on-rails'
|
10
|
-
|
15
|
+
```
|
11
16
|
|
12
17
|
And then execute:
|
13
|
-
|
18
|
+
```bash
|
14
19
|
$ bundle
|
15
|
-
|
20
|
+
```
|
16
21
|
|
17
22
|
Or install it yourself as:
|
18
|
-
|
23
|
+
```bash
|
19
24
|
$ gem install go-on-rails
|
20
|
-
|
21
|
-
|
25
|
+
```
|
22
26
|
## Usage
|
23
27
|
|
24
|
-
go-on-rails
|
28
|
+
go-on-rails aims at three scenarios:
|
29
|
+
|
30
|
+
1. Integrate some api written in Golang to existed Rails app for high performance
|
31
|
+
2. Use your farmiliar Rails tools to develope and manage a Golang app project
|
32
|
+
3. Convert a *not very complicated* Rails app to Golang equivalent
|
33
|
+
|
34
|
+
One or more examples will be given later on.
|
35
|
+
|
36
|
+
So you must have a Rails app or to create one before you can try go-on-rails generator to convert a Rails app to Golang codes.
|
37
|
+
|
38
|
+
You can just run the command to convert the application:
|
39
|
+
|
40
|
+
```bash
|
41
|
+
rails g gor [dev(elopment) | pro(duction) | test] [-m model_a model_b model_c ...]
|
42
|
+
```
|
43
|
+
|
44
|
+
Then a directory named "go_app" with Golang codes will be generated under your Rails app root path.
|
45
|
+
|
46
|
+
Install the dependent Golang packages:
|
47
|
+
|
48
|
+
```bash
|
49
|
+
rails gor:deps
|
50
|
+
```
|
25
51
|
|
26
|
-
|
52
|
+
Then change to the "go_app" directory and run:
|
27
53
|
|
28
|
-
|
54
|
+
```bash
|
55
|
+
go run main.go
|
56
|
+
```
|
29
57
|
|
30
|
-
|
31
|
-
rails g gor [dev(elopment) | pro(duction) | test]
|
32
|
-
``
|
58
|
+
You can visit the page in http://localhost:3000 by default.
|
33
59
|
|
34
|
-
|
60
|
+
More command details about go-on-rails generator:
|
35
61
|
|
36
|
-
|
62
|
+
```bash
|
37
63
|
rails g gor --help
|
38
|
-
|
64
|
+
```
|
39
65
|
|
40
66
|
And the gem is still under development, so there're a lot of known issues.
|
41
67
|
|
@@ -44,9 +70,9 @@ And the gem is still under development, so there're a lot of known issues.
|
|
44
70
|
* the generated Golang codes includes the association between models, basic relations like has_many, has_one, belongs_to have been supported
|
45
71
|
* so some association functions is available
|
46
72
|
* and the :dependent action is triggered when destroying some related model
|
47
|
-
* but the :through keyword not supported yet
|
48
73
|
* databases specific functions between mysql, postgres are not covered yet
|
49
|
-
* model callbacks
|
74
|
+
* model callbacks is not available
|
75
|
+
* sql.NullType not supported yet, so you'd better set all columns "not null" with a default value in the migration, such as "" default for string and text typed column, and 0 default for int, etc, that's consistent with Golang's zero value specification.
|
50
76
|
|
51
77
|
Really a lot...
|
52
78
|
|
@@ -1,41 +1,41 @@
|
|
1
1
|
module GoOnRails
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
class Association
|
3
|
+
def initialize(klass, models, max_col_size, max_type_size)
|
4
|
+
@klass = klass
|
5
|
+
@models = models
|
6
|
+
@max_col_size = max_col_size
|
7
|
+
@max_type_size = max_type_size
|
8
|
+
end
|
9
|
+
attr_reader :klass, :models, :max_col_size, :max_type_size
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
11
|
+
def get_schema_info
|
12
|
+
info = {struct_body: "", assoc_info: {has_many: {}, has_one: {}, belongs_to: {}}}
|
13
|
+
self.klass.reflect_on_all_associations.each do |assoc|
|
14
|
+
tags = ["json:\"#{assoc.name.to_s},omitempty\" db:\"#{assoc.name.to_s}\""]
|
15
|
+
case assoc.macro
|
16
|
+
when :has_many
|
17
|
+
col_name = assoc.name.to_s.camelize
|
18
|
+
class_name = assoc.name.to_s.singularize.camelize
|
19
|
+
unless assoc.options.empty?
|
20
|
+
class_name = assoc.options[:class_name] if assoc.options.key? :class_name
|
21
|
+
end
|
22
|
+
type_name = "[]#{class_name}"
|
23
|
+
info[:assoc_info][:has_many][col_name] = {class_name: class_name}
|
24
|
+
info[:assoc_info][:has_many][col_name].merge!(assoc.options) unless assoc.options.empty?
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
38
|
-
info
|
26
|
+
when :has_one, :belongs_to
|
27
|
+
col_name = class_name = assoc.name.to_s.camelize
|
28
|
+
class_name = assoc.options[:class_name] if assoc.options.key? :class_name unless assoc.options.empty?
|
29
|
+
type_name = class_name
|
30
|
+
info[:assoc_info][assoc.macro][col_name] = {class_name: class_name}
|
31
|
+
info[:assoc_info][assoc.macro][col_name].merge!(assoc.options) unless assoc.options.empty?
|
32
|
+
end
|
33
|
+
if col_name && type_name && (self.models.include? class_name)
|
34
|
+
format = "\t%-#{max_col_size}.#{max_col_size+2}s%-#{max_type_size}.#{max_type_size}s`%s`\n"
|
35
|
+
info[:struct_body] << sprintf(format, col_name, type_name, tags.join(" "))
|
39
36
|
end
|
37
|
+
end
|
38
|
+
info
|
40
39
|
end
|
40
|
+
end
|
41
41
|
end
|
@@ -1,97 +1,97 @@
|
|
1
1
|
module GoOnRails
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def convert
|
26
|
-
get_schema_info
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def get_schema_info
|
32
|
-
struct_info = {col_names: [], timestamp_cols: [], has_datetime_type: false, struct_body: ""}
|
2
|
+
class Convertor
|
3
|
+
TYPE_MAP = {
|
4
|
+
"string" => "string",
|
5
|
+
"text" => "string",
|
6
|
+
"boolean" => "bool",
|
7
|
+
"integer(1)" => "int8",
|
8
|
+
"integer(2)" => "int16",
|
9
|
+
"integer(3)" => "int32",
|
10
|
+
"integer(4)" => "int64",
|
11
|
+
"integer(8)" => "int64",
|
12
|
+
"float" => "float64",
|
13
|
+
"datetime" => "time.Time",
|
14
|
+
"date" => "time.Time"
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(klass, models, option = {})
|
18
|
+
@klass = klass
|
19
|
+
@models = models
|
20
|
+
@max_col_size = 0
|
21
|
+
@max_type_size = 0
|
22
|
+
end
|
23
|
+
attr_accessor :klass, :models, :max_col_size, :max_type_size
|
33
24
|
|
34
|
-
|
35
|
-
|
25
|
+
def convert
|
26
|
+
get_schema_info
|
27
|
+
end
|
36
28
|
|
37
|
-
|
38
|
-
tags = []
|
29
|
+
private
|
39
30
|
|
40
|
-
|
41
|
-
|
31
|
+
def get_schema_info
|
32
|
+
struct_info = {col_names: [], timestamp_cols: [], has_datetime_type: false, struct_body: ""}
|
42
33
|
|
43
|
-
|
44
|
-
|
45
|
-
if col_type == "datetime" and %w(created_at updated_at).include? col.name
|
46
|
-
struct_info[:timestamp_cols] << col.name
|
47
|
-
end
|
34
|
+
self.max_col_size = get_max_col_size
|
35
|
+
self.max_type_size = get_max_type_size
|
48
36
|
|
49
|
-
|
50
|
-
|
51
|
-
type = TYPE_MAP["integer(#{col.limit})"] || "int64"
|
52
|
-
type = "u#{type}" if col.sql_type.match("unsigned").present?
|
53
|
-
else
|
54
|
-
type = TYPE_MAP[col_type] || "string"
|
55
|
-
end
|
37
|
+
self.klass.columns.each_with_index do |col, index|
|
38
|
+
tags = []
|
56
39
|
|
57
|
-
|
58
|
-
|
59
|
-
struct_info[:struct_body] << sprintf(format, col.name.camelize, type, tags.join(" "))
|
60
|
-
end
|
40
|
+
# add struct tag
|
41
|
+
tags << struct_tag(col)
|
61
42
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
43
|
+
col_type = col.type.to_s
|
44
|
+
struct_info[:has_datetime_type] = true if %w(datetime time).include? col_type
|
45
|
+
if col_type == "datetime" and %w(created_at updated_at).include? col.name
|
46
|
+
struct_info[:timestamp_cols] << col.name
|
66
47
|
end
|
67
48
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
49
|
+
case col_type
|
50
|
+
when "integer"
|
51
|
+
type = TYPE_MAP["integer(#{col.limit})"] || "int64"
|
52
|
+
type = "u#{type}" if col.sql_type.match("unsigned").present?
|
53
|
+
else
|
54
|
+
type = TYPE_MAP[col_type] || "string"
|
73
55
|
end
|
74
56
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
57
|
+
format = (index == 0 ? "" : "\t") + "%-#{self.max_col_size}.#{self.max_col_size}s%-#{self.max_type_size}.#{self.max_type_size}s`%s`\n"
|
58
|
+
struct_info[:col_names] << col.name unless col.name == "id"
|
59
|
+
struct_info[:struct_body] << sprintf(format, col.name.camelize, type, tags.join(" "))
|
60
|
+
end
|
80
61
|
|
81
|
-
|
82
|
-
|
83
|
-
|
62
|
+
assoc = get_associations
|
63
|
+
struct_info[:struct_body] << assoc[:struct_body]
|
64
|
+
struct_info[:assoc_info] = assoc[:assoc_info]
|
65
|
+
return struct_info
|
66
|
+
end
|
84
67
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
68
|
+
def get_max_col_size
|
69
|
+
col_name_max_size = self.klass.column_names.collect{|name| name.size}.max || 0
|
70
|
+
assoc_max_size = self.klass.reflect_on_all_associations.collect{|assoc| assoc.name.to_s.size}.max || 0
|
71
|
+
type_max_size = TYPE_MAP.collect{|key, value| key.size}.max || 0
|
72
|
+
[col_name_max_size + 1, assoc_max_size, type_max_size].max
|
73
|
+
end
|
89
74
|
|
90
|
-
|
91
|
-
|
92
|
-
|
75
|
+
def get_max_type_size
|
76
|
+
assoc_max_size = self.klass.reflect_on_all_associations.collect{|assoc| assoc.name.to_s.size + 2}.max || 0
|
77
|
+
type_max_size = TYPE_MAP.collect{|key, value| key.size}.max || 0
|
78
|
+
[assoc_max_size, type_max_size].max
|
79
|
+
end
|
93
80
|
|
81
|
+
def get_struct_name
|
82
|
+
self.klass.table_name.camelize
|
94
83
|
end
|
84
|
+
|
85
|
+
def get_associations
|
86
|
+
builder = GoOnRails::Association.new(self.klass, self.models, self.max_col_size, self.max_type_size)
|
87
|
+
builder.get_schema_info
|
88
|
+
end
|
89
|
+
|
90
|
+
def struct_tag(col)
|
91
|
+
"json:\"#{col.name},omitempty\" db:\"#{col.name}\""
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
95
|
end
|
96
96
|
|
97
97
|
require_relative 'association'
|
@@ -5,89 +5,96 @@ class GorGenerator < Rails::Generators::Base
|
|
5
5
|
class_option :only_models, type: :boolean, default: false, aliases: '-o', description: "only generate models"
|
6
6
|
|
7
7
|
def generate_gor
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
env_names = %W(dev development pro production test)
|
9
|
+
unless env_names.include? env_name
|
10
|
+
printf("Invalid env argument: Not any of %p\n\n", env_names)
|
11
|
+
exit
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
rails_env = case env_name
|
15
|
+
when "dev"
|
16
|
+
"development"
|
17
|
+
when "pro"
|
18
|
+
"production"
|
19
|
+
else
|
20
|
+
env_name
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
models = options[:models]
|
24
|
+
if models.empty?
|
25
|
+
models = get_all_models "app/models"
|
26
|
+
else
|
27
|
+
models.map!(&:camelize)
|
28
|
+
end
|
29
|
+
puts "The models: #{models} and Rails env [#{rails_env}] will be used to generate Golang App!"
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
31
|
+
models.each do |m|
|
32
|
+
begin
|
33
|
+
klass = m.split('::').inject(Object) { |kls, part| kls.const_get(part) }
|
34
|
+
if klass < ActiveRecord::Base && !klass.abstract_class?
|
35
|
+
@model_name = klass.to_s
|
36
|
+
convertor = GoOnRails::Convertor.new(klass, models)
|
37
|
+
@struct_info = convertor.convert
|
38
|
+
template "gor_model.go.erb", "go_app/models/gor_#{@model_name.underscore}.go"
|
39
|
+
end
|
40
|
+
rescue Exception => e
|
41
|
+
puts "Failed to convert the model [#{m}]: #{e.message}"
|
43
42
|
end
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
unless options[:only_models]
|
46
|
+
# generate the main.go
|
47
|
+
copy_file "main.go", "go_app/main.go"
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
# generate program for database connection
|
50
|
+
@db_config = {}
|
51
|
+
create_database_config(rails_env)
|
52
|
+
template "db.go.erb", "go_app/models/db.go"
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
# generate the controllers and views dir
|
55
|
+
copy_file "home_controller.go", "go_app/controllers/home_controller.go"
|
56
|
+
copy_file "index.tmpl", "go_app/views/index.tmpl"
|
57
|
+
copy_file "favicon.ico", "go_app/public/favicon.ico"
|
58
|
+
end
|
59
|
+
|
60
|
+
# use gofmt to prettify the generated Golang files
|
61
|
+
gofmt_go_files
|
59
62
|
end
|
60
63
|
|
61
64
|
private
|
62
65
|
|
63
66
|
def get_all_models model_dir
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
Dir.chdir(model_dir) do
|
68
|
+
Dir["**/*.rb"]
|
69
|
+
end.map { |m| m.sub(/\.rb$/,'').camelize }
|
67
70
|
end
|
68
71
|
|
69
72
|
def create_database_config rails_env
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
73
|
+
db_conf = Rails.configuration.database_configuration[rails_env]
|
74
|
+
case db_conf["adapter"]
|
75
|
+
when "sqlite3"
|
76
|
+
@db_config[:driver_name] = "sqlite3"
|
77
|
+
@db_config[:dsn] = "../" + db_conf["database"]
|
78
|
+
@db_config[:driver_package] = "_ \"github.com/mattn/go-sqlite3\""
|
79
|
+
when "mysql2"
|
80
|
+
@db_config[:driver_name] = "mysql"
|
81
|
+
# MySQL DSN format: username:password@protocol(address)/dbname?param=value
|
82
|
+
# See more: https://github.com/go-sql-driver/mysql
|
83
|
+
format = "%s:%s@%s/%s?charset=%s&parseTime=True&loc=Local"
|
84
|
+
@db_config[:dsn] = sprintf(format, *db_conf.values_at("username", "password", "host", "database", "encoding"))
|
85
|
+
@db_config[:driver_package] = "_ \"github.com/go-sql-driver/mysql\""
|
86
|
+
when "postgresql"
|
87
|
+
@db_config[:driver_name] = "postgres"
|
88
|
+
format = "host=%s user=%s dbname=%s sslmode=disable password=%s"
|
89
|
+
@db_config[:dsn] = sprintf(format, *db_conf.values_at("host", "username", "database", "password"))
|
90
|
+
@db_config[:driver_package] = "_ \"github.com/lib/pq\""
|
91
|
+
end
|
89
92
|
end
|
90
93
|
|
94
|
+
def gofmt_go_files
|
95
|
+
go_files = Rails.root.join('go_app', 'models/*.go').to_s
|
96
|
+
system "gofmt -w #{go_files} > /dev/null 2>&1"
|
97
|
+
end
|
91
98
|
end
|
92
99
|
|
93
100
|
require_relative 'go_on_rails/converter'
|
@@ -1,8 +1,9 @@
|
|
1
1
|
<%- param_name_plural = table_name = @model_name.underscore.pluralize -%>
|
2
2
|
<%- model_name_underscore = @model_name.underscore -%>
|
3
3
|
<%- col_names = @struct_info[:col_names] -%>
|
4
|
-
// The file is generated by
|
5
|
-
// https://rubygems.org/gems/
|
4
|
+
// The file is generated by go-on-rails, a Rails generator gem:
|
5
|
+
// https://rubygems.org/gems/go-on-rails
|
6
|
+
// Or on Github: https://github.com/goonr/go-on-rails
|
6
7
|
// By B1nj0y <idegorepl@gmail.com>
|
7
8
|
package model
|
8
9
|
|
@@ -42,9 +43,13 @@ func Find<%= @model_name.pluralize %>(ids ...int64) ([]<%= @model_name %>, error
|
|
42
43
|
return nil, errors.New(msg)
|
43
44
|
}
|
44
45
|
var_<%= param_name_plural %> := []<%= @model_name %>{}
|
45
|
-
|
46
|
-
sql := fmt.Sprintf(`SELECT * FROM <%= table_name %> WHERE id IN (
|
47
|
-
|
46
|
+
idsHolder := strings.Repeat(",?", len(ids)-1)
|
47
|
+
sql := fmt.Sprintf(`SELECT * FROM <%= table_name %> WHERE id IN (?%s)`, idsHolder)
|
48
|
+
idsT := []interface{}{}
|
49
|
+
for _,id := range ids {
|
50
|
+
idsT = append(idsT, interface{}(id))
|
51
|
+
}
|
52
|
+
err := db.Select(&var_<%= param_name_plural %>, sql, idsT...)
|
48
53
|
if err != nil {
|
49
54
|
log.Printf("Error: %v\n", err)
|
50
55
|
return nil, err
|
@@ -179,9 +184,9 @@ func Find<%= @model_name.pluralize %>BySql(sql string, args ...interface{}) (<%=
|
|
179
184
|
return <%= param_name_plural %>, nil
|
180
185
|
}
|
181
186
|
|
182
|
-
func Create<%= @model_name %>(am map[string]interface{}) error {
|
187
|
+
func Create<%= @model_name %>(am map[string]interface{}) (int64, error) {
|
183
188
|
if len(am) == 0 {
|
184
|
-
return fmt.Errorf("Zero key in the attributes map!")
|
189
|
+
return 0, fmt.Errorf("Zero key in the attributes map!")
|
185
190
|
}
|
186
191
|
<%- unless @struct_info[:timestamp_cols].empty? -%>
|
187
192
|
t := time.Now()
|
@@ -199,12 +204,17 @@ func Create<%= @model_name %>(am map[string]interface{}) error {
|
|
199
204
|
}
|
200
205
|
sqlFmt := `INSERT INTO <%= table_name %> (%s) VALUES (%s)`
|
201
206
|
sqlStr := fmt.Sprintf(sqlFmt, strings.Join(keys, ","), ":"+strings.Join(keys, ",:"))
|
202
|
-
|
207
|
+
result, err := db.NamedExec(sqlStr, am)
|
203
208
|
if err != nil {
|
204
209
|
log.Print(err)
|
205
|
-
return err
|
210
|
+
return 0, err
|
206
211
|
}
|
207
|
-
|
212
|
+
lastId, err := result.LastInsertId()
|
213
|
+
if err != nil {
|
214
|
+
log.Print(err)
|
215
|
+
return 0, err
|
216
|
+
}
|
217
|
+
return lastId, nil
|
208
218
|
}
|
209
219
|
|
210
220
|
func (var_<%= model_name_underscore %> *<%= @model_name %>) Create() error {
|
@@ -223,25 +233,43 @@ func (var_<%= model_name_underscore %> *<%= @model_name %>) Create() error {
|
|
223
233
|
<%- has_many = @struct_info[:assoc_info][:has_many] -%>
|
224
234
|
<%- has_many.each do |k, v| -%>
|
225
235
|
func (var_<%= model_name_underscore %> *<%= @model_name %>) <%= v[:class_name].pluralize %>Create(am map[string]interface{}) error {
|
226
|
-
<%- if v[:
|
227
|
-
|
228
|
-
|
229
|
-
|
236
|
+
<%- if v[:through] -%>
|
237
|
+
// FIXME: use transaction to create these associated objects
|
238
|
+
<%= v[:class_name].underscore %>_id, err := Create<%= v[:class_name] %>(am)
|
239
|
+
if err != nil {
|
240
|
+
return err
|
241
|
+
}
|
242
|
+
_, err = Create<%= v[:through].to_s.singularize.camelize %>(map[string]interface{}{"<%= model_name_underscore %>_id": var_<%= model_name_underscore %>.Id, "<%= v[:class_name].underscore %>_id": <%= v[:class_name].underscore %>_id})
|
243
|
+
<%- else -%>
|
244
|
+
<%- if v[:foreign_key] -%>
|
245
|
+
am["<%= v[:foreign_key] %>"] = var_<%= model_name_underscore %>.Id
|
246
|
+
<%- else -%>
|
247
|
+
am["<%= model_name_underscore %>_id"] = var_<%= model_name_underscore %>.Id
|
248
|
+
<%- end -%>
|
249
|
+
_, err := Create<%= v[:class_name] %>(am)
|
230
250
|
<%- end -%>
|
231
|
-
err := Create<%= v[:class_name] %>(am)
|
232
251
|
return err
|
233
252
|
}
|
234
253
|
|
235
254
|
func (var_<%= model_name_underscore %> *<%= @model_name %>) Get<%= v[:class_name].pluralize %>() error {
|
236
|
-
<%- if v[:
|
237
|
-
|
238
|
-
|
239
|
-
|
255
|
+
<%- if v[:through] -%>
|
256
|
+
// FIXME: use transaction to create these associated objects
|
257
|
+
<%= v[:class_name].underscore %>_ids, err := <%= v[:through].to_s.singularize.camelize %>IntCol("<%= v[:class_name].underscore %>_id", "<%= model_name_underscore %>_id = ?", var_<%= model_name_underscore %>.Id)
|
258
|
+
if err != nil {
|
259
|
+
return err
|
260
|
+
}
|
261
|
+
var_<%= v[:class_name].underscore.pluralize %>, err := Find<%= v[:class_name].pluralize %>(<%= v[:class_name].underscore %>_ids...)
|
262
|
+
<%- else -%>
|
263
|
+
<%- if v[:foreign_key] -%>
|
264
|
+
var_<%= v[:class_name].underscore.pluralize %>, err := Find<%= v[:class_name].pluralize %>By("<%= v[:foreign_key] %>", var_<%= model_name_underscore %>.Id)
|
265
|
+
<%- else -%>
|
266
|
+
var_<%= v[:class_name].underscore.pluralize %>, err := Find<%= v[:class_name].pluralize %>By("<%= model_name_underscore %>_id", var_<%= model_name_underscore %>.Id)
|
267
|
+
<%- end -%>
|
240
268
|
<%- end -%>
|
241
269
|
if err == nil {
|
242
270
|
var_<%= model_name_underscore %>.<%= k %> = var_<%= v[:class_name].underscore.pluralize %>
|
243
|
-
|
244
|
-
|
271
|
+
}
|
272
|
+
return err
|
245
273
|
}
|
246
274
|
<%- end -%>
|
247
275
|
<%- end -%>
|
@@ -255,7 +283,7 @@ func (var_<%= model_name_underscore %> *<%= @model_name %>) Create<%= v[:class_n
|
|
255
283
|
<%- else -%>
|
256
284
|
am["<%= model_name_underscore %>_id"] = var_<%= model_name_underscore %>.Id
|
257
285
|
<%- end -%>
|
258
|
-
err := Create<%= v[:class_name] %>(am)
|
286
|
+
_, err := Create<%= v[:class_name] %>(am)
|
259
287
|
return err
|
260
288
|
}
|
261
289
|
<%- end -%>
|
@@ -270,7 +298,7 @@ func (var_<%= model_name_underscore %> *<%= @model_name %>) Create<%= v[:class_n
|
|
270
298
|
<%- else -%>
|
271
299
|
am["<%= model_name_underscore %>_id"] = var_<%= model_name_underscore %>.Id
|
272
300
|
<%- end -%>
|
273
|
-
err := Create<%= v[:class_name] %>(am)
|
301
|
+
_, err := Create<%= v[:class_name] %>(am)
|
274
302
|
return err
|
275
303
|
}
|
276
304
|
<%- end -%>
|
@@ -295,10 +323,25 @@ func Destroy<%= @model_name %>(id int64) error {
|
|
295
323
|
<%- unless ass_cols.empty? -%>
|
296
324
|
<%- ass_cols.each_value do |opts| -%>
|
297
325
|
<%- if opts.key? :dependent -%>
|
298
|
-
<%- if opts
|
299
|
-
|
326
|
+
<%- if opts[:through] -%>
|
327
|
+
<%= opts[:class_name].underscore %>_ids, err := <%= opts[:through].to_s.singularize.camelize %>IntCol("<%= opts[:class_name].underscore %>_id", "<%= model_name_underscore %>_id = ?", var_<%= model_name_underscore %>.Id)
|
328
|
+
if err != nil {
|
329
|
+
return err
|
330
|
+
}
|
331
|
+
_, err = Destroy<%= opts[:class_name].pluralize %>(<%= opts[:class_name].underscore %>_ids...)
|
332
|
+
if err != nil {
|
333
|
+
return err
|
334
|
+
}
|
335
|
+
_, err = Destroy<%= opts[:through].to_s.pluralize.camelize %>Where("<%= model_name_underscore %>_id = ?", var_<%= model_name_underscore %>.Id)
|
336
|
+
if err != nil {
|
337
|
+
return err
|
338
|
+
}
|
300
339
|
<%- else -%>
|
301
|
-
|
340
|
+
<%- if opts.key? :foreign_key -%>
|
341
|
+
Destroy<%= opts[:class_name].pluralize %>Where("<%= opts[:foreign_key] %> = ?", id)
|
342
|
+
<%- else -%>
|
343
|
+
Destroy<%= opts[:class_name].pluralize %>Where("<%= model_name_underscore %>_id = ?", id)
|
344
|
+
<%- end -%>
|
302
345
|
<%- end -%>
|
303
346
|
<%- end -%>
|
304
347
|
<%- end -%>
|
@@ -313,10 +356,14 @@ func Destroy<%= @model_name.pluralize %>(ids ...int64) (int64, error) {
|
|
313
356
|
log.Println(msg)
|
314
357
|
return 0, errors.New(msg)
|
315
358
|
}
|
316
|
-
|
317
|
-
sql := fmt.Sprintf(`DELETE FROM <%= table_name %> WHERE id IN (
|
359
|
+
idsHolder := strings.Repeat(",?", len(ids)-1)
|
360
|
+
sql := fmt.Sprintf(`DELETE FROM <%= table_name %> WHERE id IN (?%s)`, idsHolder)
|
361
|
+
idsT := []interface{}{}
|
362
|
+
for _,id := range ids {
|
363
|
+
idsT = append(idsT, interface{}(id))
|
364
|
+
}
|
318
365
|
stmt, err := db.Preparex(sql)
|
319
|
-
result, err := stmt.Exec()
|
366
|
+
result, err := stmt.Exec(idsT...)
|
320
367
|
if err != nil {
|
321
368
|
return 0, err
|
322
369
|
}
|
@@ -330,11 +377,11 @@ func Destroy<%= @model_name.pluralize %>(ids ...int64) (int64, error) {
|
|
330
377
|
<%- ass_cols.each_value do |opts| -%>
|
331
378
|
<%- if opts.key? :dependent -%>
|
332
379
|
<%- if opts.key? :foreign_key -%>
|
333
|
-
where := fmt.Sprintf("<%= opts[:foreign_key] %> IN (
|
334
|
-
Destroy<%= opts[:class_name].pluralize %>Where(where)
|
380
|
+
where := fmt.Sprintf("<%= opts[:foreign_key] %> IN (?%s)", idsHolder)
|
381
|
+
Destroy<%= opts[:class_name].pluralize %>Where(where, idsT)
|
335
382
|
<%- else -%>
|
336
|
-
where := fmt.Sprintf("<%= model_name_underscore %>_id IN (
|
337
|
-
Destroy<%= opts[:class_name].pluralize %>Where(where)
|
383
|
+
where := fmt.Sprintf("<%= model_name_underscore %>_id IN (?%s)", idsHolder)
|
384
|
+
Destroy<%= opts[:class_name].pluralize %>Where(where, idsT)
|
338
385
|
<%- end -%>
|
339
386
|
<%- end -%>
|
340
387
|
<%- end -%>
|
@@ -373,7 +420,8 @@ func (var_<%= model_name_underscore %> *<%= @model_name %>) Save() error {
|
|
373
420
|
var_<%= model_name_underscore %>.UpdatedAt = time.Now()
|
374
421
|
<%- end -%>
|
375
422
|
sqlFmt := `UPDATE <%= table_name %> SET %s WHERE id = %v`
|
376
|
-
|
423
|
+
<%- save_col_names = col_names - ["created_at"] -%>
|
424
|
+
sqlStr := fmt.Sprintf(sqlFmt, "<%= save_col_names.zip(save_col_names).map{|c| c.join(" = :")}.join(", ") %>", var_<%= model_name_underscore %>.Id)
|
377
425
|
_, err := db.NamedExec(sqlStr, var_<%= model_name_underscore %>)
|
378
426
|
return err
|
379
427
|
}
|
data/lib/tasks/gor.rake
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
namespace :gor do
|
2
|
+
desc 'Install dependent Golang packages'
|
3
|
+
task :deps do
|
4
|
+
puts 'Beginning to install Go deps...'
|
5
|
+
system "go get \
|
6
|
+
github.com/jmoiron/sqlx \
|
7
|
+
github.com/gorilla/handlers \
|
8
|
+
github.com/gorilla/mux \
|
9
|
+
github.com/mattn/go-sqlite3 \
|
10
|
+
github.com/go-sql-driver/mysql \
|
11
|
+
github.com/lib/pq"
|
12
|
+
puts 'Installation completed!'
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: go-on-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- B1nj0y
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Modeling, developing and testing your Golang app with your familiar Rails
|
14
|
-
tools like rails generate, db migration, console etc.
|
15
|
-
|
16
|
-
not so complicated)
|
14
|
+
tools like rails generate, db migration, console etc. It also help integrating some
|
15
|
+
api written in Golang to existed Rails app for high performance.
|
17
16
|
email: idegorepl@gmail.com
|
18
17
|
executables: []
|
19
18
|
extensions: []
|
@@ -31,6 +30,7 @@ files:
|
|
31
30
|
- lib/generators/gor/templates/home_controller.go
|
32
31
|
- lib/generators/gor/templates/index.tmpl
|
33
32
|
- lib/generators/gor/templates/main.go
|
33
|
+
- lib/tasks/gor.rake
|
34
34
|
homepage: https://github.com/goonr/go-on-rails
|
35
35
|
licenses:
|
36
36
|
- MIT
|