hot-glue 0.0.2 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -7
  3. data/Gemfile +4 -9
  4. data/Gemfile.lock +42 -22
  5. data/README.md +140 -30
  6. data/Rakefile +1 -1
  7. data/app/assets/config/manifest.js +0 -0
  8. data/bin/rails +2 -2
  9. data/config/database.yml +11 -0
  10. data/db/migrate/20210306212711_create_abcs.rb +11 -0
  11. data/db/migrate/20210306223300_create_defs.rb +9 -0
  12. data/db/migrate/20210306223305_create_hgis.rb +9 -0
  13. data/db/migrate/20210306223309_create_jkls.rb +9 -0
  14. data/db/migrate/20210306223701_devise_create_users.rb +44 -0
  15. data/db/migrate/20210306225506_create_xyzs.rb +9 -0
  16. data/db/schema.rb +60 -0
  17. data/lib/generators/hot_glue/install_generator.rb +3 -3
  18. data/lib/generators/hot_glue/scaffold_generator.rb +250 -138
  19. data/lib/generators/hot_glue/templates/_errors.haml +6 -5
  20. data/lib/generators/hot_glue/templates/_flash_notices.haml +7 -6
  21. data/lib/generators/hot_glue/templates/_line.haml +1 -1
  22. data/lib/generators/hot_glue/templates/_list.haml +4 -2
  23. data/lib/generators/hot_glue/templates/_new_button.haml +1 -1
  24. data/lib/generators/hot_glue/templates/_new_form.haml +10 -0
  25. data/lib/generators/hot_glue/templates/_show.haml +1 -1
  26. data/lib/generators/hot_glue/templates/{base_controller.rb → base_controller.rb.erb} +0 -0
  27. data/lib/generators/hot_glue/templates/{controller.rb → controller.rb.erb} +11 -7
  28. data/lib/generators/hot_glue/templates/create.turbo_stream.haml +12 -3
  29. data/lib/generators/hot_glue/templates/edit.haml +2 -0
  30. data/lib/generators/hot_glue/templates/index.haml +1 -1
  31. data/lib/generators/hot_glue/templates/new.haml +1 -10
  32. data/lib/generators/hot_glue/templates/{controller_spec.rb → request_spec.rb.erb} +0 -0
  33. data/lib/generators/hot_glue/templates/system_spec.rb.erb +109 -0
  34. data/lib/hotglue/version.rb +1 -1
  35. metadata +17 -6
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
14
14
  rdoc.rdoc_files.include('lib/**/*.rb')
15
15
  end
16
16
 
17
- APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
17
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
18
18
  load 'rails/tasks/engine.rake'
19
19
 
20
20
  load 'rails/tasks/statistics.rake'
File without changes
data/bin/rails CHANGED
@@ -3,8 +3,8 @@
3
3
  # installed from the root of your application.
4
4
 
5
5
  ENGINE_ROOT = File.expand_path('..', __dir__)
6
- ENGINE_PATH = File.expand_path('../lib/common_core_js/engine', __dir__)
7
- APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/hotglue/engine', __dir__)
7
+ APP_PATH = File.expand_path('../spec/dummy/application', __dir__)
8
8
 
9
9
  # Set up gems listed in the Gemfile.
10
10
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
@@ -0,0 +1,11 @@
1
+ development:
2
+ adapter: sqlite3
3
+ database: ../spec/dummy/db/development.sqlite3
4
+ pool: 5
5
+ timeout: 5000
6
+
7
+ test:
8
+ adapter: sqlite3
9
+ database: ../spec/dummy/db/test.sqlite3
10
+ pool: 5
11
+ timeout: 5000
@@ -0,0 +1,11 @@
1
+ class CreateAbcs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :abcs do |t|
4
+ t.integer :xxx
5
+ t.string :yyy
6
+ t.integer :def_id
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class CreateDefs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :defs do |t|
4
+ t.integer :user_id
5
+ t.string :name
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class CreateHgis < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :hgis do |t|
4
+ t.integer :def_id
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class CreateJkls < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :jkls do |t|
4
+ t.integer :hgi_id
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeviseCreateUsers < ActiveRecord::Migration[6.1]
4
+ def change
5
+ create_table :users do |t|
6
+ ## Database authenticatable
7
+ t.string :email, null: false, default: ""
8
+ t.string :encrypted_password, null: false, default: ""
9
+
10
+ ## Recoverable
11
+ t.string :reset_password_token
12
+ t.datetime :reset_password_sent_at
13
+
14
+ ## Rememberable
15
+ t.datetime :remember_created_at
16
+
17
+ ## Trackable
18
+ # t.integer :sign_in_count, default: 0, null: false
19
+ # t.datetime :current_sign_in_at
20
+ # t.datetime :last_sign_in_at
21
+ # t.string :current_sign_in_ip
22
+ # t.string :last_sign_in_ip
23
+
24
+ ## Confirmable
25
+ # t.string :confirmation_token
26
+ # t.datetime :confirmed_at
27
+ # t.datetime :confirmation_sent_at
28
+ # t.string :unconfirmed_email # Only if using reconfirmable
29
+
30
+ ## Lockable
31
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
32
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
33
+ # t.datetime :locked_at
34
+
35
+
36
+ t.timestamps null: false
37
+ end
38
+
39
+ add_index :users, :email, unique: true
40
+ add_index :users, :reset_password_token, unique: true
41
+ # add_index :users, :confirmation_token, unique: true
42
+ # add_index :users, :unlock_token, unique: true
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ class CreateXyzs < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :xyzs do |t|
4
+ t.integer :nothing_id
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
data/db/schema.rb ADDED
@@ -0,0 +1,60 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2021_03_06_225506) do
14
+
15
+ create_table "abcs", force: :cascade do |t|
16
+ t.integer "xxx"
17
+ t.string "yyy"
18
+ t.integer "def_id"
19
+ t.datetime "created_at", precision: 6, null: false
20
+ t.datetime "updated_at", precision: 6, null: false
21
+ end
22
+
23
+ create_table "defs", force: :cascade do |t|
24
+ t.integer "user_id"
25
+ t.string "name"
26
+ t.datetime "created_at", precision: 6, null: false
27
+ t.datetime "updated_at", precision: 6, null: false
28
+ end
29
+
30
+ create_table "hgis", force: :cascade do |t|
31
+ t.integer "def_id"
32
+ t.datetime "created_at", precision: 6, null: false
33
+ t.datetime "updated_at", precision: 6, null: false
34
+ end
35
+
36
+ create_table "jkls", force: :cascade do |t|
37
+ t.integer "hgi_id"
38
+ t.datetime "created_at", precision: 6, null: false
39
+ t.datetime "updated_at", precision: 6, null: false
40
+ end
41
+
42
+ create_table "users", force: :cascade do |t|
43
+ t.string "email", default: "", null: false
44
+ t.string "encrypted_password", default: "", null: false
45
+ t.string "reset_password_token"
46
+ t.datetime "reset_password_sent_at"
47
+ t.datetime "remember_created_at"
48
+ t.datetime "created_at", precision: 6, null: false
49
+ t.datetime "updated_at", precision: 6, null: false
50
+ t.index ["email"], name: "index_users_on_email", unique: true
51
+ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
52
+ end
53
+
54
+ create_table "xyzs", force: :cascade do |t|
55
+ t.integer "nothing_id"
56
+ t.datetime "created_at", precision: 6, null: false
57
+ t.datetime "updated_at", precision: 6, null: false
58
+ end
59
+
60
+ end
@@ -10,9 +10,9 @@ module HotGlue
10
10
 
11
11
  def initialize(*args) #:nodoc:
12
12
  super
13
- # copy_file "common_core.js", "app/javascript/common_core.js"
14
- # copy_file "common_core.scss", "app/assets/stylesheets/common_core.scss"
15
- copy_file "_flash_notices.haml", "app/views/layouts/_flash_notices.haml"
13
+ # copy_file "hot_glue.js", "#{'spec/dummy/' if Rails.env.test?}app/javascript/hot_glue.js"
14
+ # copy_file "hot_glue.scss", "#{'spec/dummy/' if Rails.env.test?}app/assets/stylesheets/hot_glue.scss"
15
+ copy_file "_flash_notices.haml", "#{'spec/dummy/' if Rails.env.test?}app/views/layouts/_flash_notices.haml"
16
16
  end
17
17
  end
18
18
  end
@@ -3,6 +3,12 @@ require 'ffaker'
3
3
 
4
4
 
5
5
  module HotGlue
6
+
7
+
8
+ class Error < StandardError
9
+ end
10
+
11
+
6
12
  module GeneratorHelper
7
13
  def text_area_output(col, field_length, col_identifier )
8
14
  lines = field_length % 40
@@ -38,149 +44,192 @@ module HotGlue
38
44
  include GeneratorHelper
39
45
 
40
46
 
41
- def initialize(*meta_args) #:nodoc:
42
- super
43
-
44
- begin
45
- object = eval(class_name)
46
- rescue StandardError => e
47
- puts "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first."
48
- exit
49
- end
50
-
47
+ class_option :singular, type: :string, default: nil
48
+ class_option :plural, type: :string, default: nil
49
+ class_option :singular_class, type: :string, default: nil
50
+ class_option :nest, type: :string, default: ""
51
+ class_option :namespace, type: :string, default: nil
52
+ class_option :auth, type: :string, default: nil
53
+ class_option :auth_identifier, type: :string, default: nil
54
+ class_option :exclude, type: :string, default: ""
55
+ class_option :include, type: :string, default: ""
56
+ class_option :god, type: :boolean, default: false
57
+ class_option :gd, type: :boolean, default: false # alias for god
58
+ class_option :spacs_only, type: :boolean, default: false
59
+ class_option :no_specs, type: :boolean, default: false
60
+ class_option :no_delete, type: :boolean, default: false
61
+ class_option :no_create, type: :boolean, default: false
62
+ class_option :no_paginate, type: :boolean, default: false
63
+ class_option :big_edit, type: :boolean, default: false
64
+ class_option :show_only, type: :string, default: ""
51
65
 
66
+ def initialize(*meta_args) #:nodoc:
67
+ super
52
68
 
53
- args = meta_args[0]
54
- @singular = args[0].tableize.singularize # should be in form hello_world
69
+ begin
70
+ object = eval(class_name)
71
+ rescue StandardError => e
72
+ message = "*** Oops: It looks like there is no object for #{class_name}. Please define the object + database table first."
73
+ raise(HotGlue::Error, message)
74
+ end
55
75
 
76
+ if @specs_only && @no_specs
77
+ raise(HotGlue::Error, "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. sorry.")
78
+ end
56
79
 
57
- @plural = @singular + "s" # supply to override; leave blank to use default
58
- @singular_class = @singular.titleize.gsub(" ", "")
59
- @nest = nil
60
- @namespace = nil
61
- @nested_args = []
62
80
 
63
- @auth = "current_user"
64
- @auth_identifier = nil
81
+ args = meta_args[0]
82
+ @singular = args.first.tableize.singularize # should be in form hello_world
83
+ @plural = options['plural'] || @singular + "s" # supply to override; leave blank to use default
84
+ @auth = options['auth'] || "current_user"
85
+ @auth_identifier = options['auth'] || (!@auth.nil? && @auth.gsub("current_", "")) || nil
86
+ @nest = options['auth'] || nil
87
+ @namespace = options['namespace'] || nil
88
+ @singular_class = @singular.titleize.gsub(" ", "")
89
+ @exclude_fields = []
90
+ @exclude_fields += options['exclude'].split(",").collect(&:to_sym)
91
+
92
+ if !options['include'].empty?
93
+ @include_fields = []
94
+ @include_fields += options['include'].split(",").collect(&:to_sym)
95
+ end
65
96
 
66
- args[1..-1].each do |a|
67
- var_name, var_value = a.split("=")
68
- case (var_name)
69
97
 
70
- when "plural"
71
- @plural = var_value
72
- when "nest"
73
- @nest = var_value
74
- when "namespace"
75
- @namespace = var_value
76
- when "auth"
77
- @auth = var_value
78
- when "auth_identifier"
79
- @auth_identifier = var_value || ""
98
+ @show_only = []
99
+ if !options['show_only'].empty?
100
+ @show_only += options['show_only'].split(",").collect(&:to_sym)
80
101
  end
81
- end
82
102
 
83
- auth_assoc = @auth.gsub("current_","")
103
+ auth_assoc = @auth.gsub("current_","")
104
+
105
+ @god = options['god'] || options['gd'] || false
106
+ @specs_only = options['specs_only'] || false
107
+ @no_specs = options['no_specs'] || false
108
+ @no_delete = options['no_delete'] || false
84
109
 
85
- @no_delete = false
86
- @no_create = false
110
+ @no_create = options['no_create'] || false
111
+ @no_paginate = options['no_paginate'] || false
112
+ @big_edit = options['big_edit']
87
113
 
88
- flags = meta_args[1]
89
- flags.each do |f|
90
- case (f)
91
- when "--god"
114
+ if @god
92
115
  @auth = nil
93
- # when "--with-index"
94
- # @with_index = true
95
- when "--specs-only"
96
- @specs_only = true
97
- when "--no-specs"
98
- @no_specs = true
99
- when "--no-delete"
100
- @no_delete = true
101
- when "--no-create"
102
- @no_create = true
103
116
  end
104
- end
105
117
 
106
- if @specs_only && @no_specs
107
- puts "*** Oops: You seem to have specified both the --specs-only flag and --no-specs flags. this doesn't make any sense, so I am aborting. sorry."
108
- exit
109
- end
118
+ # when in self auth, the object is the same as the authenticated object
119
+ if @auth && auth_identifier == @singular
120
+ @self_auth = true
121
+ end
110
122
 
123
+ @nested_args = []
124
+ if !@nest.nil?
125
+ @nested_args = @nest.split("/")
126
+ @nested_args_plural = {}
127
+ @nested_args.each do |a|
128
+ @nested_args_plural[a] = a + "s"
129
+ end
130
+ end
111
131
 
112
- # only used for the before_action
113
- if @auth_identifier.nil? && !@auth.nil?
114
- @auth_identifier = @auth.gsub("current_", "")
115
- end
132
+ # the @object_owner will always be object that will 'own' the object
133
+ # for new and create
116
134
 
117
- # when in self auth, the object is the same as the authenticated object
118
- if @auth && auth_identifier == @singular
119
- @self_auth = true
120
- end
135
+ if @auth && ! @self_auth && @nested_args.none?
136
+ @object_owner_sym = @auth.gsub("current_", "").to_sym
137
+ @object_owner_eval = @auth
138
+ else
121
139
 
122
- if !@nest.nil?
123
- @nested_args = @nest.split("/")
124
- @nested_args_plural = {}
125
- @nested_args.each do |a|
126
- @nested_args_plural[a] = a + "s"
140
+ if @nested_args.any?
141
+ @object_owner_sym = @nested_args.last.to_sym
142
+ @object_owner_eval = "@#{@nested_args.last}"
143
+ else
144
+ @object_owner_sym = ""
145
+ @object_owner_eval = ""
146
+ end
127
147
  end
128
- end
129
148
 
130
- # the @object_owner will always be object that will 'own' the object
131
- # for new and create
132
149
 
133
- if @auth && ! @self_auth && @nested_args.none?
134
- @object_owner_sym = @auth.gsub("current_", "").to_sym
135
- @object_owner_eval = @auth
136
- else
150
+ if !@object_owner_sym.empty?
151
+ auth_assoc_field = auth_assoc + "_id"
152
+ assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
137
153
 
138
- if @nested_args.any?
139
- @object_owner_sym = @nested_args.last.to_sym
140
- @object_owner_eval = "@#{@nested_args.last}"
141
- else
142
- @object_owner_sym = ""
143
- @object_owner_eval = ""
154
+ if assoc
155
+ ownership_field = assoc.name.to_s + "_id"
156
+ else
157
+ # if @auth
158
+ exit_message= "*** Oops: It looks like is no association from current_#{@object_owner_sym} to a class called #{singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users as lowercase. Also, be sure to implement current_X as a method on your controller. (If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for auth_identifier.) To make a controller that can read all records, specify with --god."
159
+ # else
160
+ # exit_message= "*** Oops: god mode could not find the association(?). something is wrong."
161
+ # end
162
+ raise(HotGlue::Error, exit_message)
163
+ end
144
164
  end
145
- end
146
165
 
166
+ if !@include_fields
167
+ @exclude_fields.push :id, :created_at, :updated_at, :encrypted_password,
168
+ :reset_password_token,
169
+ :reset_password_sent_at, :remember_created_at,
170
+ :confirmation_token, :confirmed_at,
171
+ :confirmation_sent_at, :unconfirmed_email
172
+
173
+ @exclude_fields.push(auth_assoc_field.to_sym) if !auth_assoc_field.nil?
174
+ @exclude_fields.push(ownership_field.to_sym) if !ownership_field.nil?
147
175
 
148
176
 
149
- # create the columns
150
- if !@object_owner_sym.empty?
151
- auth_assoc_field = auth_assoc + "_id"
152
- assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
153
- if assoc
154
- ownership_field = assoc.name.to_s + "_id"
177
+ @columns = object.columns.map(&:name).map(&:to_sym).reject{|field| @exclude_fields.include?(field) }
178
+
155
179
  else
156
- if @auth
157
- puts "*** Oops: It looks like is no association from current_#{@object_owner_sym} to a class called #{singular_class}. If your user is called something else, pass with flag auth=current_X where X is the model for your users as lowercase. Also, be sure to implement current_X as a method on your controller. (If you really don't want to implement a current_X on your controller and want me to check some other method for your current user, see the section in the docs for auth_identifier.) To make a controller that can read all records, specify with --god."
158
- else
159
- puts "*** Oops: god mode could not find the association(?). something is wrong."
160
- end
161
- exit
180
+ @columns = object.columns.map(&:name).map(&:to_sym).reject{|field| !@include_fields.include?(field) }
181
+
162
182
  end
163
- end
164
183
 
165
- exclude_fields = [ :id, :created_at, :updated_at, :encrypted_password, :reset_password_token,
166
- :reset_password_sent_at, :remember_created_at, :confirmation_token, :confirmed_at,
167
- :confirmation_sent_at, :unconfirmed_email]
184
+ @columns.each do |col|
185
+ if col.to_s.starts_with?("_")
186
+ @show_only << col
187
+ end
168
188
 
169
- exclude_fields << auth_assoc_field.to_sym if !auth_assoc_field.nil?
170
- exclude_fields << ownership_field.to_sym if !ownership_field.nil?
189
+ if object.columns_hash[col.to_s].type == :integer
190
+ if col.to_s.ends_with?("_id")
191
+ # guess the association name label
192
+ assoc_name = col.to_s.gsub("_id","")
193
+ assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
171
194
 
172
195
 
173
- begin
174
- @columns = object.columns.map(&:name).map(&:to_sym).reject{|field| exclude_fields.include?(field) }
175
- rescue StandardError => e
176
- puts "Ooops... it looks like is an object for #{class_name}. Please create the database table with fields first. "
177
- exit
178
- end
196
+ begin
197
+ eval(assoc.class_name)
198
+ rescue NameError => e
199
+ exit_message = "*** Oops: The table #{singular_class} has an association for '#{assoc.name.to_s}', but I can't find an assoicated model for that association. TODO: Please implement a model for #{assoc.name.to_s} that belongs to #{singular_class} "
200
+ raise(HotGlue::Error, exit_message)
179
201
 
202
+ end
180
203
 
181
204
 
205
+ if assoc.nil?
206
+ exit_message= "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
207
+ raise(HotGlue::Error,exit_message)
208
+ end
209
+
210
+ assoc_class = eval(assoc.class_name)
211
+ if assoc_class.respond_to?(:name)
212
+ # display_column = "name"
213
+ elsif assoc_class.respond_to?(:to_label)
214
+ # display_column = "to_label"
215
+ elsif assoc_class.respond_to?(:full_name)
216
+ # display_column = "full_name"
217
+ elsif assoc_class.respond_to?(:display_name)
218
+ # display_column = "display_name"
219
+ elsif assoc_class.respond_to?(:email)
220
+ # display_column = "email"
221
+ else
222
+ exit_message= "*** Oops: Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
223
+ raise(HotGlue::Error,exit_message)
224
+ end
225
+ end
226
+ end
227
+ end
182
228
  end
183
229
 
230
+
231
+
232
+ #
184
233
  def formats
185
234
  [format]
186
235
  end
@@ -193,17 +242,19 @@ module HotGlue
193
242
  @default_colspan = @columns.size
194
243
 
195
244
  unless @specs_only
196
- template "controller.rb", File.join("app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
245
+ template "controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
197
246
  if @namespace && defined?(controller_descends_from) == nil
198
- template "base_controller.rb", File.join("app/controllers#{namespace_with_dash}", "base_controller.rb")
247
+ template "base_controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "base_controller.rb")
199
248
  end
200
249
  end
201
250
 
202
251
  unless @no_specs
203
- template "controller_spec.rb", File.join("spec/controllers#{namespace_with_dash}", "#{plural}_controller_spec.rb")
252
+ template "request_spec.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}spec/request#{namespace_with_dash}", "#{plural}_spec.rb")
253
+ template "system_spec.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}spec/system#{namespace_with_dash}", "#{plural}_spec.rb")
254
+
204
255
  end
205
256
 
206
- template "_errors.haml", File.join("app/views#{namespace_with_dash}", "_errors.haml")
257
+ template "_errors.haml", File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", "_errors.haml")
207
258
  end
208
259
 
209
260
  def list_column_headings
@@ -311,6 +362,18 @@ module HotGlue
311
362
  "#{@namespace+"/" if @namespace}#{plural}/line"
312
363
  end
313
364
 
365
+ def show_path_partial
366
+ "#{@namespace+"/" if @namespace}#{plural}/show"
367
+ end
368
+
369
+ def list_path_partial
370
+ "#{@namespace+"/" if @namespace}#{plural}/list"
371
+ end
372
+
373
+ def new_path_name
374
+ "new_#{@namespace+"_" if @namespace}#{singular}_path"
375
+ end
376
+
314
377
  def nested_assignments
315
378
  @nested_args.map{|a| "#{a}: @#{a}"}.join(", ") #metaprgramming into Ruby hash
316
379
  end
@@ -386,14 +449,14 @@ module HotGlue
386
449
  haml_views.each do |view|
387
450
  formats.each do |format|
388
451
  filename = cc_filename_with_extensions(view, "haml")
389
- template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
452
+ template filename, File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", controller_file_path, filename)
390
453
  end
391
454
  end
392
455
 
393
456
  turbo_stream_views.each do |view|
394
457
  formats.each do |format|
395
458
  filename = cc_filename_with_extensions(view, 'turbo_stream.haml')
396
- template filename, File.join("app/views#{namespace_with_dash}", controller_file_path, filename)
459
+ template filename, File.join("#{'spec/dummy/' if Rails.env.test?}app/views#{namespace_with_dash}", controller_file_path, filename)
397
460
  end
398
461
  end
399
462
  end
@@ -415,13 +478,21 @@ module HotGlue
415
478
  end
416
479
 
417
480
  def haml_views
418
- res = %w(index edit new _form _line _list _new_button _show)
481
+ res = %w(index edit _form _line _list _show _errors)
482
+
483
+ unless @no_create
484
+ res += %w(new _new_form _new_button)
485
+ end
419
486
 
420
487
  res
421
488
  end
422
489
 
423
490
  def turbo_stream_views
424
- res = %w(create destroy edit update)
491
+ res = %w(create edit update)
492
+ unless @no_delete
493
+ res << 'destroy'
494
+ end
495
+ res
425
496
  end
426
497
 
427
498
  def handler
@@ -442,6 +513,16 @@ module HotGlue
442
513
  col_spaces_prepend = " "
443
514
 
444
515
  res = @columns.map { |col|
516
+
517
+ if @show_only.include?(col)
518
+
519
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
520
+ = @#{singular}.#{col.to_s}
521
+ %label.form-text
522
+ #{col.to_s.humanize}\n"
523
+ else
524
+
525
+
445
526
  type = eval("#{singular_class}.columns_hash['#{col}']").type
446
527
  limit = eval("#{singular_class}.columns_hash['#{col}']").limit
447
528
  sql_type = eval("#{singular_class}.columns_hash['#{col}']").sql_type
@@ -450,43 +531,41 @@ module HotGlue
450
531
  when :integer
451
532
  # look for a belongs_to on this object
452
533
  if col.to_s.ends_with?("_id")
453
- # guess the association name label
454
-
455
-
456
534
  assoc_name = col.to_s.gsub("_id","")
457
535
  assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
458
536
  if assoc.nil?
459
- puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
537
+ exit_message= "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
460
538
  exit
461
539
  end
462
540
 
463
541
 
464
542
  assoc_class = eval(assoc.class_name)
465
543
 
466
- if assoc_class.column_names.include?("name")
544
+ if assoc_class.respond_to?("name")
467
545
  display_column = "name"
468
- elsif assoc_class.column_names.include?("to_label")
546
+ elsif assoc_class.respond_to?("to_label")
469
547
  display_column = "to_label"
470
- elsif assoc_class.column_names.include?("full_name")
548
+ elsif assoc_class.respond_to?("full_name")
471
549
  display_column = "full_name"
472
- elsif assoc_class.column_names.include?("display_name")
550
+ elsif assoc_class.respond_to?("display_name")
473
551
  display_column = "display_name"
474
- elsif assoc_class.column_names.include?("email")
552
+ elsif assoc_class.respond_to?("email")
475
553
  display_column = "email"
476
554
  else
477
- puts "*** Oops: Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
555
+ raise("this should have been caught by the checker in the initializer")
556
+ # puts "*** Oops: Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
478
557
  end
479
558
 
480
559
  "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{assoc_name.to_s})}\"}
481
560
  #{col_spaces_prepend}= f.collection_select(:#{col.to_s}, #{assoc_class}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control')
482
- #{col_spaces_prepend} %label.small.form-text.text-muted
483
- #{col_spaces_prepend} #{col.to_s.humanize}"
561
+ #{col_spaces_prepend}%label.small.form-text.text-muted
562
+ #{col_spaces_prepend} #{col.to_s.humanize}"
484
563
 
485
564
  else
486
565
  "#{col_identifier}{class: \"form-group \#{'alert-danger' if @#{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
487
566
  #{col_spaces_prepend}= f.text_field :#{col.to_s}, value: #{singular}.#{col.to_s}, class: 'form-control', size: 4, type: 'number'
488
- #{col_spaces_prepend} %label.form-text
489
- #{col_spaces_prepend} #{col.to_s.humanize}\n"
567
+ #{col_spaces_prepend}%label.form-text
568
+ #{col_spaces_prepend} #{col.to_s.humanize}\n"
490
569
  end
491
570
  when :string
492
571
  limit ||= 256
@@ -528,7 +607,7 @@ module HotGlue
528
607
  #{col_spaces_prepend}= f.label(:#{col.to_s}, value: 'Yes', for: '#{singular}_#{col.to_s}_1')
529
608
  "
530
609
  end
531
-
610
+ end
532
611
  }.join("\n")
533
612
  return res
534
613
  end
@@ -555,24 +634,27 @@ module HotGlue
555
634
  assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
556
635
 
557
636
  if assoc.nil?
558
- puts "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
559
- exit
637
+ exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
638
+ raise(HotGlue::Error,exit_message)
560
639
  end
561
640
 
562
641
  assoc_class = eval(assoc.class_name)
563
642
 
564
- if assoc_class.column_names.include?("name")
643
+ if assoc_class.respond_to?("name")
565
644
  display_column = "name"
566
- elsif assoc_class.column_names.include?("to_label")
645
+ elsif assoc_class.respond_to?("to_label")
567
646
  display_column = "to_label"
568
- elsif assoc_class.column_names.include?("full_name")
647
+ elsif assoc_class.respond_to?("full_name")
569
648
  display_column = "full_name"
570
- elsif assoc_class.column_names.include?("display_name")
649
+ elsif assoc_class.respond_to?("display_name")
571
650
  display_column = "display_name"
572
- elsif assoc_class.column_names.include?("email")
651
+ elsif assoc_class.respond_to?("email")
573
652
  display_column = "email"
653
+ elsif assoc_class.respond_to?("number")
654
+ display_column = "number"
655
+
574
656
  else
575
- puts "*** Oops: Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, or 5) email directly on your #{assoc.class_name} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
657
+ puts "*** Oops: Can't find any column to use as the display label for the #{assoc.name.to_s} association on the #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{assoc.class_name} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
576
658
  end
577
659
 
578
660
  "#{col_identifer}
@@ -642,6 +724,30 @@ module HotGlue
642
724
  end
643
725
 
644
726
 
727
+
728
+ def display_class
729
+ me = eval(singular_class)
730
+
731
+ @display_class ||=
732
+ if me.respond_to?("name")
733
+ "name"
734
+ elsif me.respond_to?("to_label")
735
+ "to_label"
736
+ elsif me.respond_to?("full_name")
737
+ "full_name"
738
+ elsif me.respond_to?("display_name")
739
+ "display_name"
740
+ elsif me.respond_to?("email")
741
+ "email"
742
+ elsif me.respond_to?("number")
743
+ display_column = "number"
744
+
745
+ else
746
+ exit_message = "*** Oops: Can't find any column to use as the display label on #{singular_class} model . TODO: Please implement just one of: 1) name, 2) to_label, 3) full_name, 4) display_name, 5) email, or 6) number directly on your #{singular_class} model (either as database field or model methods), then RERUN THIS GENERATOR. (If more than one is implemented, the field to use will be chosen based on the rank here, e.g., if name is present it will be used; if not, I will look for a to_label, etc)"
747
+ raise(HotGlue::Error, exit_message)
748
+ end
749
+ end
750
+
645
751
  def destroy_action
646
752
  return false if @self_auth
647
753
  return !@no_delete
@@ -660,7 +766,13 @@ module HotGlue
660
766
  end
661
767
  end
662
768
 
663
- private # thor does something fancy like sending the class all of its own methods during some strange run sequence
769
+
770
+
771
+ def paginate
772
+ "= paginate #{plural}"
773
+ end
774
+
775
+ private # thor does something fancy like sending the class all of its own methods during some strange run sequence
664
776
  # does not like public methods
665
777
 
666
778
  def cc_filename_with_extensions(name, file_format = format)