hot-glue 0.2.0 → 0.2.4

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
  SHA256:
3
- metadata.gz: 81ca38b1bfb68e173a1665d924729b04afa26ccda900d707508a64e01977f1ad
4
- data.tar.gz: 8d2b98c07d84ec264600d79f5073139ea717a3b66488b5b269a4466bc5eb04be
3
+ metadata.gz: 51ed0488e72bcd508f979de89c9f9d11ee1284c702c22066e72311d9cee03894
4
+ data.tar.gz: f30e2325ec4a08af8df44fa54e955b103aed04b650e2b165bcded589d2f8faa6
5
5
  SHA512:
6
- metadata.gz: 4525044b21596dd6dc96d7aa397402421459ec483749df04dd08ad3f20de7a6a1998e38b9436d77522c48dedabb78a3b4e9e88ce2225e2c8633b8c32a30fa8a8
7
- data.tar.gz: 06d16a32919eb23b306add1ca5e1997694f0bbbb21d0bc045992530b2963cf65f6dbb987fb3223b50a1e543598e1f42611f17b80b206fb032d2c00d8ddb72eb9
6
+ metadata.gz: 8eb5cf4982698c4b51ac9caa4c223885ea9f8c2eac423c45e11ff2c7ccbb6c8aaad0e5f43d00cdf4ef3376a04bdc5ea3477813302a1fec8cc3d82e22463a5b51
7
+ data.tar.gz: 94af84f2f7e66846e593e8ab7ac5c441fbd4b8814c1fc390823a97350fe00854f6c91868094820ca3461e28b10a671cc892430b5d86621a88ef8700376b81a87
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+
3
+ before_install:
4
+ - gem update --system
5
+
6
+
7
+ branches:
8
+ only:
9
+ - main
10
+
11
+
12
+ script: "rake spec"
13
+
14
+ rvm:
15
+ - 2.7.2
data/Gemfile CHANGED
@@ -3,8 +3,14 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
 
4
4
  gemspec
5
5
 
6
+ # not required for your app
6
7
  gem 'sqlite3'
7
8
  gem 'byebug'
8
-
9
9
  gem 'rails', '6.1'
10
- gem 'devise', require: true
10
+ gem 'devise', require: true
11
+
12
+
13
+ # for testing
14
+ gem "rails-controller-testing", group: [:test]
15
+ gem "database_cleaner", group: [:test]
16
+ gem "rspec-rails", group: [:test]
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.2.0)
4
+ hot-glue (0.2.3)
5
5
  ffaker (~> 2.16)
6
6
  haml-rails (~> 2.0)
7
7
  kaminari (~> 1.2)
8
- rails (~> 6.0)
8
+ rails (> 5.1, <= 7.0.0)
9
9
  sass-rails
10
10
  turbo-rails (~> 0.5)
11
11
 
@@ -76,12 +76,19 @@ GEM
76
76
  byebug (11.1.3)
77
77
  concurrent-ruby (1.1.9)
78
78
  crass (1.0.6)
79
+ database_cleaner (2.0.1)
80
+ database_cleaner-active_record (~> 2.0.0)
81
+ database_cleaner-active_record (2.0.1)
82
+ activerecord (>= 5.a)
83
+ database_cleaner-core (~> 2.0.0)
84
+ database_cleaner-core (2.0.1)
79
85
  devise (4.8.0)
80
86
  bcrypt (~> 3.0)
81
87
  orm_adapter (~> 0.1)
82
88
  railties (>= 4.1.0)
83
89
  responders
84
90
  warden (~> 1.2.3)
91
+ diff-lcs (1.4.4)
85
92
  erubi (1.10.0)
86
93
  erubis (2.7.0)
87
94
  ffaker (2.19.0)
@@ -154,6 +161,10 @@ GEM
154
161
  bundler (>= 1.15.0)
155
162
  railties (= 6.1.0)
156
163
  sprockets-rails (>= 2.0.0)
164
+ rails-controller-testing (1.0.5)
165
+ actionpack (>= 5.0.1.rc1)
166
+ actionview (>= 5.0.1.rc1)
167
+ activesupport (>= 5.0.1.rc1)
157
168
  rails-dom-testing (2.0.3)
158
169
  activesupport (>= 4.2.0)
159
170
  nokogiri (>= 1.6)
@@ -169,6 +180,23 @@ GEM
169
180
  responders (3.0.1)
170
181
  actionpack (>= 5.0)
171
182
  railties (>= 5.0)
183
+ rspec-core (3.10.1)
184
+ rspec-support (~> 3.10.0)
185
+ rspec-expectations (3.10.1)
186
+ diff-lcs (>= 1.2.0, < 2.0)
187
+ rspec-support (~> 3.10.0)
188
+ rspec-mocks (3.10.2)
189
+ diff-lcs (>= 1.2.0, < 2.0)
190
+ rspec-support (~> 3.10.0)
191
+ rspec-rails (5.0.2)
192
+ actionpack (>= 5.2)
193
+ activesupport (>= 5.2)
194
+ railties (>= 5.2)
195
+ rspec-core (~> 3.10)
196
+ rspec-expectations (~> 3.10)
197
+ rspec-mocks (~> 3.10)
198
+ rspec-support (~> 3.10)
199
+ rspec-support (3.10.2)
172
200
  ruby_parser (3.17.0)
173
201
  sexp_processor (~> 4.15, >= 4.15.1)
174
202
  sass-rails (6.0.0)
@@ -193,7 +221,7 @@ GEM
193
221
  temple (0.8.2)
194
222
  thor (1.1.0)
195
223
  tilt (2.0.10)
196
- turbo-rails (0.7.11)
224
+ turbo-rails (0.8.1)
197
225
  rails (>= 6.0.0)
198
226
  tzinfo (2.0.4)
199
227
  concurrent-ruby (~> 1.0)
@@ -210,10 +238,13 @@ PLATFORMS
210
238
 
211
239
  DEPENDENCIES
212
240
  byebug
241
+ database_cleaner
213
242
  devise
214
243
  hot-glue!
215
244
  rails (= 6.1)
245
+ rails-controller-testing
246
+ rspec-rails
216
247
  sqlite3
217
248
 
218
249
  BUNDLED WITH
219
- 2.2.19
250
+ 2.1.4
data/README.md CHANGED
@@ -1,7 +1,17 @@
1
1
 
2
+ [![Build Status](https://app.travis-ci.com/jasonfb/hot-glue.svg?branch=main)](https://travis-ci.com/jasonfb/hot-glue)
3
+
4
+
2
5
  Hot Glue is a Rails scaffold builder for the Turbo era. It is an evolution of the admin-interface style scaffolding systems of the 2010s ([activeadmin](https://github.com/activeadmin/activeadmin), [rails_admin](https://github.com/sferik/rails_admin), and [active_scaffold](https://github.com/activescaffold/active_scaffold)).
3
6
 
4
- Using Turbo-Rails and Hotwire you get a lightning-fast out-of-the-box CRUD building experience. Every page displays only a list view: new and edit operations happen as 'edit-in-place', so the user never leaves the page.
7
+
8
+ Using Turbo-Rails and Hotwire (default in Rails 7) you get a lightning-fast out-of-the-box CRUD building experience.
9
+
10
+ Every page displays only a list view: new and edit operations happen as 'edit-in-place', so the user never leaves the page.
11
+
12
+ Because all page navigation is Turbo's responsibilty, everything plugs & plays nicely into a Turbo-backed Rails app.
13
+
14
+ Alternatively, you can use this tool to create a Turbo-backed *section* of your Rails app-- like an admin interface -- while still treating the rest of the Rails app as an API or building out other features by hand.
5
15
 
6
16
  It will read your relationships and field types to generate your code for you, leaving you with a 'sourdough starter' to work from. If you modify the generated code, you're on your own if you want to preserve your changes and also re-generate scaffold after adding fields.
7
17
 
@@ -15,7 +25,7 @@ Hot Glue generates functionality that's quick and dirty. It let's you be crafty.
15
25
  * Automatically reads your ActiveRecord models and relationships (make them before building your scaffolding!)
16
26
  * Create-read-update-delete (CRUD) with pagination (one day: sorting & searching)
17
27
  * Excellent tool for prototyping and hackathons, but a knowledge of Rails is needed.
18
- * Nest your routes model-by-model for built-in poor man's authentication. (Customers have_many :invoices; Invoices have_many :line_items; etc)
28
+ * Nest your routes model-by-model for built-in poor man's access control. (Customers have_many :invoices; Invoices have_many :line_items; etc)
19
29
  * Plays nicely with Devise, but you can implement your own current_user object instead.
20
30
  * Kaminari for pagination.
21
31
  * Create specs automatically along with the controllers.
@@ -44,8 +54,25 @@ Instantly get a simple CRUD interface
44
54
 
45
55
  ![hot-glue-4](https://user-images.githubusercontent.com/59002/116405517-c2b2e300-a7fd-11eb-8423-d43e3afc9fa6.gif)
46
56
 
57
+ ## TO INSTALL (RAILS 7)
58
+
59
+ - Install Turbo `rails turbo:install` (?)
47
60
 
48
- ## TO INSTALL
61
+ - Add `gem 'hot-glue'` to your Gemfile
62
+ - `bundle install`
63
+ - `rails generate hot_glue:install --markup=erb` for ERB
64
+ - or `rails generate hot_glue:install --markup=haml` for HAML
65
+
66
+ - Add to your `application.html.erb`
67
+ ```
68
+ <%= render partial: 'layouts/flash_notices' %>
69
+ ```
70
+ - Or for Haml add to your `application.haml`
71
+ ```
72
+ = render partial: 'layouts/flash_notices'
73
+ ```
74
+
75
+ ## TO INSTALL (RAILS 6)
49
76
 
50
77
  - Add `gem 'turbo-rails'` to your Gemfile & `bundle install`
51
78
 
@@ -55,14 +82,27 @@ Instantly get a simple CRUD interface
55
82
 
56
83
  - Add `gem 'hot-glue'` to your Gemfile & `bundle install`
57
84
 
58
- - Run the hot-glue installation with `rails generate hot_glue:install`
85
+ - in `javascript/packs/application.js` remove this line:
86
+ `import Turbolinks from "turbolinks"`
87
+
88
+ - in the same file (`javascript/packs/application.js`) add this line:
89
+ `import { Turbo } from "@hotwired/turbo-rails"`
90
+
91
+ - Run the hot-glue install generator
92
+
93
+ FOR ERB:
94
+ `rails generate hot_glue:install --markup=erb`
95
+
96
+ FOR HAML:
97
+ `rails generate hot_glue:install --markup=haml`
59
98
 
60
99
  - Add to your `application.html.erb`
61
100
  ```
62
101
  <%= render partial: 'layouts/flash_notices' %>
63
102
  ```
64
103
 
65
- - Rspec setup
104
+
105
+ ## Rspec setup
66
106
  - add `gem 'rspec-rails'` to your gemfile inside :development and :test
67
107
  - add `gem 'factory_bot_rails'` to your gemfile inside :development and :test
68
108
  - run `rails generate rspec:install`
@@ -88,10 +128,28 @@ Instantly get a simple CRUD interface
88
128
  end
89
129
  ```
90
130
 
91
- - Install Bootstrap (optional)
131
+ ## Install Bootstrap using Sprockets (IMPORTANT: YOU DO NOT NEED JQUERY*)
132
+ Bootstrap with Sprockets for Rails 5 or 7 default — Rails 6 custom
133
+ - use twbs/bootstrap-rubygem gem
134
+ - see README for bootstrap-rubygem to install
135
+ Bootstrap with Webpack for FOR RAILS 7 :
136
+
137
+ - add to Gemfile
138
+ - gem 'bootstrap', '~> 5.1.0'
139
+
140
+
141
+ - completely delete the file `app/assets/application.css`
142
+ - create new file where it was `app/assets/application.scss` with this contents (do not keep the contents of the old application.css file):
143
+
144
+ ```
145
+ // Custom bootstrap variables must be set or imported *before* bootstrap.
146
+ @import "bootstrap";
147
+ ```
148
+
149
+ * You do not need jQuery for HotGlue to work *
92
150
 
93
- Bootstrap with Webpack:
94
- - change `stylesheet_link_tag` to `stylesheet_pack_tag` in your application layout
151
+ ### Bootstrap with Webpack RAILS 6 ONLY:
152
+ - change `stylesheet_link_tag` to `stylesheet_pack_tag` in your application layout
95
153
  - run `yarn add bootstrap`
96
154
  - create a new file at `app/javascript/require_bootstrap.scss` with this content
97
155
  ```
@@ -102,16 +160,14 @@ Bootstrap with Webpack:
102
160
  ```
103
161
  import 'require_bootstrap'
104
162
  ```
105
-
106
- Bootstrap with Sprockets:
107
- - use bootstrap-rubygem gem
108
- - see README for bootstrap-rubygem to install
109
163
 
110
164
 
111
- - Install Devise or implement your own authentication
165
+
166
+
167
+ ## Install Devise or implement your own authentication
112
168
  (or only use --gd mode, see below)
113
169
 
114
- - font-awesome
170
+ ## install font-awesome. I recommend https://github.com/tomkra/font_awesome5_rails or https://github.com/FortAwesome/font-awesome-sass
115
171
 
116
172
 
117
173
  ### First Argument
@@ -188,7 +244,7 @@ Then, finally the @charge will be loaded
188
244
 
189
245
  `@charge = @line.charges.find(params[:id])`
190
246
 
191
- It's called "poor man's auth" because if a user attempts to hack the URL by passing ids for objects they don't own--- which Rails makes relatively easy with its default URL pattern-- they will hit ActiveRecord not found errors (the objects they don't own won't be found in the associated relationship).
247
+ It's called "poor man's access control" because if a user attempts to hack the URL by passing ids for objects they don't own--- which Rails makes relatively easy with its default URL pattern-- they will hit ActiveRecord not found errors (the objects they don't own won't be found in the associated relationship).
192
248
 
193
249
  It works, but it isn't granular. As well, it isn't appropriate for a large app with any level of intricacy to access control (that is, having roles).
194
250
 
@@ -201,7 +257,7 @@ By default, it will be assumed you have a `current_user` for your user authentic
201
257
 
202
258
  The poor man's auth presumes that object graphs have only one natural way to traverse them (that is, one primary way to traverse them), and that all relationships infer that a set of things or their descendants are granted access to me for reading, writing, updating, and deleting.
203
259
 
204
- Of course this is a sloppy way to do authentication, and can easily leave open endpoints your real users shouldn't have access to.
260
+ Of course this is a sloppy way to do access control, and can easily leave open endpoints your real users shouldn't have access to.
205
261
 
206
262
  When you display anything built with the scaffolding, we assume the `current_user` will have `has_many` association that matches the pluralized name of the scaffold. In the case of nesting, we will automatically find the nested objects first, then continue down the nest chain to find the target object. In this way, we know that all object are 'anchored' to the logged-in user.
207
263
 
@@ -303,21 +359,37 @@ IMPORTANT: By default, all fields that begin with an underscore (`_`) are automa
303
359
 
304
360
  I would recommend this for fields you want globally non-editable by users in your app. For example, a counter cache or other field set only by a backend mechanism.
305
361
 
306
- ### `--god` or `--gd`
362
+ ### `--stimulus_syntax=true` or `--stimulus_syntax=false`
363
+ (for Rails <=6, default is false. For Rails 7, default is true.)
307
364
 
308
- Use this flag to create controllers with no root authentication. You can still use an auth_identifier, which can be useful for a meta-leval authentication to the controller.
365
+ Stimulus is only used for the delete button's confirmation dialog.
309
366
 
310
- For example, FOR ADMIN CONTROLLERS ONLY, supply a auth_identifier and use `--god` flag.
367
+ If you don't have stimulus syntax enabled, your delete buttons have this. This will confirm the delete with a simple alert if you have UJS enabled.
368
+
369
+ ```
370
+ {confirm: 'Are you sure?'}
371
+ ```
372
+
373
+ If you do have Stimulus syntax enabled, your delete buttons will look like so:
374
+ ```
375
+ <%= button_to "Delete <i class='fa fa-1x fa-remove'></i>".html_safe,
376
+ thing_path(branch), method: :delete,
377
+ data: {
378
+ 'controller: 'confirmable',
379
+ 'confirm-message': 'Are you sure you want to delete Thing?',
380
+ 'action': 'confirmation#confirm'
381
+ },
382
+ disable_with: "Loading...", class: "delete-branch-button btn btn-primary " %>
383
+ ```
384
+
385
+ Your install script will output an additional stimulus controller:
311
386
 
312
- In Gd mode, the objects are loaded directly from the base class (these controllers have full access)
313
387
  ```
314
- def load_thing
315
- @thing = Thing.find(params[:id])
316
- end
317
388
 
318
389
  ```
319
390
 
320
391
 
392
+
321
393
  ### `--markup` (default: 'erb')
322
394
 
323
395
  ERB is default. For HAML, `--markup=haml`.
@@ -326,6 +398,21 @@ ERB is default. For HAML, `--markup=haml`.
326
398
  ## FLAGS (Options with no values)
327
399
  These options (flags) also uses `--` syntax but do not take any values. Everything is assumed (default) to be false unless specified.
328
400
 
401
+ ### `--god` or `--gd`
402
+
403
+ Use this flag to create controllers with no root authentication. You can still use an auth_identifier, which can be useful for a meta-leval authentication to the controller.
404
+
405
+ For example, FOR ADMIN CONTROLLERS ONLY, supply a auth_identifier and use `--god` flag.
406
+
407
+ In Gd mode, the objects are loaded directly from the base class (these controllers have full access)
408
+ ```
409
+ def load_thing
410
+ @thing = Thing.find(params[:id])
411
+ end
412
+
413
+ ```
414
+
415
+
329
416
  ### `--specs-only`
330
417
 
331
418
  Produces ONLY the controller spec file, nothing else.
@@ -351,15 +438,46 @@ Omits delete action.
351
438
 
352
439
  ### `--big-edit`
353
440
 
354
- If you do not want inline editing of your list items but instead to fall back to old fashioned new page behavior for your edit views, use `--big-edit`.
441
+ If you do not want inline editing of your list items but instead to fall back to full page style behavior for your edit views, use `--big-edit`. Turbo still handles the page interactions, but the user is taken to a full-screen edit page instead of an edit-in-place interaction.
442
+
355
443
 
444
+ ## Automatic Base Controller
356
445
 
446
+ HotGlue will copy a file named base_controller.rb to the same folder where it tries to create any controller, unless such a file exists there already.
447
+
448
+ Obviously, the created controller will always have this base controller as its subclass. In this way, you are encouraged to implement functionality common to the *namespace* (shared between the controllers in the namespace), using this technique.
449
+
450
+ ## Field Types Supported
451
+
452
+ - Integers that don't end with `_id`, they will be displayed as text fields.
453
+ - Integers that do end with `_id` will be treated automatically as associations. You should have a Rails association defined. (Hot Glue will warn you if it can't find one.)
454
+ - String*
455
+ - Text*
456
+ - Float*
457
+ - Datetime
458
+ - Date (TOOD: implement this)
459
+ - Time (TOOD: implement this)
460
+ - Boolean
461
+ - Enum - will be magically displayed as a value list populated from the enum list defined on your model. see https://jasonfleetwoodboldt.com/courses/stepping-up-rails/enumerated-types-in-rails-and-postgres/
462
+
463
+ * shows in a size-aware container, i.e. in a bigger box if the field allows for more content
357
464
 
358
465
 
359
466
 
360
467
  # VERSION HISTORY
361
468
 
362
- #### 2021-09-06 - v0.2.0 - SLIM and ERB ; use the option --markup=erb or --markup=haml (default is now erb)
469
+ #### 2021-10-07 - v0.2.4 - removes erroneous icons display in delete buttos (these don't work inside of button_to);
470
+ - adds support for ENUM types direclty on your field types
471
+ - you must use activerecord-pgenum
472
+ - see my blog post at https://jasonfleetwoodboldt.com/courses/stepping-up-rails/enumerated-types-in-rails-and-postgres/
473
+
474
+ #### 2021-09-30 - v0.2.3 - fixes ERB output for show-only fields; fixes flash_notices for erb or haml; adds @stimulus_syntax flag for delete confirmations with stimulus
475
+
476
+ #### 2021-09-27 - v0.2.2 - Fixes some issues with related fields; unlocks Rails 7 in Gemspec file
477
+
478
+ #### 2021-09-20 - v0.2.1 - Fixes nesting behavior when using gd option
479
+
480
+ #### 2021-09-06 - v0.2.0 - ERB or HAML; use the option --markup=erb or --markup=haml (default is now erb)
363
481
 
364
482
  #### 2021-06-28 - v0.1.2 - fixes problem with namespaces on path helpers
365
483
 
data/Rakefile CHANGED
@@ -1,32 +1,42 @@
1
+
1
2
  begin
2
3
  require 'bundler/setup'
3
4
  rescue LoadError
4
5
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
6
  end
6
7
 
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'HotGlue'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.md')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
16
-
17
- APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
18
- load 'rails/tasks/engine.rake'
19
-
20
- load 'rails/tasks/statistics.rake'
21
-
22
- require 'bundler/gem_tasks'
23
-
24
- require 'rake/testtask'
25
-
26
- Rake::TestTask.new(:test) do |t|
27
- t.libs << 'test'
28
- t.pattern = 'test/**/*_test.rb'
29
- t.verbose = false
8
+ begin
9
+ require 'rspec/core/rake_task'
10
+ RSpec::Core::RakeTask.new(:spec)
11
+ task :default => :spec
12
+ rescue LoadError
13
+ puts 'FAILED: unable to load rspec/core/rake_task in Rakefile'
30
14
  end
31
15
 
32
- task default: :test
16
+ #
17
+ # require 'rdoc/task'
18
+ #
19
+ # RDoc::Task.new(:rdoc) do |rdoc|
20
+ # rdoc.rdoc_dir = 'rdoc'
21
+ # rdoc.title = 'HotGlue'
22
+ # rdoc.options << '--line-numbers'
23
+ # rdoc.rdoc_files.include('README.md')
24
+ # rdoc.rdoc_files.include('lib/**/*.rb')
25
+ # end
26
+ #
27
+ # APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
28
+ # load 'rails/tasks/engine.rake'
29
+ #
30
+ # load 'rails/tasks/statistics.rake'
31
+ #
32
+ # require 'bundler/gem_tasks'
33
+
34
+ # require 'rake/testtask'
35
+ #
36
+ # Rake::TestTask.new(:test) do |t|
37
+ # t.libs << 'test'
38
+ # t.pattern = 'test/**/*_test.rb'
39
+ # t.verbose = false
40
+ # end
41
+ #
42
+ # task default: :test
@@ -1,4 +1,8 @@
1
1
  module HotGlueHelper
2
2
 
3
+ def enum_to_collection_select(hash)
4
+ hash.collect{|k,v| OpenStruct.new({key: k, value: v})}
5
+
6
+ end
3
7
 
4
8
  end
@@ -4,13 +4,25 @@ require 'ffaker'
4
4
  module HotGlue
5
5
  class InstallGenerator < Rails::Generators::Base
6
6
  hook_for :form_builder, :as => :scaffold
7
+ class_option :markup, type: :string, default: "erb"
7
8
 
8
9
  source_root File.expand_path('templates', __dir__)
9
10
 
10
11
 
11
12
  def initialize(*args) #:nodoc:
12
13
  super
13
- copy_file "_flash_notices.haml", "#{'spec/dummy/' if Rails.env.test?}app/views/layouts/_flash_notices.haml"
14
+ @markup = options['markup']
15
+ if @markup == "haml"
16
+ copy_file "haml/_flash_notices.haml", "#{'spec/dummy/' if Rails.env.test?}app/views/layouts/_flash_notices.haml"
17
+ elsif @markup == "erb"
18
+ copy_file "erb/_flash_notices.erb", "#{'spec/dummy/' if Rails.env.test?}app/views/layouts/_flash_notices.erb"
19
+
20
+ end
21
+
22
+ if Rails.version.split(".")[0].to_i >= 7
23
+ copy_file "confirmable.js", "#{'spec/dummy/' if Rails.env.test?}app/javascript/controllers/confirmable.js"
24
+
25
+ end
14
26
  end
15
27
  end
16
28
  end
@@ -1,6 +1,7 @@
1
1
  module HotGlue
2
2
  class ErbTemplate < TemplateBase
3
3
 
4
+ # include GeneratorHelper
4
5
  attr_accessor :singular
5
6
 
6
7
  def field_output(col, type = nil, width, col_identifier )
@@ -18,7 +19,6 @@ module HotGlue
18
19
 
19
20
 
20
21
  def all_form_fields(*args)
21
-
22
22
  columns = args[0][:columns]
23
23
  show_only = args[0][:show_only]
24
24
  singular_class = args[0][:singular_class]
@@ -35,10 +35,11 @@ module HotGlue
35
35
 
36
36
  if show_only.include?(col)
37
37
 
38
- "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
39
- = @#{singular}.#{col.to_s}
40
- %label.form-text
41
- #{col.to_s.humanize}\n"
38
+ "<div class=\"#{col_identifier} form-group <%= 'alert-danger' if #{singular}.errors.details.keys.include?(:#{col}) %>\">" +
39
+ "<%= @#{singular}.#{col.to_s} %>" +
40
+ "<label class='form-text'>#{col.to_s.humanize}</label>" +
41
+ "</div>"
42
+
42
43
  else
43
44
 
44
45
 
@@ -56,15 +57,14 @@ module HotGlue
56
57
  exit_message= "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
57
58
  exit
58
59
  end
59
- display_column = derrive_reference_name(assoc.class_name)
60
+ display_column = HotGlue.derrive_reference_name(assoc.class_name)
60
61
 
61
-
62
- "<div class='#{col_identifier} form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{assoc_name.to_s})}>
63
- <%= f.collection_select(:#{col.to_s}, #{assoc.class_name}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control')
62
+ "<div class='#{col_identifier} form-group <%= 'alert-danger' if #{singular}.errors.details.keys.include?(:#{assoc_name.to_s}) %>' >
63
+ <%= f.collection_select(:#{col.to_s}, #{assoc.class_name}.all, :id, :#{display_column}, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control') %>
64
64
  <label class='small form-text text-muted'>#{col.to_s.humanize}</label></div>"
65
65
 
66
66
  else
67
- "<div class=\"#{col_identifier} form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col})}\" >
67
+ "<div class=\"#{col_identifier} form-group <%= 'alert-danger' if #{singular}.errors.details.keys.include?(:#{col}) %> \" >
68
68
  <%= f.text_field :#{col.to_s}, value: #{singular}.#{col.to_s}, class: 'form-control', size: 4, type: 'number' %>
69
69
  <label class='small form-text text-muted'>#{col.to_s.humanize}</label></div>"
70
70
 
@@ -112,7 +112,14 @@ module HotGlue
112
112
  " <%= f.radio_button(:#{col.to_s}, '1', checked: #{singular}.#{col.to_s} ? 'checked' : '') %>\n" +
113
113
  " <%= f.label(:#{col.to_s}, value: 'Yes', for: '#{singular}_#{col.to_s}_1') %>\n" +
114
114
  "</div>"
115
+ when :enum
116
+ enum_name ="enum_name"
117
+ "<div class='#{col_identifier} form-group <%= 'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s}) %>' >
118
+ <%= f.collection_select(:#{col.to_s}, enum_to_collection_select( #{singular_class}.defined_enums['#{col.to_s}']), :key, :value, {prompt: true, selected: @#{singular}.#{col.to_s} }, class: 'form-control') %>
119
+ <label class='small form-text text-muted'>#{col.to_s.humanize}</label></div>"
120
+
115
121
  end
122
+
116
123
  end
117
124
  }.join("\n")
118
125
  return res
@@ -156,8 +163,7 @@ module HotGlue
156
163
  raise(HotGlue::Error,exit_message)
157
164
  end
158
165
 
159
- display_column = derrive_reference_name(assoc.class_name)
160
-
166
+ display_column = HotGlue.derrive_reference_name(assoc.class_name)
161
167
 
162
168
  "<div class='#{col_identifer}'>
163
169
  <%= #{singular}.#{assoc.name.to_s}.try(:#{display_column}) || '<span class=\"content alert-danger\">MISSING</span>'.html_safe %>
@@ -169,9 +175,8 @@ module HotGlue
169
175
  end
170
176
  when :float
171
177
  width = (limit && limit < 40) ? limit : (40)
172
- "#{col_identifer}
173
- = #{singular}.#{col}"
174
-
178
+ "<div class='#{col_identifer}'>
179
+ <%= #{singular}.#{col}%></div>"
175
180
  when :string
176
181
  width = (limit && limit < 40) ? limit : (40)
177
182
  "<div class='#{col_identifer}'>
@@ -217,6 +222,14 @@ module HotGlue
217
222
  NO
218
223
  <% end %>
219
224
  </div>
225
+ " when :enum
226
+ "<div class='#{col_identifer}'>
227
+ <% if #{singular}.#{col}.nil? %>
228
+ <span class='alert-danger'>MISSING</span>
229
+ <% else %>
230
+ <%= #{singular}.#{col} %>
231
+ <% end %>
232
+ </div>
220
233
  "
221
234
  end #end of switch
222
235
  }.join("\n")
@@ -1,6 +1,19 @@
1
1
  module HotGlue
2
2
  class HamlTemplate < TemplateBase
3
3
 
4
+ def text_area_output(col, field_length, col_identifier )
5
+ lines = field_length % 40
6
+ if lines > 5
7
+ lines = 5
8
+ end
9
+
10
+ "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
11
+ = f.text_area :#{col.to_s}, class: 'form-control', cols: 40, rows: '#{lines}'
12
+ %label.form-text
13
+ #{col.to_s.humanize}\n"
14
+ end
15
+
16
+
4
17
  attr_accessor :singular
5
18
 
6
19
  def field_output(col, type = nil, width, col_identifier )
@@ -10,56 +10,32 @@ module HotGlue
10
10
  class Error < StandardError
11
11
  end
12
12
 
13
- module GeneratorHelper
14
- def derrive_reference_name thing_as_string
15
- assoc_class = eval(thing_as_string)
16
-
17
- if assoc_class.respond_to?("name")
18
- display_column = "name"
19
- elsif assoc_class.respond_to?("to_label")
20
- display_column = "to_label"
21
- elsif assoc_class.respond_to?("full_name")
22
- display_column = "full_name"
23
- elsif assoc_class.respond_to?("display_name")
24
- display_column = "display_name"
25
- elsif assoc_class.respond_to?("email")
26
- display_column = "email"
27
- else
28
- raise("this should have been caught by the checker in the initializer")
29
- # 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)"
30
- end
31
- display_column
32
- end
33
-
34
-
35
- def text_area_output(col, field_length, col_identifier )
36
- lines = field_length % 40
37
- if lines > 5
38
- lines = 5
39
- end
40
-
41
- "#{col_identifier}{class: \"form-group \#{'alert-danger' if #{singular}.errors.details.keys.include?(:#{col.to_s})}\"}
42
- = f.text_area :#{col.to_s}, class: 'form-control', cols: 40, rows: '#{lines}'
43
- %label.form-text
44
- #{col.to_s.humanize}\n"
45
- end
46
-
47
-
48
-
49
-
13
+ def self.derrive_reference_name(thing_as_string)
14
+ assoc_class = eval(thing_as_string)
15
+
16
+ if assoc_class.respond_to?("name")
17
+ display_column = "name"
18
+ elsif assoc_class.respond_to?("to_label")
19
+ display_column = "to_label"
20
+ elsif assoc_class.respond_to?("full_name")
21
+ display_column = "full_name"
22
+ elsif assoc_class.respond_to?("display_name")
23
+ display_column = "display_name"
24
+ elsif assoc_class.respond_to?("email")
25
+ display_column = "email"
26
+ else
27
+ raise("this should have been caught by the checker in the initializer")
28
+ # 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)"
29
+ end
30
+ display_column
50
31
  end
51
32
 
52
-
53
33
  class ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
54
- hook_for :form_builder, :as => :scaffold
34
+ hook_for :form_builder, :as => :scaffold
55
35
 
56
36
  source_root File.expand_path('templates', __dir__)
57
37
  attr_accessor :path, :singular, :plural, :singular_class, :nest_with
58
38
 
59
-
60
- include GeneratorHelper
61
-
62
-
63
39
  class_option :singular, type: :string, default: nil
64
40
  class_option :plural, type: :string, default: nil
65
41
  class_option :singular_class, type: :string, default: nil
@@ -79,6 +55,7 @@ module HotGlue
79
55
  class_option :big_edit, type: :boolean, default: false
80
56
  class_option :show_only, type: :string, default: ""
81
57
  class_option :markup, type: :string, default: "erb"
58
+ class_option :stimulus_syntax, type: :boolean, default: nil
82
59
 
83
60
 
84
61
 
@@ -104,6 +81,14 @@ module HotGlue
104
81
  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.")
105
82
  end
106
83
 
84
+ if @stimulus_syntax.nil?
85
+ if Rails.version.split(".")[0].to_i >= 7
86
+ @stimulus_syntax = true
87
+ else
88
+ @stimulus_syntax = false
89
+ end
90
+ end
91
+
107
92
  if options['markup'] == "erb"
108
93
  @template_builder = HotGlue::ErbTemplate.new
109
94
  elsif options['markup'] == "slim"
@@ -188,6 +173,8 @@ module HotGlue
188
173
  end
189
174
  end
190
175
 
176
+ @reference_name = HotGlue.derrive_reference_name(singular_class)
177
+
191
178
  identify_object_owner
192
179
  setup_fields
193
180
  end
@@ -196,7 +183,7 @@ module HotGlue
196
183
  auth_assoc = @auth && @auth.gsub("current_","")
197
184
 
198
185
  if !@object_owner_sym.empty?
199
- auth_assoc_field = auth_assoc + "_id"
186
+ auth_assoc_field = auth_assoc + "_id" unless @god
200
187
  assoc = eval("#{singular_class}.reflect_on_association(:#{@object_owner_sym})")
201
188
 
202
189
  if assoc
@@ -299,9 +286,10 @@ module HotGlue
299
286
  nil
300
287
  end
301
288
 
289
+
290
+
302
291
  def copy_controller_and_spec_files
303
292
  @default_colspan = @columns.size
304
-
305
293
  unless @specs_only
306
294
  template "controller.rb.erb", File.join("#{'spec/dummy/' if Rails.env.test?}app/controllers#{namespace_with_dash}", "#{plural}_controller.rb")
307
295
  if @namespace
@@ -431,7 +419,14 @@ module HotGlue
431
419
  end
432
420
 
433
421
  def new_path_name
434
- "new_#{@namespace+"_" if @namespace}#{singular}_path"
422
+
423
+ base = "new_#{@namespace+"_" if @namespace}#{(@nested_args.join("_") + "_") if @nested_args.any?}#{singular}_path"
424
+ if @nested_args.any?
425
+ base += "(" + @nested_args.collect { |arg|
426
+ "@#{arg}.id"
427
+ }.join(", ") + ")"
428
+ end
429
+ base
435
430
  end
436
431
 
437
432
  def nested_assignments
@@ -661,9 +656,19 @@ module HotGlue
661
656
  end
662
657
  end
663
658
 
664
- def paginate
665
- @template_builder.paginate(plural: plural)
659
+ def paginate
660
+ @template_builder.paginate(plural: plural)
661
+ end
662
+
663
+ def delete_confirmation_syntax
664
+ if !@stimulus_syntax
665
+ "{confirm: 'Are you sure?'}"
666
+ else
667
+ "{controller: 'confirmable', 'confirm-message': \"Are you sure you want to delete \#{ #{@singular}.#{ display_class } } \", 'action': 'confirmation#confirm'}"
666
668
  end
669
+ end
670
+
671
+
667
672
  private # thor does something fancy like sending the class all of its own methods during some strange run sequence
668
673
  # does not like public methods
669
674
 
@@ -671,7 +676,6 @@ module HotGlue
671
676
  [name, file_format].compact.join(".")
672
677
  end
673
678
  end
674
-
675
679
  end
676
680
 
677
681
 
@@ -0,0 +1,14 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ console.log("defining Confirmable....")
4
+ export default class extends Controller {
5
+ static values = { message: String }
6
+
7
+ confirm(event) {
8
+
9
+ if(!window.confirm(this.message)) {
10
+ event.preventDefault();
11
+ event.stopPropagation()
12
+ }
13
+ }
14
+ }
@@ -1,6 +1,11 @@
1
1
  class <%= controller_class_name %> < <%= controller_descends_from %>
2
2
  <% unless @auth_identifier == '' || @auth.nil? %>before_action :authenticate_<%= @auth_identifier %>!<% end %>
3
3
 
4
+ <% if any_nested? %><% nest_chain = [] %> <% @nested_args.each { |arg|
5
+ this_scope = nest_chain.empty? ? "#{@auth ? auth_object : class_name}.#{arg}s" : "#{nest_chain.last}.#{arg}s"
6
+ nest_chain << arg %>
7
+ before_action :<%= arg %>
8
+ <% } %><% end %>
4
9
  before_action :load_<%= singular_name %>, only: [:show, :edit, :update, :destroy]
5
10
  helper :hot_glue
6
11
  include HotGlue::ControllerHelper
@@ -9,9 +14,16 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
9
14
  # TODO: implement current_user or use Devise
10
15
  <% end %>
11
16
 
17
+
18
+
12
19
  <% if any_nested? %><% nest_chain = [] %> <% @nested_args.each { |arg|
13
- this_scope = nest_chain.empty? ? "#{@auth ? auth_object : class_name}.#{arg}s" : "#{nest_chain.last}.#{arg}s"
14
- nest_chain << arg %>
20
+ if !@god
21
+ this_scope = nest_chain.empty? ? "#{@auth ? auth_object : class_name}.#{arg}s" : "#{nest_chain.last}.#{arg}s"
22
+ else
23
+ this_scope = eval(class_name + ".reflect_on_association(:#{arg})").class_name
24
+ end
25
+ nest_chain << arg
26
+ %>
15
27
  def <%= arg %>
16
28
  @<%= arg %> ||= <%= this_scope %>.find(params[:<%= arg %>_id])
17
29
  end<% } %><% end %>
@@ -56,7 +68,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
56
68
  load_all_<%= plural %>
57
69
  respond_to do |format|
58
70
  format.turbo_stream
59
- format.html { redirect_to <%= plural %>_path }
71
+ format.html { redirect_to <%= path_helper_plural %> }
60
72
  end
61
73
  else
62
74
  flash[:alert] = "Oops, your <%= singular_name %> could not be created."
@@ -101,7 +113,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
101
113
  load_all_<%= plural %>
102
114
  respond_to do |format|
103
115
  format.turbo_stream
104
- format.html { redirect_to <%= plural %>_path }
116
+ format.html { redirect_to <%= path_helper_plural %> }
105
117
  end
106
118
  end<% end %>
107
119
 
@@ -1,7 +1,7 @@
1
1
  <%= all_line_fields %>
2
2
  <div class="col">
3
3
  <% if destroy_action %>
4
- <\%= link_to "Delete <i class='fa fa-1x fa-remove'></i>".html_safe, <%= path_helper_singular %>(<%= path_helper_args %>), method: :delete, data: {confirm: 'Are you sure?'}, disable_with: "Loading...", class: "delete-<%= singular %>-button btn btn-primary " %>
4
+ <\%= button_to "Delete".html_safe, <%= path_helper_singular %>(<%= path_helper_args %>), method: :delete, data: <%= delete_confirmation_syntax %>, disable_with: "Loading...", class: "delete-<%= singular %>-button btn btn-primary " %>
5
5
  <% end %>
6
6
  &nbsp;
7
7
  <\%= link_to "Edit <i class='fa fa-1x fa-list-alt'></i>".html_safe, edit_<%= path_helper_singular %>(<%= path_helper_args %>), <% if @big_edit %>'data-turbo' => 'false', <% end %>disable_with: "Loading...", class: "edit-<%= singular %>-button btn btn-primary " %>
@@ -98,7 +98,7 @@ describe "interaction for <%= controller_class_name %>", type: :feature do
98
98
  visit <%= path_helper_plural %>
99
99
  find("a.edit-<%= singular %>-button[href='/<%= namespace_with_slash %><%= plural %>/#{<%= singular %>1.id}/edit']").click
100
100
 
101
- expect(page).to have_content("Editing #{<%= singular %>1.<%= derrive_reference_name(singular_class) %>}")
101
+ expect(page).to have_content("Editing #{<%= singular %>.<%= "abc" %>}")
102
102
  <%=
103
103
  @columns.map { |col|
104
104
  type = eval("#{singular_class}.columns_hash['#{col}']").type
@@ -1,3 +1,3 @@
1
1
  module HotGlue
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.4'
3
3
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot-glue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Fleetwood-Boldt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-06 00:00:00.000000000 Z
11
+ date: 2021-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.1'
20
+ - - "<="
18
21
  - !ruby/object:Gem::Version
19
- version: '6.0'
22
+ version: 7.0.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.1'
30
+ - - "<="
25
31
  - !ruby/object:Gem::Version
26
- version: '6.0'
32
+ version: 7.0.0
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: kaminari
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -96,13 +102,14 @@ dependencies:
96
102
  version: '2.16'
97
103
  description: Simple, plug & play Rails scaffold building companion for Turbo-Rails
98
104
  and Hotwire
99
- email: tech@datatravels.com
105
+ email: code@jasonfb.net
100
106
  executables: []
101
107
  extensions: []
102
108
  extra_rdoc_files: []
103
109
  files:
104
110
  - ".github/FUNDING.yml"
105
111
  - ".gitignore"
112
+ - ".travis.yml"
106
113
  - Gemfile
107
114
  - Gemfile.lock
108
115
  - LICENCE
@@ -127,6 +134,7 @@ files:
127
134
  - lib/generators/hot_glue/markup_templates/slim.rb
128
135
  - lib/generators/hot_glue/scaffold_generator.rb
129
136
  - lib/generators/hot_glue/templates/base_controller.rb.erb
137
+ - lib/generators/hot_glue/templates/confirmable.js
130
138
  - lib/generators/hot_glue/templates/controller.rb.erb
131
139
  - lib/generators/hot_glue/templates/erb/_errors.erb
132
140
  - lib/generators/hot_glue/templates/erb/_flash_notices.erb
@@ -162,7 +170,7 @@ files:
162
170
  - lib/hot-glue.rb
163
171
  - lib/hotglue/engine.rb
164
172
  - lib/hotglue/version.rb
165
- homepage: https://blog.jasonfleetwoodboldt.com/hot-glue/
173
+ homepage: https://jasonfleetwoodboldt.com/hot-glue/
166
174
  licenses:
167
175
  - Nonstandard
168
176
  metadata:
@@ -200,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
208
  - !ruby/object:Gem::Version
201
209
  version: '0'
202
210
  requirements: []
203
- rubygems_version: 3.0.9
211
+ rubygems_version: 3.1.4
204
212
  signing_key:
205
213
  specification_version: 4
206
214
  summary: A gem build scaffolding.