bullet_train-super_scaffolding 1.1.14 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/account/scaffolding/completely_concrete/tangible_things_controller.rb +3 -1
- data/app/controllers/api/v1/scaffolding/completely_concrete/tangible_things_controller.rb +73 -64
- data/app/helpers/super_scaffolding_helper.rb +7 -4
- data/app/views/account/scaffolding/absolutely_abstract/creative_concepts/_creative_concept.html.erb +19 -0
- data/app/views/account/scaffolding/absolutely_abstract/creative_concepts/_index.html.erb +5 -14
- data/app/views/account/scaffolding/absolutely_abstract/creative_concepts/show.html.erb +1 -1
- data/app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb +5 -27
- data/app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.html.erb +30 -0
- data/app/views/api/v1/scaffolding/completely_concrete/tangible_things/_tangible_thing.json.jbuilder +2 -0
- data/lib/bullet_train/super_scaffolding/scaffolders/crud_field_scaffolder.rb +1 -1
- data/lib/bullet_train/super_scaffolding/scaffolders/crud_scaffolder.rb +3 -3
- data/lib/bullet_train/super_scaffolding/scaffolders/oauth_provider_scaffolder.rb +7 -1
- data/lib/bullet_train/super_scaffolding/version.rb +1 -1
- data/lib/bullet_train/terminal_commands.rb +5 -0
- data/lib/scaffolding/block_manipulator.rb +48 -1
- data/lib/scaffolding/class_names_transformer.rb +5 -0
- data/lib/scaffolding/transformer.rb +63 -28
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 167575ff368c6952598431b5dfc8e262746a5ff645c0e18900d3126f1f8472a3
|
4
|
+
data.tar.gz: 8e3fee7b5b4996401b7c6201b6b144589f0ddadf00dbfcd73a5762fc53261db3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e982e035723c9fd0b4dea89bf5067afd56027836a1514d2753e22fc14f04c4a892d5947cd570e76547d9d4b24214e31be449f80e2dabc453cadfa39c49c7da2
|
7
|
+
data.tar.gz: 73fab7774358693d8b5070cf035d8318b38e66fc7943dbc183e9fcfdef63579159668d1fe83f813bd8a67c412ba12ea4124a463456364583c9bc86459987131e
|
@@ -61,7 +61,9 @@ class Account::Scaffolding::CompletelyConcrete::TangibleThingsController < Accou
|
|
61
61
|
|
62
62
|
private
|
63
63
|
|
64
|
-
|
64
|
+
if defined?(Api::V1::ApplicationController)
|
65
|
+
include strong_parameters_from_api
|
66
|
+
end
|
65
67
|
|
66
68
|
def process_params(strong_params)
|
67
69
|
# 🚅 skip this section when scaffolding.
|
@@ -1,78 +1,87 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Api::V1::ApplicationController is in the starter repository and isn't
|
2
|
+
# needed for this package's unit tests, but our CI tests will try to load this
|
3
|
+
# class because eager loading is set to `true` when CI=true.
|
4
|
+
# We wrap this class in an `if` statement to circumvent this issue.
|
5
|
+
if defined?(Api::V1::ApplicationController)
|
6
|
+
class Api::V1::Scaffolding::CompletelyConcrete::TangibleThingsController < Api::V1::ApplicationController
|
7
|
+
account_load_and_authorize_resource :tangible_thing, through: :absolutely_abstract_creative_concept, through_association: :completely_concrete_tangible_things
|
3
8
|
|
4
|
-
|
5
|
-
|
6
|
-
|
9
|
+
# GET /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/tangible_things
|
10
|
+
def index
|
11
|
+
end
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
# GET /api/v1/scaffolding/completely_concrete/tangible_things/:id
|
14
|
+
def show
|
15
|
+
end
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
# POST /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/tangible_things
|
18
|
+
def create
|
19
|
+
if @tangible_thing.save
|
20
|
+
render :show, status: :created, location: [:api, :v1, @tangible_thing]
|
21
|
+
else
|
22
|
+
render json: @tangible_thing.errors, status: :unprocessable_entity
|
23
|
+
end
|
18
24
|
end
|
19
|
-
end
|
20
25
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
# PATCH/PUT /api/v1/scaffolding/completely_concrete/tangible_things/:id
|
27
|
+
def update
|
28
|
+
if @tangible_thing.update(tangible_thing_params)
|
29
|
+
render :show
|
30
|
+
else
|
31
|
+
render json: @tangible_thing.errors, status: :unprocessable_entity
|
32
|
+
end
|
27
33
|
end
|
28
|
-
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
# DELETE /api/v1/scaffolding/completely_concrete/tangible_things/:id
|
36
|
+
def destroy
|
37
|
+
@tangible_thing.destroy
|
38
|
+
end
|
34
39
|
|
35
|
-
|
40
|
+
private
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
42
|
+
module StrongParameters
|
43
|
+
# Only allow a list of trusted parameters through.
|
44
|
+
def tangible_thing_params
|
45
|
+
strong_params = params.require(:scaffolding_completely_concrete_tangible_thing).permit(
|
46
|
+
*permitted_fields,
|
47
|
+
# 🚅 skip this section when scaffolding.
|
48
|
+
:text_field_value,
|
49
|
+
:action_text_value,
|
50
|
+
:boolean_button_value,
|
51
|
+
:button_value,
|
52
|
+
:color_picker_value,
|
53
|
+
:cloudinary_image_value,
|
54
|
+
:date_field_value,
|
55
|
+
:date_and_time_field_value,
|
56
|
+
:date_and_time_field_value_time_zone,
|
57
|
+
:email_field_value,
|
58
|
+
:file_field_value,
|
59
|
+
:file_field_value_removal,
|
60
|
+
:option_value,
|
61
|
+
:password_field_value,
|
62
|
+
:phone_field_value,
|
63
|
+
:super_select_value,
|
64
|
+
:text_area_value,
|
65
|
+
# 🚅 stop any skipping we're doing now.
|
66
|
+
# 🚅 super scaffolding will insert new fields above this line.
|
67
|
+
*permitted_arrays,
|
68
|
+
# 🚅 skip this section when scaffolding.
|
69
|
+
multiple_button_values: [],
|
70
|
+
multiple_option_values: [],
|
71
|
+
multiple_super_select_values: []
|
72
|
+
# 🚅 stop any skipping we're doing now.
|
73
|
+
# 🚅 super scaffolding will insert new arrays above this line.
|
74
|
+
)
|
70
75
|
|
71
|
-
|
76
|
+
process_params(strong_params)
|
72
77
|
|
73
|
-
|
78
|
+
strong_params
|
79
|
+
end
|
74
80
|
end
|
75
|
-
end
|
76
81
|
|
77
|
-
|
82
|
+
include StrongParameters
|
83
|
+
end
|
84
|
+
else
|
85
|
+
class Api::V1::Scaffolding::CompletelyConcrete::TangibleThingsController
|
86
|
+
end
|
78
87
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module SuperScaffoldingHelper
|
2
2
|
unless defined?(BulletTrain::ActionModels)
|
3
|
+
# action_model_select_controller is originally a method
|
4
|
+
# in the Action Models package, but we can't simply
|
5
|
+
# remove this method from Super Scaffolded index partials
|
6
|
+
# when the package isn't present. Since we keep
|
7
|
+
# action_model_select_controller in our views, we need
|
8
|
+
# this method so we don't get a NoMethodError.
|
3
9
|
def action_model_select_controller
|
4
|
-
|
5
|
-
tag.div do
|
6
|
-
yield
|
7
|
-
end
|
10
|
+
yield
|
8
11
|
end
|
9
12
|
end
|
10
13
|
end
|
data/app/views/account/scaffolding/absolutely_abstract/creative_concepts/_creative_concept.html.erb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
<% context ||= @team %>
|
2
|
+
<% hide_actions ||= false %>
|
3
|
+
<% hide_back ||= false %>
|
4
|
+
|
5
|
+
<% with_attribute_settings object: creative_concept do %>
|
6
|
+
<tr data-id="<%= creative_concept.id %>">
|
7
|
+
<td><%= render 'shared/attributes/text', attribute: :name, url: [:account, creative_concept] %></td>
|
8
|
+
<td><%= render 'account/shared/memberships/photos', memberships: creative_concept.all_collaborators, size: 9, align: :center %></td>
|
9
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
10
|
+
<td><%= display_date_and_time(creative_concept.created_at) %></td>
|
11
|
+
<td class="buttons">
|
12
|
+
<% unless hide_actions %>
|
13
|
+
<%# We write the full path here since this partial is called from different scopes. %>
|
14
|
+
<%= link_to t('account.scaffolding.absolutely_abstract.creative_concepts.buttons.shorthand.edit'), [:edit, :account, creative_concept], class: 'button-secondary button-smaller' if can? :edit, creative_concept %>
|
15
|
+
<%= button_to t('account.scaffolding.absolutely_abstract.creative_concepts.buttons.shorthand.destroy'), [:account, creative_concept], method: :delete, data: { confirm: t('account.scaffolding.absolutely_abstract.creative_concepts.buttons.confirmations.destroy', model_locales(creative_concept)) }, class: 'button-secondary button-smaller' if can? :destroy, creative_concept %>
|
16
|
+
<% end %>
|
17
|
+
</td>
|
18
|
+
</tr>
|
19
|
+
<% end %>
|
@@ -1,7 +1,11 @@
|
|
1
|
+
<% creative_concepts = creative_concepts.accessible_by(current_ability) %>
|
1
2
|
<% context ||= @team %>
|
2
3
|
<% hide_actions ||= false %>
|
3
4
|
<% hide_back ||= false %>
|
4
5
|
|
6
|
+
<% pagy ||= nil %>
|
7
|
+
<% pagy, creative_concepts = pagy(creative_concepts, page_param: :creative_concepts_page) unless pagy %>
|
8
|
+
|
5
9
|
<%= updates_for context, :scaffolding_absolutely_abstract_creative_concepts do %>
|
6
10
|
<%= render 'account/shared/box' do |p| %>
|
7
11
|
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
@@ -24,20 +28,7 @@
|
|
24
28
|
</thead>
|
25
29
|
<tbody>
|
26
30
|
<% creative_concepts.each do |creative_concept| %>
|
27
|
-
|
28
|
-
<tr data-id="<%= creative_concept.id %>">
|
29
|
-
<td><%= render 'shared/attributes/text', attribute: :name, url: [:account, creative_concept] %></td>
|
30
|
-
<td><%= render 'account/shared/memberships/photos', memberships: creative_concept.all_collaborators, size: 9, align: :center %></td>
|
31
|
-
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
32
|
-
<td><%= display_date_and_time(creative_concept.created_at) %></td>
|
33
|
-
<td class="buttons">
|
34
|
-
<% unless hide_actions %>
|
35
|
-
<%= link_to t('.buttons.shorthand.edit'), [:edit, :account, creative_concept], class: 'button-secondary button-smaller' if can? :edit, creative_concept %>
|
36
|
-
<%= button_to t('.buttons.shorthand.destroy'), [:account, creative_concept], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(creative_concept)) }, class: 'button-secondary button-smaller' if can? :destroy, creative_concept %>
|
37
|
-
<% end %>
|
38
|
-
</td>
|
39
|
-
</tr>
|
40
|
-
<% end %>
|
31
|
+
<%= render 'account/scaffolding/absolutely_abstract/creative_concepts/creative_concept', creative_concept: creative_concept %>
|
41
32
|
<% end %>
|
42
33
|
</tbody>
|
43
34
|
</table>
|
@@ -54,7 +54,7 @@
|
|
54
54
|
<% end %>
|
55
55
|
<% end %>
|
56
56
|
|
57
|
-
<%= render 'account/scaffolding/completely_concrete/tangible_things/index', tangible_things: @creative_concept.completely_concrete_tangible_things
|
57
|
+
<%= render 'account/scaffolding/completely_concrete/tangible_things/index', tangible_things: @creative_concept.completely_concrete_tangible_things, hide_back: true %>
|
58
58
|
|
59
59
|
<% if can? :read, Scaffolding::AbsolutelyAbstract::CreativeConcepts::Collaborator.new(creative_concept: @creative_concept) %>
|
60
60
|
<%= render 'account/scaffolding/absolutely_abstract/creative_concepts/collaborators/index', collaborators: @creative_concept.collaborators, hide_back: true %>
|
@@ -1,14 +1,15 @@
|
|
1
|
+
<% tangible_things = tangible_things.accessible_by(current_ability) %>
|
1
2
|
<% absolutely_abstract_creative_concept = @absolutely_abstract_creative_concept || @creative_concept %>
|
2
3
|
<% context ||= absolutely_abstract_creative_concept %>
|
3
4
|
<% collection ||= :completely_concrete_tangible_things %>
|
4
5
|
<% hide_actions ||= false %>
|
5
6
|
<% hide_back ||= false %>
|
6
7
|
|
7
|
-
<%
|
8
|
-
<% pagy, tangible_things = pagy(tangible_things, page_param: :tangible_things_page) %>
|
8
|
+
<% pagy ||= nil %>
|
9
|
+
<% pagy, tangible_things = pagy(tangible_things, page_param: :tangible_things_page) unless pagy %>
|
9
10
|
|
10
11
|
<%= action_model_select_controller do %>
|
11
|
-
|
12
|
+
<% updates_for context, collection do %>
|
12
13
|
<%= render 'account/shared/box', pagy: pagy do |p| %>
|
13
14
|
<% p.content_for :title, t(".contexts.#{context.class.name.underscore}.header") %>
|
14
15
|
<% p.content_for :description do %>
|
@@ -35,30 +36,7 @@
|
|
35
36
|
</thead>
|
36
37
|
<tbody>
|
37
38
|
<% tangible_things.each do |tangible_thing| %>
|
38
|
-
|
39
|
-
<tr data-id="<%= tangible_thing.id %>">
|
40
|
-
<%= render "shared/tables/checkbox", object: tangible_thing %>
|
41
|
-
<%# 🚅 skip this section when scaffolding. %>
|
42
|
-
<td><%= render 'shared/attributes/text', attribute: :text_field_value, url: [:account, tangible_thing] %></td>
|
43
|
-
<td><%= render 'shared/attributes/boolean', attribute: :boolean_button_value %></td>
|
44
|
-
<td><%= render 'shared/attributes/option', attribute: :button_value %></td>
|
45
|
-
<td><%= render 'shared/attributes/options', attribute: :multiple_button_values %></td>
|
46
|
-
<%# 🚅 stop any skipping we're doing now. %>
|
47
|
-
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
48
|
-
<td><%= render 'shared/attributes/date_and_time', attribute: :created_at %></td>
|
49
|
-
<td class="buttons">
|
50
|
-
<% unless hide_actions %>
|
51
|
-
<% if can? :edit, tangible_thing %>
|
52
|
-
<%= link_to t('.buttons.shorthand.edit'), [:edit, :account, tangible_thing], class: 'button-secondary button-smaller' %>
|
53
|
-
<% end %>
|
54
|
-
<% if can? :destroy, tangible_thing %>
|
55
|
-
<%= button_to t('.buttons.shorthand.destroy'), [:account, tangible_thing], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(tangible_thing)) }, class: 'button-secondary button-smaller' %>
|
56
|
-
<% end %>
|
57
|
-
<%# 🚅 super scaffolding will insert new action model buttons above this line. %>
|
58
|
-
<% end %>
|
59
|
-
</td>
|
60
|
-
</tr>
|
61
|
-
<% end %>
|
39
|
+
<%= render 'account/scaffolding/completely_concrete/tangible_things/tangible_thing', tangible_thing: tangible_thing %>
|
62
40
|
<% end %>
|
63
41
|
</tbody>
|
64
42
|
</table>
|
data/app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.html.erb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
<% absolutely_abstract_creative_concept = @absolutely_abstract_creative_concept || @creative_concept %>
|
2
|
+
<% context ||= absolutely_abstract_creative_concept %>
|
3
|
+
<% collection ||= :completely_concrete_tangible_things %>
|
4
|
+
<% hide_actions ||= false %>
|
5
|
+
<% hide_back ||= false %>
|
6
|
+
|
7
|
+
<% with_attribute_settings object: tangible_thing do %>
|
8
|
+
<tr data-id="<%= tangible_thing.id %>">
|
9
|
+
<%= render "shared/tables/checkbox", object: tangible_thing %>
|
10
|
+
<%# 🚅 skip this section when scaffolding. %>
|
11
|
+
<td><%= render 'shared/attributes/text', attribute: :text_field_value, url: [:account, tangible_thing] %></td>
|
12
|
+
<td><%= render 'shared/attributes/boolean', attribute: :boolean_button_value %></td>
|
13
|
+
<td><%= render 'shared/attributes/option', attribute: :button_value %></td>
|
14
|
+
<td><%= render 'shared/attributes/options', attribute: :multiple_button_values %></td>
|
15
|
+
<%# 🚅 stop any skipping we're doing now. %>
|
16
|
+
<%# 🚅 super scaffolding will insert new fields above this line. %>
|
17
|
+
<td><%= render 'shared/attributes/date_and_time', attribute: :created_at %></td>
|
18
|
+
<td class="buttons">
|
19
|
+
<% unless hide_actions %>
|
20
|
+
<% if can? :edit, tangible_thing %>
|
21
|
+
<%= link_to t('.buttons.shorthand.edit'), [:edit, :account, tangible_thing], class: 'button-secondary button-smaller' %>
|
22
|
+
<% end %>
|
23
|
+
<% if can? :destroy, tangible_thing %>
|
24
|
+
<%= button_to t('.buttons.shorthand.destroy'), [:account, tangible_thing], method: :delete, data: { confirm: t('.buttons.confirmations.destroy', model_locales(tangible_thing)) }, class: 'button-secondary button-smaller' %>
|
25
|
+
<% end %>
|
26
|
+
<%# 🚅 super scaffolding will insert new action model buttons above this line. %>
|
27
|
+
<% end %>
|
28
|
+
</td>
|
29
|
+
</tr>
|
30
|
+
<% end %>
|
@@ -9,7 +9,7 @@ module BulletTrain
|
|
9
9
|
puts ""
|
10
10
|
puts "E.g. add a description and body to Pages:"
|
11
11
|
puts " rails g migration add_description_etc_to_pages description:text body:text"
|
12
|
-
puts " bin/super-scaffold crud-field Page description:
|
12
|
+
puts " bin/super-scaffold crud-field Page description:text_area body:text_area"
|
13
13
|
puts ""
|
14
14
|
puts "Options:"
|
15
15
|
puts ""
|
@@ -9,18 +9,18 @@ module BulletTrain
|
|
9
9
|
puts ""
|
10
10
|
puts "E.g. a Team has many Sites with some attributes:"
|
11
11
|
puts " rails g model Site team:references name:string url:text"
|
12
|
-
puts " bin/super-scaffold crud Site Team name:
|
12
|
+
puts " bin/super-scaffold crud Site Team name:text_field url:text_area"
|
13
13
|
puts ""
|
14
14
|
puts "E.g. a Section belongs to a Page, which belongs to a Site, which belongs to a Team:"
|
15
15
|
puts " rails g model Section page:references title:text body:text"
|
16
|
-
puts " bin/super-scaffold crud Section Page,Site,Team title:
|
16
|
+
puts " bin/super-scaffold crud Section Page,Site,Team title:text_area body:text_area"
|
17
17
|
puts ""
|
18
18
|
puts "E.g. an Image belongs to either a Page or a Site:"
|
19
19
|
puts " Doable! See https://bit.ly/2NvO8El for a step by step guide."
|
20
20
|
puts ""
|
21
21
|
puts "E.g. Pages belong to a Site and are sortable via drag-and-drop:"
|
22
22
|
puts " rails g model Page site:references name:string path:text"
|
23
|
-
puts " bin/super-scaffold crud Page Site,Team name:
|
23
|
+
puts " bin/super-scaffold crud Page Site,Team name:text_field path:text_area --sortable"
|
24
24
|
puts ""
|
25
25
|
puts "🏆 Protip: Commit your other changes before running Super Scaffolding so it's easy to undo if you (or we) make any mistakes."
|
26
26
|
puts "If you do that, you can reset to your last commit state by using `git checkout .` and `git clean -d -f` ."
|
@@ -61,7 +61,13 @@ module BulletTrain
|
|
61
61
|
puts "When you find one you like, hover your mouse over it and then come back here and"
|
62
62
|
puts "and enter the name of the icon you want to use."
|
63
63
|
response = $stdin.gets.chomp
|
64
|
-
TerminalCommands.
|
64
|
+
if TerminalCommands.can_open?
|
65
|
+
TerminalCommands.open_file_or_link("http://light.pinsupreme.com/icon_fonts_themefy.html")
|
66
|
+
else
|
67
|
+
puts "Sorry! We can't open these URLs automatically on your platform, but you can visit them manually:"
|
68
|
+
puts ""
|
69
|
+
puts " http://light.pinsupreme.com/icon_fonts_themefy.html"
|
70
|
+
end
|
65
71
|
puts ""
|
66
72
|
puts "Did you find an icon you wanted to use? Enter the name here or hit enter to just"
|
67
73
|
puts "use the dollar symbol:"
|
@@ -41,6 +41,30 @@ module Scaffolding::BlockManipulator
|
|
41
41
|
lines
|
42
42
|
end
|
43
43
|
|
44
|
+
# This method unwraps the block from the perspective of the child.
|
45
|
+
#
|
46
|
+
# 2.times do
|
47
|
+
# 3.times do
|
48
|
+
# puts "foo"
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# Here we would pass the index of `"3.times do\n"` to
|
53
|
+
# `block_start` which would result in removing the outer block.
|
54
|
+
def self.unwrap_block(lines:, block_start:)
|
55
|
+
block_start = if block_start.is_a? String
|
56
|
+
block_start_line = lines.find { |line| line.match?(block_start) }
|
57
|
+
lines.index(block_start_line)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Find the proper indices for both child and parent blocks.
|
61
|
+
block_parent_start = find_block_parent(block_start, lines)
|
62
|
+
block_parent_end = find_block_end(starting_from: block_parent_start, lines: lines)
|
63
|
+
|
64
|
+
new_lines = shift_block(lines: lines, block_start: block_start)
|
65
|
+
new_lines.reject.with_index { |lines, idx| idx == block_parent_start || idx == block_parent_end }
|
66
|
+
end
|
67
|
+
|
44
68
|
def self.insert(content, lines:, within: nil, after: nil, before: nil, after_block: nil, append: false)
|
45
69
|
# Search for before like we do after, we'll just inject before it.
|
46
70
|
after ||= before
|
@@ -133,7 +157,7 @@ module Scaffolding::BlockManipulator
|
|
133
157
|
# This loop was previously in the RoutesFileManipulator.
|
134
158
|
lines.each_with_index do |line, line_number|
|
135
159
|
next unless line_number > starting_from
|
136
|
-
if /^#{indentation_of(starting_from, lines)}end\s
|
160
|
+
if /^#{indentation_of(starting_from, lines)}end\s*/.match?(line)
|
137
161
|
return line_number
|
138
162
|
end
|
139
163
|
end
|
@@ -159,4 +183,27 @@ module Scaffolding::BlockManipulator
|
|
159
183
|
rescue
|
160
184
|
nil
|
161
185
|
end
|
186
|
+
|
187
|
+
# Shifts the block either to the left or right.
|
188
|
+
def self.shift_block(lines:, block_start:, direction: :left, amount: 2, shift_contents_only: false)
|
189
|
+
block_start = lines.index(block_start) if block_start.is_a? String
|
190
|
+
block_range = (block_start..(find_block_end(starting_from: block_start, lines: lines)))
|
191
|
+
block_range = (block_range.first + 1)..(block_range.last - 1) if shift_contents_only
|
192
|
+
new_lines = []
|
193
|
+
|
194
|
+
lines.each_with_index do |line, line_number|
|
195
|
+
if block_range.cover?(line_number)
|
196
|
+
# If we're shifting a block to the left, we want to safeguard
|
197
|
+
# the String so it doesn't delete any excess characters.
|
198
|
+
if direction == :left
|
199
|
+
amount.times { line = line.gsub(/^\s/, "") }
|
200
|
+
elsif direction == :right
|
201
|
+
line = "\s" * amount + line
|
202
|
+
end
|
203
|
+
end
|
204
|
+
new_lines << line
|
205
|
+
end
|
206
|
+
|
207
|
+
new_lines
|
208
|
+
end
|
162
209
|
end
|
@@ -100,6 +100,11 @@ class Scaffolding::ClassNamesTransformer
|
|
100
100
|
parent.pluralize.titlecase.tr("/", " ")
|
101
101
|
when "Scaffolding Completely Concrete Tangible Things"
|
102
102
|
child.pluralize.titlecase.tr("/", " ")
|
103
|
+
|
104
|
+
# This is a specific example for locales where we only leave tangible_things.
|
105
|
+
when "scaffolding.completely_concrete.tangible_things"
|
106
|
+
child.underscore.pluralize
|
107
|
+
|
103
108
|
when "Scaffolding/Absolutely Abstract/Creative Concepts"
|
104
109
|
parent.pluralize.titlecase
|
105
110
|
when "Scaffolding/Completely Concrete/Tangible Things"
|
@@ -6,9 +6,6 @@ require "scaffolding/class_names_transformer"
|
|
6
6
|
class Scaffolding::Transformer
|
7
7
|
attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find
|
8
8
|
|
9
|
-
def code_for_child_on_parent_show_page
|
10
|
-
end
|
11
|
-
|
12
9
|
def update_models_abstract_class
|
13
10
|
end
|
14
11
|
|
@@ -101,6 +98,7 @@ class Scaffolding::Transformer
|
|
101
98
|
"scaffolding_completely_concrete_tangible_thing",
|
102
99
|
"scaffolding-absolutely-abstract-creative-concept",
|
103
100
|
"scaffolding-completely-concrete-tangible-thing",
|
101
|
+
"scaffolding.completely_concrete.tangible_things",
|
104
102
|
|
105
103
|
# class name in context plural.
|
106
104
|
"absolutely_abstract_creative_concepts",
|
@@ -703,7 +701,7 @@ class Scaffolding::Transformer
|
|
703
701
|
when "file_field"
|
704
702
|
"file"
|
705
703
|
when "password_field"
|
706
|
-
"
|
704
|
+
"text"
|
707
705
|
else
|
708
706
|
raise "Invalid field type: #{type}."
|
709
707
|
end
|
@@ -912,6 +910,10 @@ class Scaffolding::Transformer
|
|
912
910
|
<%= render 'shared/attributes/#{attribute_partial}', attribute: :#{attribute_name} %>
|
913
911
|
ERB
|
914
912
|
|
913
|
+
if type == "password_field"
|
914
|
+
field_content.gsub!(/\s%>/, ", options: { password: true } %>")
|
915
|
+
end
|
916
|
+
|
915
917
|
scaffold_add_line_to_file("./app/views/account/scaffolding/completely_concrete/tangible_things/show.html.erb", field_content.strip, ERB_NEW_FIELDS_HOOK, prepend: true)
|
916
918
|
|
917
919
|
end
|
@@ -940,8 +942,12 @@ class Scaffolding::Transformer
|
|
940
942
|
<td#{cell_attributes}><%= render 'shared/attributes/#{attribute_partial}', attribute: :#{attribute_name}#{", #{table_cell_options.join(", ")}" if table_cell_options.any?} %></td>
|
941
943
|
ERB
|
942
944
|
|
945
|
+
if type == "password_field"
|
946
|
+
field_content.gsub!(/\s%>/, ", options: { password: true } %>")
|
947
|
+
end
|
948
|
+
|
943
949
|
unless ["Team", "User"].include?(child)
|
944
|
-
scaffold_add_line_to_file("./app/views/account/scaffolding/completely_concrete/tangible_things/
|
950
|
+
scaffold_add_line_to_file("./app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.html.erb", field_content.strip, ERB_NEW_FIELDS_HOOK, prepend: true)
|
945
951
|
end
|
946
952
|
|
947
953
|
end
|
@@ -1040,6 +1046,10 @@ class Scaffolding::Transformer
|
|
1040
1046
|
elsif is_multiple
|
1041
1047
|
"assign_checkboxes(strong_params, :#{name})"
|
1042
1048
|
end
|
1049
|
+
when "options"
|
1050
|
+
if is_multiple
|
1051
|
+
"assign_checkboxes(strong_params, :#{name})"
|
1052
|
+
end
|
1043
1053
|
when "super_select"
|
1044
1054
|
if boolean_buttons
|
1045
1055
|
"assign_boolean(strong_params, :#{name})"
|
@@ -1059,7 +1069,9 @@ class Scaffolding::Transformer
|
|
1059
1069
|
|
1060
1070
|
# TODO The serializers can't handle these `has_rich_text` attributes.
|
1061
1071
|
unless type == "trix_editor"
|
1062
|
-
|
1072
|
+
unless type == "file_field"
|
1073
|
+
scaffold_add_line_to_file("./app/views/api/v1/scaffolding/completely_concrete/tangible_things/_tangible_thing.json.jbuilder", ":#{name},", RUBY_NEW_FIELDS_HOOK, prepend: true, suppress_could_not_find: true)
|
1074
|
+
end
|
1063
1075
|
|
1064
1076
|
assertion = case type
|
1065
1077
|
when "date_field"
|
@@ -1067,8 +1079,7 @@ class Scaffolding::Transformer
|
|
1067
1079
|
when "date_and_time_field"
|
1068
1080
|
"assert_equal_or_nil DateTime.parse(tangible_thing_data['#{name}']), tangible_thing.#{name}"
|
1069
1081
|
when "file_field"
|
1070
|
-
#
|
1071
|
-
"# assert tangible_thing_data['#{name}'].match?('foo.txt') unless response.status == 201"
|
1082
|
+
"assert_equal tangible_thing_data['#{name}'], rails_blob_path(@tangible_thing.#{name}) unless controller.action_name == 'create'"
|
1072
1083
|
else
|
1073
1084
|
"assert_equal_or_nil tangible_thing_data['#{name}'], tangible_thing.#{name}"
|
1074
1085
|
end
|
@@ -1077,10 +1088,13 @@ class Scaffolding::Transformer
|
|
1077
1088
|
|
1078
1089
|
# File fields are handled in a specific way when using the jsonapi-serializer.
|
1079
1090
|
if type == "file_field"
|
1080
|
-
|
1091
|
+
scaffold_add_line_to_file("./app/views/api/v1/scaffolding/completely_concrete/tangible_things/_tangible_thing.json.jbuilder", "json.#{name} url_for(tangible_thing.#{name}) if tangible_thing.#{name}.attached?", RUBY_FILES_HOOK, prepend: true, suppress_could_not_find: true)
|
1081
1092
|
# We also want to make sure we attach the dummy file in the API test on setup
|
1082
1093
|
file_name = "./test/controllers/api/v1/scaffolding/completely_concrete/tangible_things_controller_test.rb"
|
1083
|
-
content =
|
1094
|
+
content = <<~RUBY
|
1095
|
+
@#{child.underscore}.#{name} = Rack::Test::UploadedFile.new("test/support/foo.txt")
|
1096
|
+
@another_#{child.underscore}.#{name} = Rack::Test::UploadedFile.new("test/support/foo.txt")
|
1097
|
+
RUBY
|
1084
1098
|
scaffold_add_line_to_file(file_name, content, RUBY_FILES_HOOK, prepend: true)
|
1085
1099
|
end
|
1086
1100
|
|
@@ -1214,6 +1228,25 @@ class Scaffolding::Transformer
|
|
1214
1228
|
end
|
1215
1229
|
end
|
1216
1230
|
|
1231
|
+
# Add `default: false` to boolean migrations.
|
1232
|
+
if boolean_buttons
|
1233
|
+
confirmation_reference = "create_table :#{class_names_transformer.table_name}"
|
1234
|
+
confirmation_migration_file_name = `grep "#{confirmation_reference}" db/migrate/*`.split(":").first
|
1235
|
+
|
1236
|
+
old_line, new_line = nil
|
1237
|
+
File.open(confirmation_migration_file_name) do |migration_file|
|
1238
|
+
old_lines = migration_file.readlines
|
1239
|
+
old_lines.each do |line|
|
1240
|
+
target_attribute = line.match?(/\s*t\.boolean :#{name}/)
|
1241
|
+
if target_attribute
|
1242
|
+
old_line = line
|
1243
|
+
new_line = "#{old_line.chomp}, default: false\n"
|
1244
|
+
end
|
1245
|
+
end
|
1246
|
+
end
|
1247
|
+
replace_in_file(confirmation_migration_file_name, old_line, new_line)
|
1248
|
+
end
|
1249
|
+
|
1217
1250
|
end
|
1218
1251
|
|
1219
1252
|
#
|
@@ -1239,18 +1272,23 @@ class Scaffolding::Transformer
|
|
1239
1272
|
end
|
1240
1273
|
RUBY
|
1241
1274
|
|
1242
|
-
# Generating a model with an `attachment` data type (i.e. - `rails g ModelName file:attachment`)
|
1243
|
-
# adds `has_one_attached` to our model, just not directly above the
|
1244
|
-
# We move the string here so it's
|
1275
|
+
# Generating a model with an `attachment(s)` data type (i.e. - `rails g ModelName file:attachment`)
|
1276
|
+
# adds `has_one_attached` or `has_many_attached` to our model, just not directly above the
|
1277
|
+
# HAS_ONE_HOOK or the HAS_MANY_HOOK. We move the string here so it's scaffolded above the proper hook.
|
1245
1278
|
model_file_path = transform_string("./app/models/scaffolding/completely_concrete/tangible_thing.rb")
|
1246
1279
|
model_contents = File.readlines(model_file_path)
|
1247
|
-
|
1280
|
+
reflection_declaration = is_multiple ? "has_many_attached :#{name}" : "has_one_attached :#{name}"
|
1281
|
+
|
1282
|
+
# Save the file without the hook so we can write it via the `scaffold_add_line_to_file` method below.
|
1283
|
+
model_without_attached_hook = model_contents.reject.each { |line| line.include?(reflection_declaration) }
|
1248
1284
|
File.open(model_file_path, "w") do |f|
|
1249
1285
|
model_without_attached_hook.each { |line| f.write(line) }
|
1250
1286
|
end
|
1251
1287
|
|
1252
|
-
|
1288
|
+
hook_type = is_multiple ? HAS_MANY_HOOK : HAS_ONE_HOOK
|
1289
|
+
scaffold_add_line_to_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", reflection_declaration, hook_type, prepend: true)
|
1253
1290
|
|
1291
|
+
# TODO: We may need to edit these depending on how we save multiple files.
|
1254
1292
|
scaffold_add_line_to_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", "attr_accessor :#{name}_removal", ATTR_ACCESSORS_HOOK, prepend: true)
|
1255
1293
|
scaffold_add_line_to_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", remove_file_methods, METHODS_HOOK, prepend: true)
|
1256
1294
|
scaffold_add_line_to_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", "after_validation :remove_#{name}, if: :#{name}_removal?", CALLBACKS_HOOK, prepend: true)
|
@@ -1295,7 +1333,8 @@ class Scaffolding::Transformer
|
|
1295
1333
|
files = if cli_options["only-index"]
|
1296
1334
|
[
|
1297
1335
|
"./app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb",
|
1298
|
-
"./app/views/account/scaffolding/completely_concrete/tangible_things/index.html.erb"
|
1336
|
+
"./app/views/account/scaffolding/completely_concrete/tangible_things/index.html.erb",
|
1337
|
+
"./app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.html.erb"
|
1299
1338
|
]
|
1300
1339
|
else
|
1301
1340
|
# copy a ton of files over and do the appropriate string replace.
|
@@ -1362,7 +1401,7 @@ class Scaffolding::Transformer
|
|
1362
1401
|
unless cli_options["skip-parent"] || parent == "None"
|
1363
1402
|
scaffold_add_line_to_file(
|
1364
1403
|
"./app/views/account/scaffolding/absolutely_abstract/creative_concepts/show.html.erb",
|
1365
|
-
|
1404
|
+
"<%= render 'account/scaffolding/completely_concrete/tangible_things/index', tangible_things: @creative_concept.completely_concrete_tangible_things, hide_back: true %>",
|
1366
1405
|
"<%# 🚅 super scaffolding will insert new children above this line. %>",
|
1367
1406
|
prepend: true
|
1368
1407
|
)
|
@@ -1466,23 +1505,19 @@ class Scaffolding::Transformer
|
|
1466
1505
|
|
1467
1506
|
begin
|
1468
1507
|
routes_manipulator.apply([routes_namespace])
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1508
|
+
Scaffolding::FileManipulator.write("config/routes.rb", routes_manipulator.lines)
|
1509
|
+
rescue => _
|
1510
|
+
add_additional_step :red, "We weren't able to automatically add your `#{routes_namespace}` routes for you. In theory this should be very rare, so if you could reach out on Slack, you could probably provide context that will help us fix whatever the problem was. In the meantime, to add the routes manually, we've got a guide at https://blog.bullettrain.co/nested-namespaced-rails-routing-examples/ ."
|
1472
1511
|
end
|
1473
1512
|
|
1474
|
-
Scaffolding::FileManipulator.write("config/routes.rb", routes_manipulator.lines)
|
1475
|
-
|
1476
1513
|
unless cli_options["skip-api"]
|
1477
1514
|
begin
|
1478
1515
|
api_routes_manipulator = Scaffolding::RoutesFileManipulator.new("config/routes/api/#{BulletTrain::Api.current_version}.rb", child, parent, cli_options)
|
1479
1516
|
api_routes_manipulator.apply([BulletTrain::Api.current_version.to_sym])
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1517
|
+
Scaffolding::FileManipulator.write("config/routes/api/#{BulletTrain::Api.current_version}.rb", api_routes_manipulator.lines)
|
1518
|
+
rescue => _
|
1519
|
+
add_additional_step :red, "We weren't able to automatically add your `api/#{BulletTrain::Api.current_version}` routes for you. In theory this should be very rare, so if you could reach out on Slack, you could probably provide context that will help us fix whatever the problem was. In the meantime, to add the routes manually, we've got a guide at https://blog.bullettrain.co/nested-namespaced-rails-routing-examples/ ."
|
1483
1520
|
end
|
1484
|
-
|
1485
|
-
Scaffolding::FileManipulator.write("config/routes/api/#{BulletTrain::Api.current_version}.rb", api_routes_manipulator.lines)
|
1486
1521
|
end
|
1487
1522
|
end
|
1488
1523
|
|
@@ -1505,7 +1540,7 @@ class Scaffolding::Transformer
|
|
1505
1540
|
puts "enter the name of the icon you want to use."
|
1506
1541
|
puts "(Or hit enter when choosing to skip this step.)"
|
1507
1542
|
$stdin.gets.chomp
|
1508
|
-
if
|
1543
|
+
if TerminalCommands.can_open?
|
1509
1544
|
TerminalCommands.open_file_or_link("https://themify.me/themify-icons")
|
1510
1545
|
if font_awesome?
|
1511
1546
|
TerminalCommands.open_file_or_link("https://fontawesome.com/icons?d=gallery&s=light")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train-super_scaffolding
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- app/models/scaffolding/completely_concrete/tangible_things.rb
|
101
101
|
- app/models/scaffolding/completely_concrete/tangible_things/assignment.rb
|
102
102
|
- app/views/account/scaffolding/absolutely_abstract/creative_concepts/_breadcrumbs.html.erb
|
103
|
+
- app/views/account/scaffolding/absolutely_abstract/creative_concepts/_creative_concept.html.erb
|
103
104
|
- app/views/account/scaffolding/absolutely_abstract/creative_concepts/_creative_concept.json.jbuilder
|
104
105
|
- app/views/account/scaffolding/absolutely_abstract/creative_concepts/_form.html.erb
|
105
106
|
- app/views/account/scaffolding/absolutely_abstract/creative_concepts/_index.html.erb
|
@@ -125,6 +126,7 @@ files:
|
|
125
126
|
- app/views/account/scaffolding/completely_concrete/tangible_things/_form.html.erb
|
126
127
|
- app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb
|
127
128
|
- app/views/account/scaffolding/completely_concrete/tangible_things/_menu_item.html.erb
|
129
|
+
- app/views/account/scaffolding/completely_concrete/tangible_things/_tangible_thing.html.erb
|
128
130
|
- app/views/account/scaffolding/completely_concrete/tangible_things/edit.html.erb
|
129
131
|
- app/views/account/scaffolding/completely_concrete/tangible_things/index.html.erb
|
130
132
|
- app/views/account/scaffolding/completely_concrete/tangible_things/new.html.erb
|