go-on-rails 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|