hot-glue 0.5.19.2 → 0.5.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +135 -17
- data/lib/generators/hot_glue/fields/association_field.rb +2 -2
- data/lib/generators/hot_glue/fields/date_time_field.rb +1 -1
- data/lib/generators/hot_glue/fields/field.rb +1 -1
- data/lib/generators/hot_glue/markup_templates/erb.rb +20 -15
- data/lib/generators/hot_glue/scaffold_generator.rb +28 -5
- data/lib/generators/hot_glue/templates/controller.rb.erb +45 -14
- data/lib/generators/hot_glue/templates/erb/_edit.erb +6 -7
- data/lib/generators/hot_glue/templates/system_spec.rb.erb +1 -1
- data/lib/hotglue/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34d4899a5495270c4364848ad5e61527141d1f2b869e3e55c24efb6c63865ac9
|
4
|
+
data.tar.gz: 1a97496b55af910b3c14ead50c92205e0e8ed7c6d75330050041a8e9c6aa4df7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9aea82f09683d50f8e4175777fff16ef07da0682055cbe3ee29f3da3360a2b8763cfc079afe15c69f3e05f3b4dd33d063b63aa483c5e32ad60c2ac20da305f65
|
7
|
+
data.tar.gz: e3ec284bdb6d2d7d1030502fc45858c55afaf82e97fda92fd0bcb7359a7f54315a360aacd9bfd7e23da56dff08541ed0f120f2bc071faab950990688b40fb2ea
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -75,15 +75,11 @@ For Hot Glue, you will need:
|
|
75
75
|
|
76
76
|
Section #1 is to create a new Rails app. (Or you can do that yourself.)
|
77
77
|
|
78
|
-
Section #2 is to setup Rspec, FactoryBot, and Faker
|
78
|
+
Section #2 is to setup Rspec, FactoryBot, and Faker — choose 2B for Rspec0
|
79
79
|
|
80
|
-
|
80
|
+
Skip #3 and #4 is optional. #5 is optional but recommended.
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
Section #6 is for two support gems (Kaminari) for Hot Glue
|
85
|
-
|
86
|
-
Section #7 is for Hot Glue itself
|
82
|
+
Sectoin #6 is for Hot Glue itself, and Section #7 is for Kaminari
|
87
83
|
|
88
84
|
You will also need section #8 to setup Devise if you want authentication.
|
89
85
|
|
@@ -645,15 +641,6 @@ This is what would happen if 9 fields, specified in the order A,B,C,D,E,F,G,H,I,
|
|
645
641
|
|
646
642
|
|
647
643
|
|
648
|
-
### `--show-only=`
|
649
|
-
(separate field names by COMMA)
|
650
|
-
|
651
|
-
Any fields only the 'show-only' list will appear as non-editable on the generated form for both new & edit actions. (visible only)
|
652
|
-
|
653
|
-
IMPORTANT: By default, all fields that begin with an underscore (`_`) are automatically show-only.
|
654
|
-
|
655
|
-
This is 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.
|
656
|
-
|
657
644
|
### `--modify=field1{...},field2{...}`
|
658
645
|
|
659
646
|
|
@@ -685,12 +672,92 @@ The available modifiers are:
|
|
685
672
|
| truthy label\|falsy label | specify a binary switch with a pipe (\|) character if the value is truthy, it will display as "truthy label" if the value is falsy, it will display as "falsy label" | boolean, datetime, date, time | | |
|
686
673
|
| | | | | |
|
687
674
|
|
675
|
+
### `--pundit`
|
676
|
+
If you enable Pundit, your controllers will look for a Policy that matches the name of the thing being built.
|
677
|
+
|
678
|
+
**Realtime Field-level Access**
|
679
|
+
Hot Glue gives you automatic field level access control if you create `*_able?` methods for each field you'd like to control on your Pundit policy.
|
680
|
+
|
681
|
+
(Although this is not what Pundit recommends for field level access control, it has been implemented this way to provide field-by-field user feedback to the user shown in red just like Rails validation errors are currently shown. This is is only hypothetical, because the interface correctly shows the field as viewable or editable anyway, making bad entry only something that could be achieved through a mistake or hacking. Nevertheless, rest assured that if there was a input mistake-- like a user having a field editable when it shouldn't be, the backend policy would guard against the disallowed input and show an error message.)
|
682
|
+
|
683
|
+
The `*_able?` method should return true or false depending on whether or not the field can be edited. (No distinction is made between the different contexts. You may check if the record is new using `new_record?`.
|
684
|
+
|
685
|
+
The `*_able?` method is used by Hot Glue only on the new and edit actions, but you should incorporate it into the policy's `update?` method as in the example, which will extend other operations since Hot Glue will use the policy to authorize the action
|
686
|
+
Add one `*_able?` method to the policy for each field you want to allow field-level access control.
|
687
|
+
|
688
|
+
Replace `*` with the name of the field you want under access control. Remember to include `_id` for foreign keys. You do not need it for any field you don't want under access control.
|
689
|
+
|
690
|
+
When the method returns true, the field will be displayed to the user (and allowed) for editing.
|
691
|
+
When the method returns false, the field will be displayed as read-only (viewable) to the user.
|
692
|
+
|
693
|
+
Important: These special fields determine *only* display behavior (new and edit), not create and update.
|
694
|
+
|
695
|
+
For create & update field-level access control, you must also implement the `update?` method on the Policy. Notice how in the example policy below, the `update?` method uses the `name_able?` method when it is checking if the name field can be updated, tying the feature together.
|
696
|
+
|
697
|
+
You can set Pundit to be enabled globally on the whole project for every build in `config/hot_glue.yml` (then you can leave off the `--pundit` flag from the scaffold command)
|
698
|
+
`:pundit_default:` (all builds in that project will use Pundit)
|
699
|
+
|
700
|
+
|
701
|
+
Here's an example `ThingPolicy` that would allow **editing the name field** only if:
|
702
|
+
• the current user is an admin
|
703
|
+
• the sent_at date is nil (meaning it has not been sent yet)
|
704
|
+
|
705
|
+
For your policies, copy the `initialize` method of both the outer class (`ThingPolicy`) and the inner class (`Scope`) exactly as shown below.
|
706
|
+
|
707
|
+
|
708
|
+
```
|
709
|
+
class ThingPolicy < ApplicationPolicy
|
710
|
+
def initialize(user, record)
|
711
|
+
@user = user
|
712
|
+
@record = record
|
713
|
+
end
|
714
|
+
|
715
|
+
def name_able?
|
716
|
+
@record.sent_at.nil?
|
717
|
+
end
|
718
|
+
|
719
|
+
def update?
|
720
|
+
if !@user.is_admin?
|
721
|
+
return false
|
722
|
+
elsif record.name_changed? && !name_able?
|
723
|
+
record.errors.add(:name, "cannot be changed.")
|
724
|
+
return false
|
725
|
+
else
|
726
|
+
return true
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
class Scope < Scope
|
731
|
+
attr_reader :user, :scope
|
732
|
+
def initialize(user, scope)
|
733
|
+
@user = user
|
734
|
+
@scope = scope
|
735
|
+
end
|
736
|
+
end
|
737
|
+
end
|
738
|
+
```
|
739
|
+
|
740
|
+
|
741
|
+
Because Hot Glue detects the `*_able?` methods at build time, if you add them to your policy, you will have to rebuild your scaffold.
|
742
|
+
|
743
|
+
|
744
|
+
### `--show-only=`
|
745
|
+
(separate field names by COMMA)
|
746
|
+
|
747
|
+
• Make this field appear as viewable only all actions. (visible only)
|
748
|
+
• When set on this list, it will override any Pundit policy even when Pundit would otherwise allow the access.
|
749
|
+
|
750
|
+
IMPORTANT: By default, all fields that begin with an underscore (`_`) are automatically show-only.
|
751
|
+
|
752
|
+
This is 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.
|
688
753
|
|
689
754
|
|
690
755
|
### `--update-show-only`
|
691
756
|
(separate field names by COMMA)
|
692
757
|
|
693
|
-
|
758
|
+
• Make this field appear as viewable only for the edit action (and not allowed in the update action).
|
759
|
+
• When set on this list, it will override any Pundit policy for edit/update actions even when Pundit would otherwise allow the access.
|
760
|
+
|
694
761
|
|
695
762
|
Note that Hot Glue still generates a singular partial (`_form`) for both actions, but your form will now contain statements like:
|
696
763
|
|
@@ -705,6 +772,35 @@ Note that Hot Glue still generates a singular partial (`_form`) for both actions
|
|
705
772
|
This works for both regular fields, association fields, and alt lookup fields.
|
706
773
|
|
707
774
|
|
775
|
+
When mixing the show only, update show only, and Pundit features, notice that the show only + update show only will act to override whatever the policy might say.
|
776
|
+
|
777
|
+
Remember, the show only list is specified using `--show-only` and the update show only list is specified using `--update-show-only`.
|
778
|
+
|
779
|
+
'Viewable' means it displays as view-only (not editable) even on the form. In this context, 'viewable' means 'read-only'. It does not mean 'visible'.
|
780
|
+
|
781
|
+
That's because when the field is **not viewable**, then it is editable or inputable. This may seem counter-intuitive for a standard interpretation of the word 'viewable,' but consider that Hot Glue has been carefully designed this way. If you do not want the field to appear at all, then you simply remove it using the exclude list or don't specify it in your include list. If the field is being built at all, Hot Glue assumes your users want to see or edit it. Other special cases are beyond the scope of Hot Glue but can easily be added using direct customization of the code.
|
782
|
+
|
783
|
+
Without Pundit:
|
784
|
+
| | on new screen | on edit screen |
|
785
|
+
|------------------------------------------|---------------|----------------|
|
786
|
+
| for a field on the show only list | viewable | viewable |
|
787
|
+
| for a field on the update show only list | inputable | viewable |
|
788
|
+
| for all other fields | inputable | inputable |
|
789
|
+
|
790
|
+
|
791
|
+
With Pundit:
|
792
|
+
| | on new screen | on edit screen |
|
793
|
+
|------------------------------------------|---------------|----------------|
|
794
|
+
| for a field on the show only list | viewable | viewable |
|
795
|
+
| for a field on the update show only list | check policy | viewable |
|
796
|
+
| for all other fields | check policy | check policy |
|
797
|
+
| | | |
|
798
|
+
|
799
|
+
Remember, if there's a corresponding `*_able?` method on the policy, it will be used to determine if the field is **editable** or not in the cases where 'check policy' is above.
|
800
|
+
(where `*` is the name of your field)
|
801
|
+
|
802
|
+
As shown in the method `name_able?` of the example ThingPolicy above, if this field on your policy returns true, the field will be editable. If it returns false, the field will be viewable (read-only).
|
803
|
+
|
708
804
|
|
709
805
|
### `--ujs_syntax=true` (Default is set automatically based on whether you have turbo-rails installed)
|
710
806
|
|
@@ -813,6 +909,14 @@ Omits new & create actions.
|
|
813
909
|
|
814
910
|
Omits delete button & destroy action.
|
815
911
|
|
912
|
+
### `--no-controller`
|
913
|
+
|
914
|
+
Omits controller.
|
915
|
+
|
916
|
+
### `--no-list`
|
917
|
+
|
918
|
+
Omits list views.
|
919
|
+
|
816
920
|
### `--big-edit`
|
817
921
|
|
818
922
|
If you do not want inline editing of your list items but instead want 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.
|
@@ -1300,6 +1404,20 @@ end
|
|
1300
1404
|
|
1301
1405
|
# VERSION HISTORY
|
1302
1406
|
|
1407
|
+
|
1408
|
+
#### 2023-09-18 - v0.5.21
|
1409
|
+
- Removes `@` symbols using instance variables in `_edit` partials and in the enum syntax
|
1410
|
+
- fixes in system_spec.rb.erb
|
1411
|
+
- Adds flags --no-controller --no-list
|
1412
|
+
- adds regen code to a file in the views folder REGENERATE.md if you have set --no-controller
|
1413
|
+
|
1414
|
+
|
1415
|
+
#### 2023-09-08 - v0.5.20
|
1416
|
+
`--pundit` authorization
|
1417
|
+
• Will look for a `XyzPolicy` class and method on your class named `*_able?` matching the fields on your object. See Pundit section for details.
|
1418
|
+
• Field-level access control (can determine which fields are editble or viewable based on the record or current user or combination factors)
|
1419
|
+
• The field-level access control doesn't show the fields as editable to the user if they can't be edited by the user (it shows them as view-only).
|
1420
|
+
|
1303
1421
|
#### 2023-09-02 - v0.5.19
|
1304
1422
|
|
1305
1423
|
Given a table generated with this schema:
|
@@ -104,7 +104,7 @@ class AssociationField < Field
|
|
104
104
|
end
|
105
105
|
|
106
106
|
(is_owner ? "<% unless @#{assoc_name} %>\n" : "") +
|
107
|
-
" <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, {prompt: true, selected:
|
107
|
+
" <%= f.collection_select(:#{name}, #{hawked_association}, :id, :#{display_column}, {prompt: true, selected: #{singular}.#{name} }, class: 'form-control') %>\n" +
|
108
108
|
(is_owner ? "<% else %>\n <%= @#{assoc_name}.#{display_column} %>" : "") +
|
109
109
|
(is_owner ? "\n<% end %>" : "")
|
110
110
|
end
|
@@ -116,7 +116,7 @@ class AssociationField < Field
|
|
116
116
|
|
117
117
|
def form_show_only_output
|
118
118
|
assoc_name = name.to_s.gsub("_id","")
|
119
|
-
assoc = eval("#{
|
119
|
+
assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
|
120
120
|
if assoc.nil?
|
121
121
|
exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
|
122
122
|
exit
|
@@ -115,7 +115,7 @@ class Field
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def modified_display_output
|
118
|
-
if
|
118
|
+
if modify[:cast] && modify[:cast] == "$"
|
119
119
|
"<%= number_to_currency(#{singular}.#{name}) %>"
|
120
120
|
elsif modify[:binary]
|
121
121
|
"<%= #{singular}.#{name} ? '#{modify[:binary][:truthy]}' : '#{modify[:binary][:falsy]}' %>"
|
@@ -8,7 +8,7 @@ module HotGlue
|
|
8
8
|
:inline_list_labels, :layout_object,
|
9
9
|
:columns, :col_identifier, :singular,
|
10
10
|
:form_placeholder_labels, :hawk_keys, :update_show_only,
|
11
|
-
:alt_lookups, :attachments, :show_only, :columns_map
|
11
|
+
:alt_lookups, :attachments, :show_only, :columns_map, :pundit
|
12
12
|
|
13
13
|
|
14
14
|
def initialize(singular:, singular_class: ,
|
@@ -17,7 +17,7 @@ module HotGlue
|
|
17
17
|
ownership_field: , form_labels_position: ,
|
18
18
|
inline_list_labels: ,
|
19
19
|
form_placeholder_labels:, hawk_keys: ,
|
20
|
-
update_show_only:, alt_lookups: , attachments: , columns_map: )
|
20
|
+
update_show_only:, alt_lookups: , attachments: , columns_map:, pundit: )
|
21
21
|
|
22
22
|
@singular = singular
|
23
23
|
@singular_class = singular_class
|
@@ -28,6 +28,7 @@ module HotGlue
|
|
28
28
|
@small_buttons = small_buttons
|
29
29
|
@layout_strategy = layout_strategy
|
30
30
|
@show_only = show_only
|
31
|
+
@pundit = pundit
|
31
32
|
@ownership_field = ownership_field
|
32
33
|
|
33
34
|
@form_labels_position = form_labels_position
|
@@ -81,30 +82,34 @@ module HotGlue
|
|
81
82
|
result = columns.map{ |column|
|
82
83
|
" <div class='#{column_classes} cell--#{singular}--#{column.join("-")}' >" +
|
83
84
|
column.map { |col|
|
84
|
-
field_result = show_only.include?(col.to_sym) ?
|
85
|
-
columns_map[col].form_show_only_output :
|
86
|
-
columns_map[col].form_field_output
|
87
85
|
|
88
86
|
field_error_name = columns_map[col].field_error_name
|
89
87
|
|
90
|
-
|
91
88
|
label_class = columns_map[col].label_class
|
92
89
|
label_for = columns_map[col].label_for
|
93
90
|
|
94
91
|
the_label = "\n<label class='#{label_class}' for='#{label_for}'>#{col.to_s.humanize}</label>"
|
95
|
-
show_only_open = ""
|
96
|
-
show_only_close = ""
|
97
92
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
93
|
+
|
94
|
+
field_result =
|
95
|
+
if show_only.include?(col)
|
96
|
+
columns_map[col].form_show_only_output
|
97
|
+
elsif update_show_only.include?(col) && !@pundit
|
98
|
+
"<% if action_name == 'edit' %>" + columns_map[col].form_show_only_output + "<% else %>" + columns_map[col].form_field_output + "<% end %>"
|
99
|
+
elsif update_show_only.include?(col) && @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
|
100
|
+
"<% if action_name == 'create' && policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_show_only_output + "<% else %>" + columns_map[col].form_field_output + "<% end %>"
|
101
|
+
|
102
|
+
# show only on the update action overrides any pundit policy
|
103
|
+
elsif @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
|
104
|
+
"<% if policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_field_output + "<% else %>" + columns_map[col].form_show_only_output + "<% end %>"
|
105
|
+
else
|
106
|
+
columns_map[col].form_field_output
|
107
|
+
end
|
103
108
|
|
104
109
|
add_spaces_each_line( "\n <span class='<%= \"alert-danger\" if #{singular}.errors.details.keys.include?(:#{field_error_name}) %>' #{'style="display: inherit;"'} >\n" +
|
105
110
|
add_spaces_each_line( (form_labels_position == 'before' ? the_label : "") +
|
106
|
-
|
107
|
-
|
111
|
+
+ field_result +
|
112
|
+
(form_labels_position == 'after' ? the_label : "") , 4) +
|
108
113
|
"\n </span>\n <br />", 2)
|
109
114
|
|
110
115
|
}.join("") + "\n </div>"
|
@@ -21,7 +21,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
21
21
|
:display_as, :downnest_children, :downnest_object, :hawk_keys, :layout_object, :modify,
|
22
22
|
:nest_with, :path, :plural, :sample_file_path, :show_only_data, :singular,
|
23
23
|
:singular_class, :smart_layout, :stacked_downnesting, :update_show_only, :ownership_field,
|
24
|
-
:layout_strategy, :form_placeholder_labels, :form_labels_position
|
24
|
+
:layout_strategy, :form_placeholder_labels, :form_labels_position, :pundit
|
25
25
|
|
26
26
|
class_option :singular, type: :string, default: nil
|
27
27
|
class_option :plural, type: :string, default: nil
|
@@ -43,6 +43,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
43
43
|
class_option :no_create, type: :boolean, default: false
|
44
44
|
class_option :no_edit, type: :boolean, default: false
|
45
45
|
class_option :no_list, type: :boolean, default: false
|
46
|
+
class_option :no_controller, type: :boolean, default: false
|
47
|
+
class_option :no_list, type: :boolean, default: false
|
46
48
|
class_option :no_paginate, type: :boolean, default: false
|
47
49
|
class_option :big_edit, type: :boolean, default: false
|
48
50
|
class_option :show_only, type: :string, default: ""
|
@@ -81,6 +83,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
81
83
|
class_option :button_icons, default: nil
|
82
84
|
class_option :modify, default: {}
|
83
85
|
class_option :display_as, default: {}
|
86
|
+
class_option :pundit, default: nil
|
84
87
|
|
85
88
|
def initialize(*meta_args)
|
86
89
|
super
|
@@ -288,6 +291,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
288
291
|
|
289
292
|
@no_edit = options['no_edit'] || false
|
290
293
|
@no_list = options['no_list'] || false
|
294
|
+
@no_controller = options['no_controller'] || false
|
295
|
+
@no_list = options['no_list'] || false
|
291
296
|
@no_list_label = options['no_list_label'] || false
|
292
297
|
@no_list_heading = options['no_list_heading'] || false
|
293
298
|
@stacked_downnesting = options['stacked_downnesting']
|
@@ -295,6 +300,12 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
295
300
|
@display_list_after_update = options['display_list_after_update'] || false
|
296
301
|
@smart_layout = options['smart_layout']
|
297
302
|
|
303
|
+
@pundit = options['pundit']
|
304
|
+
if @pundit.nil?
|
305
|
+
@pundit = get_default_from_config(key: :pundit_default)
|
306
|
+
end
|
307
|
+
|
308
|
+
|
298
309
|
if options['include'].include?(":") && @smart_layout
|
299
310
|
raise HotGlue::Error, "You specified both --smart-layout and also specified grouping mode (there is a : character in your field include list); you must remove the colon(s) from your --include tag or remove the --smart-layout option"
|
300
311
|
end
|
@@ -443,7 +454,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
443
454
|
form_placeholder_labels: @form_placeholder_labels,
|
444
455
|
alt_lookups: @alt_lookups,
|
445
456
|
attachments: @attachments,
|
446
|
-
columns_map: @columns_map
|
457
|
+
columns_map: @columns_map,
|
458
|
+
pundit: @pundit,
|
447
459
|
)
|
448
460
|
elsif @markup == "slim"
|
449
461
|
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
@@ -680,7 +692,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
680
692
|
|
681
693
|
def copy_controller_and_spec_files
|
682
694
|
@default_colspan = @columns.size
|
683
|
-
unless @specs_only
|
695
|
+
unless @specs_only || @no_controller
|
684
696
|
template "controller.rb.erb", File.join("#{filepath_prefix}app/controllers#{namespace_with_dash}", "#{@controller_build_folder}_controller.rb")
|
685
697
|
if @namespace
|
686
698
|
begin
|
@@ -806,7 +818,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
806
818
|
show_only_list = which_partial == :create ? @show_only : (@update_show_only + @show_only)
|
807
819
|
|
808
820
|
if show_only_list.include?(col)
|
809
|
-
|
821
|
+
# TODO: decide if this should get re-implemeneted
|
822
|
+
# " page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
|
810
823
|
else
|
811
824
|
col_obj.spec_setup_and_change_act(which_partial)
|
812
825
|
end
|
@@ -857,7 +870,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
857
870
|
nested_set: @nested_set,
|
858
871
|
with_params: true,
|
859
872
|
put_form: true,
|
860
|
-
top_level:
|
873
|
+
top_level: false)
|
861
874
|
end
|
862
875
|
|
863
876
|
def delete_path_helper
|
@@ -1012,6 +1025,11 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1012
1025
|
|
1013
1026
|
def copy_view_files
|
1014
1027
|
return if @specs_only
|
1028
|
+
|
1029
|
+
if @no_controller
|
1030
|
+
File.write("#{Rails.root}/app/views/#{namespace_with_trailing_dash}/#{plural}/REGENERATE.md", regenerate_me_code)
|
1031
|
+
end
|
1032
|
+
|
1015
1033
|
all_views.each do |view|
|
1016
1034
|
formats.each do |format|
|
1017
1035
|
source_filename = cc_filename_with_extensions("#{@markup}/#{view}", "#{@markup}")
|
@@ -1111,6 +1129,11 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
1111
1129
|
if !(@no_edit && @no_create)
|
1112
1130
|
res << '_form'
|
1113
1131
|
end
|
1132
|
+
|
1133
|
+
if @no_list
|
1134
|
+
res -= %w{_list _line index}
|
1135
|
+
end
|
1136
|
+
|
1114
1137
|
res
|
1115
1138
|
end
|
1116
1139
|
|
@@ -65,21 +65,29 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
65
65
|
@<%= singular_name %> = (<%= auth_object.gsub("@",'') %><%= " if params.include?(:#{@nested_set[0][:singular]}_id)" if @nested_set.any? && @nested_set[0][:optional] %>)<% if @nested_set.any? && @nested_set[0][:optional] %> || <%= class_name %>.find(params[:id])<% end %>
|
66
66
|
end<% end %>
|
67
67
|
|
68
|
-
def load_all_<%= plural %><% if
|
68
|
+
def load_all_<%= plural %><% if @pundit %>
|
69
|
+
@<%= plural_name %> = policy_scope(<%= class_name %>).page(params[:page])<%= n_plus_one_includes %>
|
70
|
+
authorize @<%= plural_name %>.all<% else %> <% if !@self_auth %>
|
69
71
|
@<%= plural_name %> = <%= object_scope.gsub("@",'') %>.page(params[:page])<%= n_plus_one_includes %><%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set.any? && @nested_set[0] && @nested_set[0][:optional] %><% if @nested_set[0] && @nested_set[0][:optional] %>
|
70
72
|
@<%= plural_name %> = <%= class_name %>.all<% end %><% else %>
|
71
|
-
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes
|
73
|
+
@<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %><% end %>
|
74
|
+
<% end %>
|
72
75
|
end
|
73
76
|
|
74
77
|
def index
|
75
|
-
load_all_<%= plural %>
|
78
|
+
load_all_<%= plural %><% if @pundit %>
|
79
|
+
rescue Pundit::NotAuthorizedError
|
80
|
+
flash[:alert] = "You are not authorized to perform this action."<% end %>
|
76
81
|
end
|
77
82
|
|
78
83
|
<% if create_action %> def new<% if @object_owner_sym %>
|
79
|
-
@<%= singular_name %> =
|
80
|
-
@<%= singular_name %> =
|
81
|
-
@<%= singular_name %> =
|
82
|
-
|
84
|
+
@<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new(<% if eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% elsif @object_owner_optional && any_nested? %>
|
85
|
+
@<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new({}.merge(<%= @nested_set.last[:singular] %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}))<% else %>
|
86
|
+
@<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new(<% if any_nested? %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% end %>
|
87
|
+
<% if @pundit %>authorize @<%= singular_name %><% end %><% if @pundit %>
|
88
|
+
rescue Pundit::NotAuthorizedError
|
89
|
+
flash[:alert] = "You are not authorized to perform this action."
|
90
|
+
render :index<% end %>
|
83
91
|
end
|
84
92
|
|
85
93
|
def create
|
@@ -106,12 +114,18 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
106
114
|
else
|
107
115
|
flash[:alert] = "Oops, your <%= singular_name %> could not be created. #{@hawk_alarm}"
|
108
116
|
render :create, status: :unprocessable_entity
|
109
|
-
end
|
117
|
+
end<% if @pundit %>
|
118
|
+
rescue Pundit::NotAuthorizedError
|
119
|
+
flash[:alert] = "Creating <%= singular %> not authorized. #{@<%= singular %>.errors.collect{|k| "#{k.attribute} #{k.message}"}.join(" ")} #{flash[:notice]} "
|
120
|
+
render :index <% end %>
|
110
121
|
end
|
111
122
|
|
112
123
|
<% end %>
|
113
124
|
<% unless @no_edit %> def edit
|
114
|
-
render :edit
|
125
|
+
render :edit<% if @pundit %>
|
126
|
+
rescue Pundit::NotAuthorizedError
|
127
|
+
flash[:alert] = "Editing #{@<%= singular %>.<%= display_class %>} not authorized."
|
128
|
+
render :index <% end %>
|
115
129
|
end
|
116
130
|
|
117
131
|
<% end %><% if @build_update_action %> def update
|
@@ -120,7 +134,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
120
134
|
}.join("\n") %><% end %> <% merge_lookups = @alt_lookups.filter{|key,d| ! @update_show_only.include?(key.to_sym) }.collect{|key, data| "#{key.gsub("_id", "")}: #{key.gsub("_id", "")}" }.join(",") %>
|
121
135
|
<% @magic_buttons.each { |button| %>@<%= singular_name %>.<%= button %>! if <%= singular_name %>_params[:__<%= button %>]
|
122
136
|
<% } %>
|
123
|
-
modified_params = modify_date_inputs_on_params(
|
137
|
+
modified_params = modify_date_inputs_on_params(<% if @update_show_only %>update_<% end %><%= singular_name %>_params.dup<%= controller_update_params_tap_away_alt_lookups %>, <%= current_user_object %>, <%= datetime_fields_list %>) <% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
|
124
138
|
modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
|
125
139
|
modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% elsif !@object_owner_eval.empty? %>
|
126
140
|
modified_params = modified_params.merge(<%= @object_owner_eval %>) <% end %><% if !merge_lookups.empty? %>
|
@@ -136,7 +150,13 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
136
150
|
<%= @update_alt_lookups.collect{|key, data|
|
137
151
|
" @#{ singular_name }.#{key.gsub("_id", "")} = #{key.gsub("_id", "")}"
|
138
152
|
}.join("/n") %><% end %><%= controller_attachment_orig_filename_pickup_syntax %>
|
153
|
+
<% if @pundit %>
|
154
|
+
if @<%= singular_name %>.attributes = modified_params
|
155
|
+
authorize @<%= singular_name %>
|
156
|
+
@<%= singular_name %>.save
|
157
|
+
<% else %>
|
139
158
|
if @<%= singular_name %>.update(modified_params)
|
159
|
+
<% end %>
|
140
160
|
<% if @display_list_after_update %> load_all_<%= plural %><% end %>
|
141
161
|
flash[:notice] = "#{flash[:notice]} Saved #{@<%= singular %>.<%= display_class %>}"
|
142
162
|
flash[:alert] = @hawk_alarm if @hawk_alarm
|
@@ -144,22 +164,33 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
144
164
|
else
|
145
165
|
flash[:alert] = "#{flash[:notice]} <%= singular_name.titlecase %> could not be saved. #{@hawk_alarm}"
|
146
166
|
render :update, status: :unprocessable_entity
|
147
|
-
end
|
167
|
+
end<% if @pundit %>
|
168
|
+
rescue Pundit::NotAuthorizedError
|
169
|
+
flash[:alert] = "Updating #{@<%= singular_name %>.<%= display_class %>} not authorized. "
|
170
|
+
render :update<% end %>
|
148
171
|
end
|
149
172
|
|
150
173
|
<% end %><% if destroy_action %> def destroy
|
174
|
+
<% if @pundit %>authorize @<%= singular_name %><% end %>
|
151
175
|
begin
|
152
176
|
@<%=singular_name%>.destroy
|
153
177
|
flash[:notice] = '<%= singular_name.titlecase %> successfully deleted'
|
154
178
|
rescue StandardError => e
|
155
179
|
flash[:alert] = '<%= singular_name.titlecase %> could not be deleted'
|
156
180
|
end <%= post_action_parental_updates %>
|
157
|
-
load_all_<%= plural %>
|
181
|
+
load_all_<%= plural %><% if @pundit %>
|
182
|
+
rescue Pundit::NotAuthorizedError
|
183
|
+
flash[:alert] = "Deleting #{@<%= singular_name %>.<%= display_class %>} not authorized. "
|
184
|
+
render :update<% end %>
|
158
185
|
end<% end %>
|
159
186
|
|
160
187
|
def <%=singular_name%>_params
|
161
|
-
params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @show_only) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
|
162
|
-
end
|
188
|
+
params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @show_only ) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
|
189
|
+
end<% if @update_show_only %>
|
190
|
+
|
191
|
+
def update_<%=singular_name%>_params
|
192
|
+
params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @update_show_only) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
|
193
|
+
end<% end %>
|
163
194
|
|
164
195
|
def namespace
|
165
196
|
<% if @namespace %>'<%= @namespace %>/'<% else %><% end %>
|
@@ -1,12 +1,11 @@
|
|
1
|
-
<\%= turbo_frame_tag "<%= @namespace %>__#{dom_id(
|
1
|
+
<\%= turbo_frame_tag "<%= @namespace %>__#{dom_id(<%= singular %>)}" do %>
|
2
2
|
<div class="cell editable" style="position: relative;">
|
3
|
-
<\% if
|
4
|
-
<\%= render(partial: "<%= namespace_with_trailing_dash %>errors", locals: {resource:
|
3
|
+
<\% if <%= singular %>.errors.any? %>
|
4
|
+
<\%= render(partial: "<%= namespace_with_trailing_dash %>errors", locals: {resource: <%= singular %> }) %>
|
5
5
|
<\% end %>
|
6
|
-
|
7
|
-
|
8
|
-
<\%=
|
9
|
-
<\%= render partial: "<%= namespace_with_trailing_dash + @controller_build_folder + "/" %>form", locals: {:<%= singular %> => <%= "@" + singular%>, f: f}<%= @nested_set.collect{|arg| ".merge(@#{arg[:singular]} ? {#{arg[:singular]}: @#{arg[:singular]}} : {})" }.join %> \%>
|
6
|
+
<h2>Editing <\%= <%= singular %>.<%= display_class %> %></h2>
|
7
|
+
<\%= form_with model: <%= singular %>, url: <%= form_path_edit_helper %> do |f| %>
|
8
|
+
<\%= render partial: "<%= namespace_with_trailing_dash + @controller_build_folder + "/" %>form", locals: {:<%= singular %> => <%= singular %>, f: f}<%= @nested_set.collect{|arg| ".merge(#{arg[:singular]} ? {#{arg[:singular]}: #{arg[:singular]}} : {})" }.join %> \%>
|
10
9
|
<\% end %>
|
11
10
|
</div>
|
12
11
|
<\% end %>
|
@@ -15,7 +15,7 @@ describe 'interaction for <%= controller_class_name %>' do
|
|
15
15
|
<% unless @god %>let(:<%= @auth %>) {create(:<%= @auth.gsub('current_', '') %>)}<% end %>
|
16
16
|
<%= spec_related_column_lets %>
|
17
17
|
let!(:<%= singular %>1) {create(:<%= singular %><%= object_parent_mapping_as_argument_for_specs %> <%= item1_addOns %> )}
|
18
|
-
<%= objest_nest_factory_setup %> <% unless @god || @existing_content.include?("login_as")%>
|
18
|
+
<%= objest_nest_factory_setup %> <% unless @god || (@existing_content && @existing_content.include?("login_as")) %>
|
19
19
|
before do
|
20
20
|
login_as(<%= @auth %>)
|
21
21
|
end <% end %> <% if any_datetime_fields? %>
|
data/lib/hotglue/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hot-glue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.21
|
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: 2023-09-
|
11
|
+
date: 2023-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|