go-on-rails 0.1.10 → 0.1.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25289bcbadbef0dfd3ea8b2a40485cdb1c2c8862
4
- data.tar.gz: af6b2200a33c29ed1e3393a5b74858ee737b10a9
3
+ metadata.gz: a3dc0eef63c002b0600a7b8593197776fa5d5efa
4
+ data.tar.gz: 899707b6d8f8be9734d0b8101533b73c3d2922f0
5
5
  SHA512:
6
- metadata.gz: 525c1d5c73e45658c9038051ef7fc00fcd223f59371f8b44fe19f196600c18ddff0bb39a6ad1e03e833830c6fba172a176e7409c8885b95fbac0b1001e55b239
7
- data.tar.gz: 275f4e5c119a7e4d3ee0bd4b2506d66f879520c1908de193205e71b09b6b68d196e3cc5f7605f98841af89cbefb435e52560853a1c204938489420d8300929b4
6
+ metadata.gz: a0905ffeef7c809e4d7d92b1b8dced27cec08202636ac508a1e06310a0c0087c3858a6129862a97c19aaf60af071884bdbf57a6980090731ac3ef6eb15f24aa5
7
+ data.tar.gz: 8733f862097286d34da51f0b504951b980477d740ada46cf0b6c511457227032094c89d35b0c30c2e9a69cfcadab5839e5c69be9454694a17ecdde7154cfb605
data/README.md CHANGED
@@ -14,7 +14,10 @@ go-on-rails is a Rails generator created for three scenarios:
14
14
  2. Use your farmiliar Rails tools to develope and manage a Golang app project
15
15
  3. Convert a *not very complicated* Rails app to Golang equivalent
16
16
 
17
- Here's a simple [example(tutorial)](https://github.com/goonr/example_simple) shows the basic usage of go-on-rails generator, and [another example](https://github.com/goonr/example_with_admin) shows how to integrate Go APIs in a Rails project. Some real-world examples are coming soon.
17
+ Here's some examples:
18
+ * a simple [example(tutorial)](https://github.com/goonr/example_simple) on the basic usage of go-on-rails generator
19
+ * [An advanced example](https://github.com/goonr/example_with_admin) shows how to integrate Go APIs in a Rails project
20
+ * [Another example](https://github.com/goonr/example_read_rails_session) shows how to read a Rails session from a go-on-rails generated Go API
18
21
 
19
22
  ## Prerequisites
20
23
 
@@ -26,7 +29,7 @@ Here's a simple [example(tutorial)](https://github.com/goonr/example_simple) sho
26
29
  Add this line to your application's Gemfile:
27
30
 
28
31
  ```ruby
29
- gem 'go-on-rails', '~> 0.1.9'
32
+ gem 'go-on-rails', '~> 0.1.11'
30
33
  ```
31
34
 
32
35
  And then execute:
@@ -11,14 +11,27 @@ module GoOnRails
11
11
  "integer(8)" => "int64",
12
12
  "float" => "float64",
13
13
  "datetime" => "time.Time",
14
- "date" => "time.Time"
15
- }
14
+ "date" => "time.Time",
15
+ "inet" => "string"
16
+ }.freeze
16
17
 
17
- def initialize(klass, models)
18
+ # COALESCE datetime typed field for different databases
19
+ # FIXME: no idea for sqlite3 at present
20
+ DATETIME_COALESCE_MAP = {
21
+ "sqlite3" => "%s",
22
+ "mysql" => "COALESCE(%s, CONVERT_TZ('0001-01-01 00:00:00','+00:00','UTC')) AS %s",
23
+ "postgres" => "COALESCE(%s, (TIMESTAMP WITH TIME ZONE '0001-01-01 00:00:00+00') AT TIME ZONE 'UTC') AS %s"
24
+ }.freeze
25
+
26
+ # types need special treatment in the nullable_map() method
27
+ SPECIAL_COALESCE_TYPES = %w[inet].freeze
28
+
29
+ def initialize(klass, models, database)
18
30
  @klass = klass
19
31
  @models = models
32
+ @database = database
20
33
  end
21
- attr_accessor :klass, :models
34
+ attr_accessor :klass, :models, :database
22
35
 
23
36
  def convert
24
37
  get_schema_info
@@ -27,9 +40,16 @@ module GoOnRails
27
40
  private
28
41
 
29
42
  def get_schema_info
30
- struct_info = {col_names: [], timestamp_cols: [], has_datetime_type: false, struct_body: ""}
43
+ struct_info = {
44
+ col_names: [],
45
+ timestamp_cols: [],
46
+ has_datetime_type: false,
47
+ struct_body: "",
48
+ }
31
49
 
32
50
  validation = GoOnRails::Validator.new(self.klass)
51
+ # store fields by if nullable
52
+ fields = { yes: [], no: [] }
33
53
 
34
54
  self.klass.columns.each_with_index do |col, index|
35
55
  tags = []
@@ -51,6 +71,17 @@ module GoOnRails
51
71
  type = TYPE_MAP[col_type] || "string"
52
72
  end
53
73
 
74
+ # check the fields if nullable
75
+ if col.null == true
76
+ if SPECIAL_COALESCE_TYPES.include?(col_type)
77
+ fields[:yes] << [col.name, col_type]
78
+ else
79
+ fields[:yes] << [col.name, type]
80
+ end
81
+ else
82
+ fields[:no] << col.name
83
+ end
84
+
54
85
  struct_info[:col_names] << col.name unless col.name == "id"
55
86
  struct_info[:struct_body] << sprintf("%s %s `%s`\n", col.name.camelize, type, tags.join(" "))
56
87
  end
@@ -59,6 +90,8 @@ module GoOnRails
59
90
  struct_info[:struct_body] << assoc[:struct_body]
60
91
  struct_info[:assoc_info] = assoc[:assoc_info]
61
92
  struct_info[:has_assoc_dependent] = assoc[:has_assoc_dependent]
93
+ struct_info[:select_fields] = nullable_select_str(fields)
94
+
62
95
  return struct_info
63
96
  end
64
97
 
@@ -75,6 +108,36 @@ module GoOnRails
75
108
  valid_tags = validation.build_validator_tag(col)
76
109
  "json:\"#{col.name},omitempty\" db:\"#{col.name}\" #{valid_tags}"
77
110
  end
111
+
112
+ def nullable_select_str(fields)
113
+ fields[:yes].map do |f|
114
+ sprintf(nullable_map(f[1]), "#{self.klass.table_name}.#{f[0]}", f[0])
115
+ end.concat(
116
+ fields[:no].map do |f|
117
+ sprintf("%s.%s", self.klass.table_name, f)
118
+ end
119
+ ).join(", ")
120
+ end
121
+
122
+ def nullable_map(type)
123
+ case type
124
+ when "string"
125
+ "COALESCE(%s, '') AS %s"
126
+ when "int8", "int16", "int32", "int64"
127
+ "COALESCE(%s, 0) AS %s"
128
+ when "float64"
129
+ "COALESCE(%s, 0.0) AS %s"
130
+ when "bool"
131
+ "COALESCE(%s, FALSE) AS %s"
132
+ when "time.Time"
133
+ DATETIME_COALESCE_MAP[self.database]
134
+ when "inet"
135
+ "COALESCE(%s, '0.0.0.0') AS %s"
136
+ else
137
+ # FIXME: here just return the column name, may skip some nullable field and cause an error in a query
138
+ "%s"
139
+ end
140
+ end
78
141
  end
79
142
  end
80
143
 
@@ -33,21 +33,26 @@ class GorGenerator < Rails::Generators::Base
33
33
  @db_config = {}
34
34
  read_database_config(rails_env)
35
35
 
36
- # iterate the models to generate Go codes
36
+ @all_structs_info = {}
37
+ # iterate the models to get all the structs' info
37
38
  @models.each do |m|
38
39
  begin
39
40
  klass = m.split('::').inject(Object) { |kls, part| kls.const_get(part) }
40
41
  if klass < ActiveRecord::Base && !klass.abstract_class?
41
- @model_name = klass.to_s
42
- convertor = GoOnRails::Convertor.new(klass, @models)
43
- @struct_info = convertor.convert
44
- template "gor_model.go.erb", "go_app/models/gor_#{@model_name.underscore}.go"
42
+ convertor = GoOnRails::Convertor.new(klass, @models, @db_config[:driver_name])
43
+ @all_structs_info[klass.to_s] = convertor.convert
45
44
  end
46
45
  rescue Exception => e
47
46
  puts "Failed to convert the model [#{m}]: #{e.message}"
48
47
  end
49
48
  end
50
49
 
50
+ # iterate the structs info to generate codes for each model
51
+ @all_structs_info.each do |k, v|
52
+ @model_name, @struct_info = k, v
53
+ template "gor_model.go.erb", "go_app/models/gor_#{@model_name.underscore}.go"
54
+ end
55
+
51
56
  # generate program for database connection
52
57
  template "db.go.erb", "go_app/models/db.go"
53
58
 
@@ -2,6 +2,7 @@
2
2
  <%- var_pmn = table_name = @model_name.underscore.pluralize -%>
3
3
  <%#- var_umn stands for underscored model name -#%>
4
4
  <%- var_umn = @model_name.underscore -%>
5
+ <%- fields = @struct_info[:select_fields] -%>
5
6
  <%- col_names = @struct_info[:col_names] -%>
6
7
  <%- has_assoc = !@struct_info[:assoc_info][:has_many].empty? || !@struct_info[:assoc_info][:has_one].empty? -%>
7
8
  // Package models includes the functions on the model <%= @model_name %>.
@@ -13,9 +14,9 @@ import (
13
14
  "log"
14
15
  "math"
15
16
  "strings"
16
- <%- if @struct_info[:has_datetime_type] -%>
17
+ <%- if @struct_info[:has_datetime_type] -%>
17
18
  "time"
18
- <%- end -%>
19
+ <%- end -%>
19
20
 
20
21
  "github.com/asaskevich/govalidator"
21
22
  )
@@ -228,7 +229,7 @@ func Find<%= @model_name %>(id int64) (*<%= @model_name %>, error) {
228
229
  return nil, errors.New("Invalid ID: it can't be zero")
229
230
  }
230
231
  _<%= var_umn %> := <%= @model_name %>{}
231
- err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT * FROM <%= table_name %> WHERE id = ? LIMIT 1`), id)
232
+ err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT <%= fields %> FROM <%= table_name %> WHERE <%= table_name %>.id = ? LIMIT 1`), id)
232
233
  if err != nil {
233
234
  log.Printf("Error: %v\n", err)
234
235
  return nil, err
@@ -239,7 +240,7 @@ func Find<%= @model_name %>(id int64) (*<%= @model_name %>, error) {
239
240
  // First<%= @model_name %> find the first one <%= var_umn %> by ID ASC order
240
241
  func First<%= @model_name %>() (*<%= @model_name %>, error) {
241
242
  _<%= var_umn %> := <%= @model_name %>{}
242
- err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT * FROM <%= table_name %> ORDER BY id ASC LIMIT 1`))
243
+ err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT <%= fields %> FROM <%= table_name %> ORDER BY <%= table_name %>.id ASC LIMIT 1`))
243
244
  if err != nil {
244
245
  log.Printf("Error: %v\n", err)
245
246
  return nil, err
@@ -250,7 +251,7 @@ func First<%= @model_name %>() (*<%= @model_name %>, error) {
250
251
  // First<%= @model_name.pluralize %> find the first N <%= var_umn.pluralize %> by ID ASC order
251
252
  func First<%= @model_name.pluralize %>(n uint32) ([]<%= @model_name %>, error) {
252
253
  _<%= var_pmn %> := []<%= @model_name %>{}
253
- sql := fmt.Sprintf("SELECT * FROM <%= table_name %> ORDER BY id ASC LIMIT %v", n)
254
+ sql := fmt.Sprintf("SELECT <%= fields %> FROM <%= table_name %> ORDER BY <%= table_name %>.id ASC LIMIT %v", n)
254
255
  err := DB.Select(&_<%= var_pmn %>, DB.Rebind(sql))
255
256
  if err != nil {
256
257
  log.Printf("Error: %v\n", err)
@@ -262,7 +263,7 @@ func First<%= @model_name.pluralize %>(n uint32) ([]<%= @model_name %>, error) {
262
263
  // Last<%= @model_name %> find the last one <%= var_umn %> by ID DESC order
263
264
  func Last<%= @model_name %>() (*<%= @model_name %>, error) {
264
265
  _<%= var_umn %> := <%= @model_name %>{}
265
- err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT * FROM <%= table_name %> ORDER BY id DESC LIMIT 1`))
266
+ err := DB.Get(&_<%= var_umn %>, DB.Rebind(`SELECT <%= fields %> FROM <%= table_name %> ORDER BY <%= table_name %>.id DESC LIMIT 1`))
266
267
  if err != nil {
267
268
  log.Printf("Error: %v\n", err)
268
269
  return nil, err
@@ -273,7 +274,7 @@ func Last<%= @model_name %>() (*<%= @model_name %>, error) {
273
274
  // Last<%= @model_name.pluralize %> find the last N <%= var_umn.pluralize %> by ID DESC order
274
275
  func Last<%= @model_name.pluralize %>(n uint32) ([]<%= @model_name %>, error) {
275
276
  _<%= var_pmn %> := []<%= @model_name %>{}
276
- sql := fmt.Sprintf("SELECT * FROM <%= table_name %> ORDER BY id DESC LIMIT %v", n)
277
+ sql := fmt.Sprintf("SELECT <%= fields %> FROM <%= table_name %> ORDER BY <%= table_name %>.id DESC LIMIT %v", n)
277
278
  err := DB.Select(&_<%= var_pmn %>, DB.Rebind(sql))
278
279
  if err != nil {
279
280
  log.Printf("Error: %v\n", err)
@@ -291,7 +292,7 @@ func Find<%= @model_name.pluralize %>(ids ...int64) ([]<%= @model_name %>, error
291
292
  }
292
293
  _<%= var_pmn %> := []<%= @model_name %>{}
293
294
  idsHolder := strings.Repeat(",?", len(ids)-1)
294
- sql := DB.Rebind(fmt.Sprintf(`SELECT * FROM <%= table_name %> WHERE id IN (?%s)`, idsHolder))
295
+ sql := DB.Rebind(fmt.Sprintf(`SELECT <%= fields %> FROM <%= table_name %> WHERE <%= table_name %>.id IN (?%s)`, idsHolder))
295
296
  idsT := []interface{}{}
296
297
  for _,id := range ids {
297
298
  idsT = append(idsT, interface{}(id))
@@ -307,7 +308,7 @@ func Find<%= @model_name.pluralize %>(ids ...int64) ([]<%= @model_name %>, error
307
308
  // Find<%= @model_name %>By find a single <%= var_umn %> by a field name and a value
308
309
  func Find<%= @model_name %>By(field string, val interface{}) (*<%= @model_name %>, error) {
309
310
  _<%= var_umn %> := <%= @model_name %>{}
310
- sqlFmt := `SELECT * FROM <%= table_name %> WHERE %s = ? LIMIT 1`
311
+ sqlFmt := `SELECT <%= fields %> FROM <%= table_name %> WHERE %s = ? LIMIT 1`
311
312
  sqlStr := fmt.Sprintf(sqlFmt, field)
312
313
  err := DB.Get(&_<%= var_umn %>, DB.Rebind(sqlStr), val)
313
314
  if err != nil {
@@ -319,7 +320,7 @@ func Find<%= @model_name %>By(field string, val interface{}) (*<%= @model_name %
319
320
 
320
321
  // Find<%= @model_name.pluralize %>By find all <%= var_pmn %> by a field name and a value
321
322
  func Find<%= @model_name.pluralize %>By(field string, val interface{}) (_<%= var_pmn %> []<%= @model_name %>, err error) {
322
- sqlFmt := `SELECT * FROM <%= table_name %> WHERE %s = ?`
323
+ sqlFmt := `SELECT <%= fields %> FROM <%= table_name %> WHERE %s = ?`
323
324
  sqlStr := fmt.Sprintf(sqlFmt, field)
324
325
  err = DB.Select(&_<%= var_pmn %>, DB.Rebind(sqlStr), val)
325
326
  if err != nil {
@@ -331,7 +332,7 @@ func Find<%= @model_name.pluralize %>By(field string, val interface{}) (_<%= var
331
332
 
332
333
  // All<%= @model_name.pluralize %> get all the <%= @model_name %> records
333
334
  func All<%= @model_name.pluralize %>() (<%= var_pmn %> []<%= @model_name %>, err error) {
334
- err = DB.Select(&<%= var_pmn %>, "SELECT * FROM <%= table_name %>")
335
+ err = DB.Select(&<%= var_pmn %>, "SELECT <%= fields %> FROM <%= table_name %>")
335
336
  if err != nil {
336
337
  log.Println(err)
337
338
  return nil, err
@@ -526,7 +527,7 @@ func <%= @model_name %>StrCol(col, where string, args ...interface{}) (strColRec
526
527
  // with placeholders, eg: FindUsersWhere("first_name = ? AND age > ?", "John", 18)
527
528
  // will return those records in the table "users" whose first_name is "John" and age elder than 18
528
529
  func Find<%= @model_name.pluralize %>Where(where string, args ...interface{}) (<%= var_pmn %> []<%= @model_name %>, err error) {
529
- sql := "SELECT * FROM <%= table_name %>"
530
+ sql := "SELECT <%= fields %> FROM <%= table_name %>"
530
531
  if len(where) > 0 {
531
532
  sql = sql + " WHERE " + where
532
533
  }
@@ -688,7 +689,7 @@ func <%= @model_name %>Get<%= k.pluralize %>(id int64) ([]<%= v[:class_name] %>,
688
689
  // FIXME: use transaction to create these associated objects
689
690
  <%- target_table = v[:class_name].underscore.pluralize -%>
690
691
  <%- through_table = v[:through].to_s.pluralize -%>
691
- sql := `SELECT <%= target_table %>.*
692
+ sql := `SELECT <%= @all_structs_info[v[:class_name]][:select_fields] %>
692
693
  FROM <%= target_table %>
693
694
  INNER JOIN <%= through_table %>
694
695
  ON <%= target_table %>.id = <%= through_table %>.<%= v[:class_name].underscore %>_id
@@ -1,4 +1,4 @@
1
- package controller
1
+ package controllers
2
2
 
3
3
  import (
4
4
  "net/http"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: go-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - B1nj0y
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-09 00:00:00.000000000 Z
11
+ date: 2017-10-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Modeling, developing and testing your Golang app with your familiar Rails
14
14
  tools like rails generate, db migration, console etc. It is more meant to help integrating