hot-glue 0.6.28 → 0.6.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -14
- data/README.md +92 -10
- data/lib/generators/hot_glue/fields/association_field.rb +1 -1
- data/lib/generators/hot_glue/fields/attachment_field.rb +11 -2
- data/lib/generators/hot_glue/layout_strategy/bootstrap.rb +0 -1
- data/lib/generators/hot_glue/markup_templates/erb.rb +15 -3
- data/lib/generators/hot_glue/scaffold_generator.rb +59 -16
- data/lib/generators/hot_glue/templates/controller.rb.erb +8 -7
- data/lib/hot-glue.rb +0 -2
- data/lib/hotglue/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7eb77747230d52128ce322520c8c208c5e235cb27cca4042c99a0ce0e910382b
|
|
4
|
+
data.tar.gz: 9ba630157d1335f28acb15c7342f2d3489e63358ad38fd4d19185162fceb6895
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 990d8138a2916b7599ea831b8c2d09d70b5df653a0ec8b2f88632eae696c21ecd24406ec1d0b8ea180ffdc2fe1401a2030672d6e7c5695693e2c86d1222a01e5
|
|
7
|
+
data.tar.gz: c396428e8d84b06fe05483add1a9d89ea7149e303efef49d14cccafe3ce25312440b8620db4a5d79fe0bd9e4876b71e98bbac895a540a24cdd7f1b752afb2711
|
data/Gemfile.lock
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
hot-glue (0.6.
|
|
4
|
+
hot-glue (0.6.29)
|
|
5
5
|
ffaker (~> 2.16)
|
|
6
|
-
kaminari (~> 1.2)
|
|
7
6
|
rails (> 5.1)
|
|
8
7
|
|
|
9
8
|
GEM
|
|
@@ -114,18 +113,6 @@ GEM
|
|
|
114
113
|
importmap-rails (1.1.5)
|
|
115
114
|
actionpack (>= 6.0.0)
|
|
116
115
|
railties (>= 6.0.0)
|
|
117
|
-
kaminari (1.2.2)
|
|
118
|
-
activesupport (>= 4.1.0)
|
|
119
|
-
kaminari-actionview (= 1.2.2)
|
|
120
|
-
kaminari-activerecord (= 1.2.2)
|
|
121
|
-
kaminari-core (= 1.2.2)
|
|
122
|
-
kaminari-actionview (1.2.2)
|
|
123
|
-
actionview
|
|
124
|
-
kaminari-core (= 1.2.2)
|
|
125
|
-
kaminari-activerecord (1.2.2)
|
|
126
|
-
activerecord
|
|
127
|
-
kaminari-core (= 1.2.2)
|
|
128
|
-
kaminari-core (1.2.2)
|
|
129
116
|
loofah (2.19.0)
|
|
130
117
|
crass (~> 1.0.2)
|
|
131
118
|
nokogiri (>= 1.5.9)
|
data/README.md
CHANGED
|
@@ -558,22 +558,24 @@ The child object is named `Rule` but it can belong to a Blast or an Agent. (Agen
|
|
|
558
558
|
|
|
559
559
|
We build the blast & agent controllers like so:
|
|
560
560
|
|
|
561
|
-
|
|
562
|
-
bin/rails generate hot_glue:scaffold
|
|
561
|
+
|
|
562
|
+
`bin/rails generate hot_glue:scaffold Blast --downnest='blast_rules(rules)'`
|
|
563
|
+
|
|
564
|
+
`bin/rails generate hot_glue:scaffold Agent --downnest='agent_rules(rules)'`
|
|
563
565
|
|
|
564
566
|
Notice that the relationship name is `rules` (not blast_rules), so what goes before the parenthesis is the controller name (with prefix)
|
|
565
567
|
What goes inside the controller name is the real relationship name.
|
|
566
568
|
|
|
567
569
|
For the children, we can't build one controller for the Rule, instead we build one for the `AgentRules` and another for the `BlastRules`
|
|
568
570
|
|
|
569
|
-
bin/rails generate hot_glue:scaffold Rule --nested='blast(ruleable)' --controller-prefix='Blast'
|
|
570
|
-
bin/rails generate hot_glue:scaffold Rule --nested='agent(ruleable)' --controller-prefix='Agent'
|
|
571
|
+
`bin/rails generate hot_glue:scaffold Rule --nested='blast(ruleable)' --controller-prefix='Blast'`
|
|
572
|
+
`bin/rails generate hot_glue:scaffold Rule --nested='agent(ruleable)' --controller-prefix='Agent'`
|
|
571
573
|
|
|
572
574
|
(I realize building one child controller for each type of polymorph is tedius, but this is the best solution I could come up with.)
|
|
573
575
|
|
|
574
576
|
As these are children, what goes into the `--netsed` setting inside the parentheses is the polymorphic name specified by `as:` when declaring the `belongs_to`
|
|
575
577
|
|
|
576
|
-
routes.rb
|
|
578
|
+
config/routes.rb
|
|
577
579
|
|
|
578
580
|
```
|
|
579
581
|
resources :agents do
|
|
@@ -585,6 +587,22 @@ routes.rb
|
|
|
585
587
|
end
|
|
586
588
|
```
|
|
587
589
|
|
|
590
|
+
Outside a polymorphic relationship, you sometimes have children with `belongs_to` that uses a custom name instead of the name of the class (using class_name on the belongs to)
|
|
591
|
+
|
|
592
|
+
Imagine a `followings` table with two foreign keys: follower_id and follows_id (both pointing to a BskyUser)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
`belongs_to :follower, class_name: "BskyUser", foreign_key: :follower_id`
|
|
596
|
+
`belongs_to :follows, class_name: "BskyUser", foreign_key: :follows_id`
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
Here, specify nested using square braces for the non-standard parent name
|
|
600
|
+
|
|
601
|
+
`--nested='bsky_users[follower]'` and `--nested='bsky_users[follows]'`
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
|
|
588
606
|
### `--stacked-downnesting`
|
|
589
607
|
|
|
590
608
|
This puts the downnested portals on top of one another (stacked top to bottom) instead of side-by-side (left to right). This is useful if you have a lot of downnested portals and you want to keep the page from getting too wide.
|
|
@@ -1658,12 +1676,17 @@ bin/rails generate Book --include=name,author_id --search=set --search-fields=na
|
|
|
1658
1676
|
```
|
|
1659
1677
|
|
|
1660
1678
|
### `--phantom-search='{type}_{name}[All|choice A:scope_a|choice B:scope_b]`
|
|
1679
|
+
`--phantom-search='radio_{name}[All|choice A:scope_a|choice B:scope_b]`
|
|
1680
|
+
`--phantom-search='checkboxes_{name}[All|choice A:off_scope_a:on_scope_a|choice B:off_scope_b:on_scope_b]`
|
|
1681
|
+
|
|
1661
1682
|
|
|
1662
1683
|
A phantom search is a search we are doing on this result set that doesn't correspond to a single field. Currently, the only available implementation is for scopes with no arguments, as in the example below. It is called 'phantom' because it could be (probably is) querying fields within the scope, but the search doesn't match up with a single field on your model. (So it's like creating 'phantom' criteria.). Only RADIO type is implemented, dropdown & checkboxes an a way to input a search value passed into the scope as an argument is TBD.
|
|
1663
1684
|
|
|
1664
|
-
{type} is any of: radio,
|
|
1685
|
+
{type} is any of: radio, checkboxes (showing one of each type above)
|
|
1665
1686
|
|
|
1666
|
-
{name} is a designation for this phantom search.
|
|
1687
|
+
{name} is a designation for this phantom search.
|
|
1688
|
+
Should NOT match any field name on your table.
|
|
1689
|
+
This should describe the kind of categorization we are performing. Name is used for radio only; not shown to the user for checkboxes
|
|
1667
1690
|
|
|
1668
1691
|
Your phantom search selector will be appended to the search fields and will be treated like a first-class search input, able to be combined with any of the other fields specified in a set search.
|
|
1669
1692
|
|
|
@@ -1676,9 +1699,14 @@ After the type & name, comes a block marked by square braces [ ... ]
|
|
|
1676
1699
|
|
|
1677
1700
|
Within the square braces, each search option is separated by a pipe (|) character.
|
|
1678
1701
|
|
|
1679
|
-
Within each option is a label and ruby scope, separated by a colon (:).
|
|
1702
|
+
Within each option is a label and either one ruby scope (for radios) or an OFF scope and ON scope (for checkboxes), separated by a colon (:).
|
|
1680
1703
|
|
|
1681
|
-
The label comes before the colon the ruby scope.
|
|
1704
|
+
The label comes before the first colon the ruby scope. For checkboxes, you will have two colons followed by an "off" and "on scope'
|
|
1705
|
+
label:off scope:on scope
|
|
1706
|
+
|
|
1707
|
+
The ruby scope can be specified with or without a dot.
|
|
1708
|
+
|
|
1709
|
+
Each ruby scope must be defined on your model. If there is no scope specified (empty), we assume "all", but we still need to specify a label for "All", which is why in the example above "All" has no colon after it.
|
|
1682
1710
|
|
|
1683
1711
|
#### Radio Example
|
|
1684
1712
|
|
|
@@ -2151,7 +2179,29 @@ This means that to find users within the search, the essential piece of informat
|
|
|
2151
2179
|
end
|
|
2152
2180
|
```
|
|
2153
2181
|
|
|
2182
|
+
If you want your typeahead to accept an input for a non-matched field, you need to use a factory (see `--factory-creation`)
|
|
2183
|
+
|
|
2184
|
+
Here, we assume that Authors are nested within a library (an arbitrary abstraction to demonstrate a typeahead at a nested route)
|
|
2185
|
+
|
|
2186
|
+
```
|
|
2187
|
+
factory = AuthorsFactory.new(
|
|
2188
|
+
library: library,
|
|
2189
|
+
query: params[:authors_query],
|
|
2190
|
+
author_params: modified_params)
|
|
2191
|
+
```
|
|
2192
|
+
|
|
2193
|
+
Your authors factory will need to check the params for `author_params[:author_id].empty?`
|
|
2194
|
+
|
|
2154
2195
|
|
|
2196
|
+
When the factory is passed an empty string here, it is from a non-matched lookup. You will either lookup the author_id if provided, or create a new one if not
|
|
2197
|
+
```
|
|
2198
|
+
if !author_params[:author_id].empty?
|
|
2199
|
+
author = Author.find(author_params[:author_id])
|
|
2200
|
+
else
|
|
2201
|
+
author = Target.find_or_create_by!(library: library, name: query)
|
|
2202
|
+
end
|
|
2203
|
+
```
|
|
2204
|
+
Notice this is creating a new author by the `name` field, which should be same field you are searching by in the typeahead.
|
|
2155
2205
|
|
|
2156
2206
|
--
|
|
2157
2207
|
|
|
@@ -2234,7 +2284,39 @@ These automatic pickups for partials are detected at build time. This means that
|
|
|
2234
2284
|
|
|
2235
2285
|
# VERSION HISTORY
|
|
2236
2286
|
|
|
2237
|
-
#### 2025-
|
|
2287
|
+
#### 2025-10-19 - v0.6.30
|
|
2288
|
+
- fixes references from search typeaheads to a typeahead controller which is nested
|
|
2289
|
+
- `--nested` can now take square braces if the relationship from child to parent (belongs_to) uses a non-standard association name; @downnest_object fix for data array; changes to object_scope to accomodate new paradigm
|
|
2290
|
+
|
|
2291
|
+
|
|
2292
|
+
|
|
2293
|
+
#### 2025-10-11 - v0.6.29
|
|
2294
|
+
|
|
2295
|
+
• When specifying a alt lookup in non-Gd mode, we treat this a security concern because alt lookups can get any related record from the database; if you use a factory when creating your object, you can pass the lookup to the factory and scope your lookup in there; fix to not raise exception when specified an alt lookup in non-Gd mode if you are also using a factory
|
|
2296
|
+
|
|
2297
|
+
• Attachments now have a graceful fail if the attachment is invariable (cannot be made into a thumbnail), and so there is no thumbnail to display. Instead, a small box with the file type ("pdf" or "msword") is shown in place where the thumbnail would display
|
|
2298
|
+
|
|
2299
|
+
• Adds a 'triple' implementation for newer pagination gems: will_paginate and pagy. HG will auto detect which pagination gem you have in your Gemfile, and pick ONE of the three based on this preference order: Pagy over will_paginate; will_paginate over Kaminari, no pagination if none of the three are installed.
|
|
2300
|
+
|
|
2301
|
+
Kaminari is barely workable with newer Rails and seems somewhat abandoned; will_paginate is officially in maintenance mode, so Pagy is the way to go. I have implemented all three for the widest legacy support. On my Rails Cookbook pages, I have replaced Kaminari with Pagy.
|
|
2302
|
+
|
|
2303
|
+
Migrating a large app from Kaminari to Pagy:
|
|
2304
|
+
|
|
2305
|
+
- If you rip out Kaminari right away, it will be necessary to rebuild all of your Hot Glue controllers & views. On a large or customized app, this will be too tedious to do at once. Instead, contrary to the Pagy documentation, which encourages you to aggressively rip out the old gem (Kaminari), you can leave both gems in place, operating side-by-side. As you rebuild each scaffold controller by controller, newly built scaffolds will use Pagy, replacing the older Kaminari syntax.
|
|
2306
|
+
|
|
2307
|
+
• Hot Glue is now _OFFICIALLY dependency-free_! I've been building and working with Rails gems for years and years, and one of the interesting challenges that Rails 7 & 8 posed is that when the JavaScript and CSS delivery paradigms shift, it caused a massive atrophy of several old Rails gems. Codebases that relied on, for example, the old jquery-rails gem suddenly found themselves pantless. JS tool-only Gems are now discouraged, in favor of importmaps, propshaft, or JSBundling.
|
|
2308
|
+
|
|
2309
|
+
When you build a gem, the naive gem builder thinks to themselves: Let me pull in other people's tools to make my tool stand on the shoulders of giants.
|
|
2310
|
+
|
|
2311
|
+
But when paradigms shift, those gems the gem depends on become a blocker for your Gem moving forward.
|
|
2312
|
+
|
|
2313
|
+
I already had very few dependencies in Hot Glue — really just Rspec, Kaminari, and Rails itself. Although you need Turbo (and by extension JS), bootstrap is optional (but recommended), and Rspec is optional (but default).
|
|
2314
|
+
|
|
2315
|
+
The ONLY remaining dependency is ffaker (sorry!), which is necessary for the specs.
|
|
2316
|
+
|
|
2317
|
+
Hot Glue is a companion tool to Turbo itself. Where Turbo Rails goes, we go. Although this gem is primarily built for Bootstrap, Bootstrap remains officially optional. Although you need Turbo for it to work, how you bring Turbo is up to you (bundling, pinning, propshafting, etc). With the removal of Kaminari and new support for will_paginate and Pagy, I hope this Gem can be integrated into more apps who may already have chosen their pagination system.
|
|
2318
|
+
|
|
2319
|
+
#### 2025-09-26 - v0.6.28
|
|
2238
2320
|
- Checkboxes option for Phantom Search (previously phantom searches only supported radio).
|
|
2239
2321
|
See "Checkboxes example" under the docs for `--phantom-search` above
|
|
2240
2322
|
|
|
@@ -204,7 +204,7 @@ class AssociationField < Field
|
|
|
204
204
|
assoc_name = name.to_s.gsub("_id","")
|
|
205
205
|
assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
|
|
206
206
|
if modify_as && modify_as[:typeahead]
|
|
207
|
-
search_url = "#{namespace ? namespace + "_" : ""}#{assoc.class_name.downcase.pluralize}_typeahead_index_url"
|
|
207
|
+
search_url = "#{namespace ? namespace + "_" : ""}#{modify_as[:nested] ? modify_as[:nested][0] + "_" : ""}#{assoc.class_name.downcase.pluralize}_typeahead_index_url"
|
|
208
208
|
|
|
209
209
|
# \"q[0][#{name}_search]\"
|
|
210
210
|
# @q['0']['#{name}_search']
|
|
@@ -42,7 +42,16 @@ def spec_setup_and_change_act(which_partial = nil)
|
|
|
42
42
|
|
|
43
43
|
def line_field_output
|
|
44
44
|
thumbnail = attachment_data[:thumbnail]
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
if thumbnail
|
|
46
|
+
"<% if #{singular}.#{name}.attached? %>
|
|
47
|
+
<% if !#{singular}.#{name}.variable? %>
|
|
48
|
+
<span class=\"badge bg-secondary\"><%= #{singular}.#{name}.blob.content_type.split('/')[1] %></span>
|
|
49
|
+
<% else %>
|
|
50
|
+
<%= image_tag(#{singular}.#{name}.variant(:thumb)) %>
|
|
51
|
+
<% end %>
|
|
52
|
+
<% end %>"
|
|
53
|
+
else
|
|
54
|
+
""
|
|
55
|
+
end
|
|
47
56
|
end
|
|
48
57
|
end
|
|
@@ -12,7 +12,7 @@ module HotGlue
|
|
|
12
12
|
:search, :search_fields, :search_query_fields, :search_position,
|
|
13
13
|
:form_path, :layout_object, :search_clear_button, :search_autosearch,
|
|
14
14
|
:stimmify, :stimmify_camel, :hidden_create, :hidden_update, :invisible_create,
|
|
15
|
-
:invisible_update, :plural, :phantom_search
|
|
15
|
+
:invisible_update, :plural, :phantom_search, :pagination_style
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def initialize(singular:, singular_class: ,
|
|
@@ -25,7 +25,8 @@ module HotGlue
|
|
|
25
25
|
search:, search_fields:, search_query_fields: , search_position:,
|
|
26
26
|
search_clear_button:, search_autosearch:, layout_object:,
|
|
27
27
|
form_path: , stimmify: , stimmify_camel:, hidden_create:, hidden_update: ,
|
|
28
|
-
invisible_create:, invisible_update: , plural: , phantom_search
|
|
28
|
+
invisible_create:, invisible_update: , plural: , phantom_search:,
|
|
29
|
+
pagination_style: )
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
@form_path = form_path
|
|
@@ -66,6 +67,7 @@ module HotGlue
|
|
|
66
67
|
@attachments = attachments
|
|
67
68
|
@related_sets = related_sets
|
|
68
69
|
@phantom_search = phantom_search
|
|
70
|
+
@pagination_style = pagination_style
|
|
69
71
|
end
|
|
70
72
|
|
|
71
73
|
def add_spaces_each_line(text, num_spaces)
|
|
@@ -266,7 +268,17 @@ module HotGlue
|
|
|
266
268
|
def paginate(*args)
|
|
267
269
|
plural = args[0][:plural]
|
|
268
270
|
|
|
269
|
-
|
|
271
|
+
if @pagination_style == "kaminari"
|
|
272
|
+
"<% if #{plural}.respond_to?(:total_pages) %><%= paginate(#{plural}) %> <% end %>"
|
|
273
|
+
elsif @pagination_style == "will_paginate"
|
|
274
|
+
"<% if #{plural}.respond_to?(:total_pages) %><%= will_paginate(#{plural}) %> <% end %>"
|
|
275
|
+
elsif @pagination_style == "pagy"
|
|
276
|
+
if !@layout_strategy == "bootstrap"
|
|
277
|
+
"<%== pagy_nav(@pagy, anchor_string: 'data-turbo-action=\"advance\"') %>"
|
|
278
|
+
else
|
|
279
|
+
"<%== pagy_bootstrap_nav(@pagy, anchor_string: 'data-turbo-action=\"advance\"') %>"
|
|
280
|
+
end
|
|
281
|
+
end
|
|
270
282
|
end
|
|
271
283
|
|
|
272
284
|
|
|
@@ -166,6 +166,15 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
166
166
|
@stimulus_syntax = true
|
|
167
167
|
end
|
|
168
168
|
|
|
169
|
+
|
|
170
|
+
if Gem::Specification.find_all_by_name('pagy').any?
|
|
171
|
+
@pagination_style = 'pagy'
|
|
172
|
+
elsif Gem::Specification.find_all_by_name('will_paginate').any?
|
|
173
|
+
@pagination_style = 'will_paginate'
|
|
174
|
+
elsif Gem::Specification.find_all_by_name('kaminari').any?
|
|
175
|
+
@pagination_style = 'kaminari'
|
|
176
|
+
end
|
|
177
|
+
|
|
169
178
|
if !options['markup'].nil?
|
|
170
179
|
message = "Using --markup flag in the generator is deprecated; instead, use a file at config/hot_glue.yml with a key markup set to `erb` or `haml`"
|
|
171
180
|
raise(HotGlue::Error, message)
|
|
@@ -447,11 +456,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
447
456
|
|
|
448
457
|
child_name.gsub!("+","")
|
|
449
458
|
|
|
450
|
-
|
|
451
|
-
@downnest_object[child] = {
|
|
459
|
+
@downnest_object[child_name] = {
|
|
452
460
|
name: child_name,
|
|
453
461
|
extra_size: extra_size,
|
|
454
|
-
polymorph_as: polymorph_as
|
|
462
|
+
polymorph_as: polymorph_as,
|
|
455
463
|
}
|
|
456
464
|
end
|
|
457
465
|
end
|
|
@@ -503,17 +511,27 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
503
511
|
|
|
504
512
|
if !@nested.nil?
|
|
505
513
|
@nested_set = @nested.split("/").collect { |arg|
|
|
506
|
-
if arg.include?("(")
|
|
514
|
+
if arg.include?("[") && arg.include?("(")
|
|
515
|
+
arg =~ /(.*)\((.*)\)\[(.*)\]/
|
|
516
|
+
singular, polymorph_as, parent_name = $1, $2, $3
|
|
517
|
+
|
|
518
|
+
elsif arg.include?("(")
|
|
507
519
|
arg =~ /(.*)\((.*)\)/
|
|
508
520
|
singular, polymorph_as = $1, $2
|
|
521
|
+
parent_name = singular
|
|
522
|
+
elsif arg.include?("[")
|
|
523
|
+
arg =~ /(.*)\[(.*)\]/
|
|
524
|
+
singular, parent_name = $1, $2
|
|
509
525
|
else
|
|
510
526
|
singular = arg
|
|
527
|
+
parent_name = singular
|
|
511
528
|
end
|
|
512
529
|
|
|
513
530
|
{
|
|
514
531
|
singular: singular,
|
|
515
532
|
plural: singular.pluralize,
|
|
516
|
-
polymorph_as: polymorph_as
|
|
533
|
+
polymorph_as: polymorph_as,
|
|
534
|
+
parent_name: parent_name
|
|
517
535
|
}
|
|
518
536
|
}
|
|
519
537
|
puts "NESTING: #{@nested_set}"
|
|
@@ -704,7 +722,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
704
722
|
raise "You specified an alt-lookup for #{key} but that field is not an association field"
|
|
705
723
|
elsif !@columns_map[key.to_sym]
|
|
706
724
|
raise "You specified an alt-lookup for #{key} but that field does not exist in the list of columns"
|
|
707
|
-
elsif !@god && !@hawk_keys.include?(key.to_sym)
|
|
725
|
+
elsif !@god && !@hawk_keys.include?(key.to_sym) && !@factory_creation
|
|
708
726
|
raise "You specified an alt-lookup for #{key} in non-Gd mode but this would leave the lookup unprotected. To fix, use with --hawk or with --factory-creation "
|
|
709
727
|
end
|
|
710
728
|
end
|
|
@@ -845,7 +863,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
845
863
|
hidden_update: @hidden_update,
|
|
846
864
|
invisible_create: @invisible_create,
|
|
847
865
|
invisible_update: @invisible_update,
|
|
848
|
-
phantom_search: @phantom_search
|
|
866
|
+
phantom_search: @phantom_search,
|
|
867
|
+
pagination_style: @pagination_style
|
|
849
868
|
)
|
|
850
869
|
elsif @markup == "slim"
|
|
851
870
|
raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
|
|
@@ -1416,17 +1435,34 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
1416
1435
|
end
|
|
1417
1436
|
|
|
1418
1437
|
def object_scope
|
|
1438
|
+
if @nested_set.any? && @nested_set.last[:parent_name]
|
|
1439
|
+
last_parent = @nested_set.last[:parent_name]
|
|
1440
|
+
foreign_key = eval("#{singular_class}.reflect_on_association(:#{last_parent})").foreign_key
|
|
1441
|
+
association = eval(singular_class).reflect_on_association(@nested_set.last[:parent_name].to_sym)
|
|
1442
|
+
.klass.reflect_on_all_associations(:has_many)
|
|
1443
|
+
.to_a.find{|x|
|
|
1444
|
+
|
|
1445
|
+
if x.source_reflection
|
|
1446
|
+
x.foreign_key == foreign_key
|
|
1447
|
+
|
|
1448
|
+
# raise "#{singular_class} class declaration is missing source reflection for the `has_many :#{x.name}` association"
|
|
1449
|
+
end
|
|
1450
|
+
}.plural_name
|
|
1451
|
+
else
|
|
1452
|
+
association = plural
|
|
1453
|
+
end
|
|
1454
|
+
|
|
1419
1455
|
if @auth && !@god
|
|
1420
1456
|
if @nested_set.none?
|
|
1421
|
-
@auth + ".#{
|
|
1457
|
+
@auth + ".#{association}"
|
|
1422
1458
|
else
|
|
1423
|
-
"@" + @nested_set.last[:singular] + ".#{
|
|
1459
|
+
"@" + @nested_set.last[:singular] + ".#{association}"
|
|
1424
1460
|
end
|
|
1425
1461
|
else
|
|
1426
1462
|
if @nested_set.none?
|
|
1427
1463
|
@singular_class
|
|
1428
1464
|
else
|
|
1429
|
-
"@" + @nested_set.last[:singular] + ".#{
|
|
1465
|
+
"@" + @nested_set.last[:singular] + ".#{association}"
|
|
1430
1466
|
end
|
|
1431
1467
|
end
|
|
1432
1468
|
end
|
|
@@ -1448,10 +1484,10 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
1448
1484
|
def any_nested?
|
|
1449
1485
|
@nested_set.any?
|
|
1450
1486
|
end
|
|
1451
|
-
|
|
1452
|
-
def all_objects_variable
|
|
1453
|
-
|
|
1454
|
-
end
|
|
1487
|
+
#
|
|
1488
|
+
# def all_objects_variable
|
|
1489
|
+
# all_objects_root + ".page(params[:page])"
|
|
1490
|
+
# end
|
|
1455
1491
|
|
|
1456
1492
|
def auth_object
|
|
1457
1493
|
@auth
|
|
@@ -1815,7 +1851,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
1815
1851
|
else
|
|
1816
1852
|
if !@self_auth
|
|
1817
1853
|
|
|
1818
|
-
res << spaces(4) + "@#{ plural_name } = #{ object_scope.gsub("@",'') }#{ n_plus_one_includes }#{record_scope}"
|
|
1854
|
+
res << spaces(4) + "@#{ plural_name } = #{ object_scope.gsub("@",'') }#{ n_plus_one_includes }#{record_scope}#{".all" if n_plus_one_includes.blank? && record_scope.blank? }"
|
|
1819
1855
|
|
|
1820
1856
|
if @search_fields
|
|
1821
1857
|
res << @search_fields.collect{ |field|
|
|
@@ -1870,7 +1906,14 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
|
|
|
1870
1906
|
res << "\n"
|
|
1871
1907
|
end
|
|
1872
1908
|
|
|
1873
|
-
|
|
1909
|
+
|
|
1910
|
+
if @pagination_style == "kaminari"
|
|
1911
|
+
res << " @#{plural} = @#{plural}.page(params[:page])#{ ".per(per)" if @paginate_per_page_selector }"
|
|
1912
|
+
elsif @pagination_style == "will_paginate"
|
|
1913
|
+
res << " @#{plural} = @#{plural}.paginate(page: params[:page], #{ ", per_page: per" if @paginate_per_page_selector })"
|
|
1914
|
+
elsif @pagination_style == "pagy"
|
|
1915
|
+
res << " @pagy, @#{plural} = pagy(@#{plural})"
|
|
1916
|
+
end
|
|
1874
1917
|
res
|
|
1875
1918
|
end
|
|
1876
1919
|
|
|
@@ -24,15 +24,15 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
|
24
24
|
before_action :<%= arg[:singular] %><%= ", if: -> { params.include?(:#{arg[:singular]}_id) }" if arg[:optional] %><% } %><% end %>
|
|
25
25
|
before_action :load_<%= singular_name %>, only: %i[<%= "show edit update" unless @no_edit %> <%= "destroy" unless @no_delete %>]
|
|
26
26
|
after_action -> { flash.discard }, if: -> { request.format.symbol == :turbo_stream }<% if @nested_set.any? %>
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
def <%= @nested_set[0][:singular] %><% if @god
|
|
28
29
|
next_object = nil
|
|
29
30
|
collect_objects = @nested_set.reverse.collect {|x|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# if eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})")
|
|
34
|
-
next_object = eval("#{next_object || class_name}.reflect_on_association(:#{x[:singular]})").class_name
|
|
31
|
+
assoc_name = x[:parent_name] || x[:singular]
|
|
32
|
+
# if eval("#{next_object || class_name}.reflect_on_association(:#{assoc_name})").nil?
|
|
33
|
+
# raise "***** Unable to find the association `#{assoc_name}` on the class #{next_object || class_name} ..... you probably want to add `belongs_to :#{assoc_name}` to the #{next_object || class_name} object?"
|
|
35
34
|
# end
|
|
35
|
+
next_object = eval("#{next_object || class_name}.reflect_on_association(:#{assoc_name})").class_name
|
|
36
36
|
}
|
|
37
37
|
root_object = collect_objects.last
|
|
38
38
|
else
|
|
@@ -42,6 +42,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
|
42
42
|
root_object = @auth + "." + @nested_set[0][:plural]
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
|
+
|
|
45
46
|
%><% if !@god && @nested_set[0][:singular] == @auth_identifier %>
|
|
46
47
|
@<%= @nested_set[0][:singular] %> ||= <%= root_object %>
|
|
47
48
|
<% else %>
|
|
@@ -63,7 +64,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
|
|
|
63
64
|
def load_<%= singular_name %>
|
|
64
65
|
<% if @nested_set[0] && @nested_set[0][:optional] %>if params.include?(:<%= @nested_set.last[:singular] %>_id)
|
|
65
66
|
@<%= singular_name %> = <%= object_scope.gsub("@",'') %>.find(params[:id])
|
|
66
|
-
else <% end %>@<%= singular_name %> = <%= object_scope %>.find(params[:id])<% if @nested_set[0] && @nested_set[0][:optional] %>
|
|
67
|
+
else <% end %>@<%= singular_name %> = <%= object_scope.gsub("@",'') %>.find(params[:id])<% if @nested_set[0] && @nested_set[0][:optional] %>
|
|
67
68
|
end<% end %>
|
|
68
69
|
end
|
|
69
70
|
<% else %>
|
data/lib/hot-glue.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require "hotglue/engine"
|
|
2
|
-
require 'kaminari'
|
|
3
2
|
|
|
4
3
|
module HotGlue
|
|
5
4
|
module TemplateBuilders
|
|
@@ -10,7 +9,6 @@ module HotGlue
|
|
|
10
9
|
class Error < StandardError
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
|
|
14
12
|
def self.to_camel_case(str)
|
|
15
13
|
words = str.split(/[^a-zA-Z0-9]/) # split by non-alphanumeric characters
|
|
16
14
|
return '' if words.empty?
|
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.6.
|
|
4
|
+
version: 0.6.30
|
|
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: 2025-
|
|
11
|
+
date: 2025-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - ">"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '5.1'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: kaminari
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '1.2'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '1.2'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: ffaker
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|