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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2129ed55c51850638d178892b9aa302d66640a0925a36e707dc08cc0a8e389bd
4
- data.tar.gz: 43765dbe89dcac2771437b51d74395db217f266f0c67a514683f8a3f3649c04f
3
+ metadata.gz: 167575ff368c6952598431b5dfc8e262746a5ff645c0e18900d3126f1f8472a3
4
+ data.tar.gz: 8e3fee7b5b4996401b7c6201b6b144589f0ddadf00dbfcd73a5762fc53261db3
5
5
  SHA512:
6
- metadata.gz: 76b42ea50341efa8ddd79a0c92939bbfa60e9106d5e5862ea40a2ae4f327994d7f3f6bee594175728a6abdcaaade057fbf87888c43dd92782c62a5baec89b2da
7
- data.tar.gz: 8ac8d05651fd79b96be8ed1a3f57e04bf28effb8305e90865ac89b945d22c32c608c98f10cf38f8063363e40f8ad75a33f73106ed5f7c893732d927762d06708
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
- include strong_parameters_from_api
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
- class Api::V1::Scaffolding::CompletelyConcrete::TangibleThingsController < Api::V1::ApplicationController
2
- account_load_and_authorize_resource :tangible_thing, through: :absolutely_abstract_creative_concept, through_association: :completely_concrete_tangible_things
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
- # GET /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/tangible_things
5
- def index
6
- end
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
- # GET /api/v1/scaffolding/completely_concrete/tangible_things/:id
9
- def show
10
- end
13
+ # GET /api/v1/scaffolding/completely_concrete/tangible_things/:id
14
+ def show
15
+ end
11
16
 
12
- # POST /api/v1/scaffolding/absolutely_abstract/creative_concepts/:absolutely_abstract_creative_concept_id/completely_concrete/tangible_things
13
- def create
14
- if @tangible_thing.save
15
- render :show, status: :created, location: [:api, :v1, @tangible_thing]
16
- else
17
- render json: @tangible_thing.errors, status: :unprocessable_entity
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
- # PATCH/PUT /api/v1/scaffolding/completely_concrete/tangible_things/:id
22
- def update
23
- if @tangible_thing.update(tangible_thing_params)
24
- render :show
25
- else
26
- render json: @tangible_thing.errors, status: :unprocessable_entity
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
- # DELETE /api/v1/scaffolding/completely_concrete/tangible_things/:id
31
- def destroy
32
- @tangible_thing.destroy
33
- end
35
+ # DELETE /api/v1/scaffolding/completely_concrete/tangible_things/:id
36
+ def destroy
37
+ @tangible_thing.destroy
38
+ end
34
39
 
35
- private
40
+ private
36
41
 
37
- module StrongParameters
38
- # Only allow a list of trusted parameters through.
39
- def tangible_thing_params
40
- strong_params = params.require(:scaffolding_completely_concrete_tangible_thing).permit(
41
- *permitted_fields,
42
- # 🚅 skip this section when scaffolding.
43
- :text_field_value,
44
- :action_text_value,
45
- :boolean_button_value,
46
- :button_value,
47
- :color_picker_value,
48
- :cloudinary_image_value,
49
- :date_field_value,
50
- :date_and_time_field_value,
51
- :date_and_time_field_value_time_zone,
52
- :email_field_value,
53
- :file_field_value,
54
- :file_field_value_removal,
55
- :option_value,
56
- :password_field_value,
57
- :phone_field_value,
58
- :super_select_value,
59
- :text_area_value,
60
- # 🚅 stop any skipping we're doing now.
61
- # 🚅 super scaffolding will insert new fields above this line.
62
- *permitted_arrays,
63
- # 🚅 skip this section when scaffolding.
64
- multiple_button_values: [],
65
- multiple_option_values: [],
66
- multiple_super_select_values: []
67
- # 🚅 stop any skipping we're doing now.
68
- # 🚅 super scaffolding will insert new arrays above this line.
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
- process_params(strong_params)
76
+ process_params(strong_params)
72
77
 
73
- strong_params
78
+ strong_params
79
+ end
74
80
  end
75
- end
76
81
 
77
- include StrongParameters
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
- # TODO I don't know why if I just call `yield` I get duplicate content on the page.
5
- tag.div do
6
- yield
7
- end
10
+ yield
8
11
  end
9
12
  end
10
13
  end
@@ -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
- <% with_attribute_settings object: creative_concept do %>
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.accessible_by(current_ability), hide_back: true %>
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
- <% tangible_things = tangible_things.order(:id) unless has_order?(tangible_things) %>
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
- <%= updates_for context, collection do %>
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
- <% with_attribute_settings object: tangible_thing do %>
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>
@@ -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 %>
@@ -20,3 +20,5 @@ json.extract! tangible_thing,
20
20
  # 🚅 super scaffolding will insert new fields above this line.
21
21
  :created_at,
22
22
  :updated_at
23
+
24
+ # 🚅 super scaffolding will insert file-related logic above this line.
@@ -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:text body:text"
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:string url:text"
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:text body:text"
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:text path:text --sortable"
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.open_file_or_link("http://light.pinsupreme.com/icon_fonts_themefy.html")
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:"
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module SuperScaffolding
3
- VERSION = "1.1.14"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -20,6 +20,11 @@ module TerminalCommands
20
20
  os == linux
21
21
  end
22
22
 
23
+ def self.can_open?
24
+ (TerminalCommands.macosx? && `which open`.present?) ||
25
+ (TerminalCommands.linux? && `which xdg-open`.present?)
26
+ end
27
+
23
28
  def self.macosx
24
29
  "darwin"
25
30
  end
@@ -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+/.match?(line)
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
- "string"
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/_index.html.erb", field_content.strip, ERB_NEW_FIELDS_HOOK, prepend: true)
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
- 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)
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
- # TODO Get this working again.
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
- # TODO Get this working again.
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 = "# @#{child.underscore}.#{name} = Rack::Test::UploadedFile.new(\"test/support/foo.txt\")"
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 HAS_ONE_HOOK.
1244
- # We move the string here so it's right above the HAS_ONE_HOOK.
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
- model_without_attached_hook = model_contents.reject.each { |line| line.include?("has_one_attached :#{name}") }
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
- scaffold_add_line_to_file("./app/models/scaffolding/completely_concrete/tangible_thing.rb", "has_one_attached :#{name}", HAS_ONE_HOOK, prepend: true)
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
- code_for_child_on_parent_show_page || "<%= render 'account/scaffolding/completely_concrete/tangible_things/index', tangible_things: @creative_concept.completely_concrete_tangible_things, hide_back: true %>",
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
- rescue => e
1470
- puts "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/ .".send(:yellow)
1471
- raise e
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
- rescue => e
1481
- puts "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/ .".send(:yellow)
1482
- raise e
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 (TerminalCommands.macosx? && `which open`.present?) || TerminalCommands.linux?
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.1.14
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-16 00:00:00.000000000 Z
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