go-on-rails 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
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