lib/scaffolding/transformer.rb in bullet_train-super_scaffolding-1.2.10 vs lib/scaffolding/transformer.rb in bullet_train-super_scaffolding-1.2.11
- old
+ new
@@ -21,10 +21,20 @@
def last_joinable_parent
"Team"
end
+ def top_level_model?
+ parent == "Team" || no_parent?
+ end
+
+ # We write an explicit method here so we know we
+ # aren't handling `parent` in this situation as `nil`.
+ def no_parent?
+ parent == "None"
+ end
+
def update_action_models_abstract_class(targets_n)
end
def initialize(child, parents, cli_options = {})
self.child = child
@@ -39,11 +49,13 @@
RUBY_NEW_FIELDS_PROCESSING_HOOK = "# 🚅 super scaffolding will insert processing for new fields above this line."
RUBY_NEW_ARRAYS_HOOK = "# 🚅 super scaffolding will insert new arrays above this line."
RUBY_NEW_FIELDS_HOOK = "# 🚅 super scaffolding will insert new fields above this line."
RUBY_ADDITIONAL_NEW_FIELDS_HOOK = "# 🚅 super scaffolding will also insert new fields above this line."
RUBY_EVEN_MORE_NEW_FIELDS_HOOK = "# 🚅 super scaffolding will additionally insert new fields above this line."
+ RUBY_NEW_API_VERSION_HOOK = "# 🚅 super scaffolding will insert new api versions above this line."
RUBY_FILES_HOOK = "# 🚅 super scaffolding will insert file-related logic above this line."
+ RUBY_FACTORY_SETUP_HOOK = "# 🚅 super scaffolding will insert factory setup in place of this line."
ERB_NEW_FIELDS_HOOK = "<%#{RUBY_NEW_FIELDS_HOOK} %>"
CONCERNS_HOOK = "# 🚅 add concerns above."
ATTR_ACCESSORS_HOOK = "# 🚅 add attribute accessors above."
BELONGS_TO_HOOK = "# 🚅 add belongs_to associations above."
HAS_MANY_HOOK = "# 🚅 add has_many associations above."
@@ -249,15 +261,10 @@
end
transformed_file_content.join
end
- # TODO I was running into an error in a downstream application where it couldn't find silence_logs? We should implement it in this package.
- def silence_logs?
- ENV["SILENCE_LOGS"].present?
- end
-
def scaffold_file(file, overrides: false)
transformed_file_content = get_transformed_file_content(file)
transformed_file_name = transform_string(file)
# Remove `_overrides` from the file name if we're sourcing from a local override folder.
@@ -288,10 +295,13 @@
puts "Proceeding to generate '#{transformed_directory_name}'."
end
Dir.foreach(resolve_template_path(directory)) do |file|
file = "#{directory}/#{file}"
+
+ next if file.match?("/_menu_item.html.erb") && !top_level_model?
+
unless File.directory?(resolve_template_path(file))
scaffold_file(file)
end
end
@@ -303,10 +313,13 @@
end
if override_path
Dir.foreach(override_path) do |file|
file = "#{directory}_overrides/#{file}"
+
+ next if file.match?("/_menu_item.html.erb") && !top_level_model?
+
unless File.directory?(resolve_template_path(file))
scaffold_file(file, overrides: true)
end
end
end
@@ -569,19 +582,19 @@
end
def add_has_many_association
has_many_line = ["has_many :completely_concrete_tangible_things"]
- # TODO I _think_ this is the right way to check for whether we need `class_name` to specify the name of the model.
- unless transform_string("completely_concrete_tangible_things").classify == child
+ # Specify the class name if the model is namespaced.
+ if child.match?("::")
has_many_line << "class_name: \"Scaffolding::CompletelyConcrete::TangibleThing\""
end
has_many_line << "dependent: :destroy"
- # TODO I _think_ this is the right way to check for whether we need `foreign_key` to specify the name of the model.
- unless transform_string("absolutely_abstract_creative_concept_id") == "#{parent.underscore}_id"
+ # Specify the foreign key if the parent is namespaced.
+ if parent.match?("::")
has_many_line << "foreign_key: :absolutely_abstract_creative_concept_id"
# And if we need `foreign_key`, we should also specify `inverse_of`.
has_many_line << "inverse_of: :absolutely_abstract_creative_concept"
end
@@ -912,11 +925,12 @@
if type == "password_field"
field_content.gsub!(/\s%>/, ", options: { password: true } %>")
end
- 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)
+ show_page_doesnt_exist = child == "User"
+ 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, suppress_could_not_find: show_page_doesnt_exist)
end
#
# INDEX TABLE
@@ -929,10 +943,24 @@
unless ["Team", "User"].include?(child)
scaffold_add_line_to_file("./app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb", field_content, "<%# 🚅 super scaffolding will insert new field headers above this line. %>", prepend: true)
end
+ # If these strings are the same, we get duplicate variable names in the _index.html.erb partial,
+ # so we account for that here. Run the Super Scaffolding test setup script and check the index partial
+ # of models with namespaced parents for reference (i.e. - Objective, Projects::Step).
+ transformed_abstract_str = transform_string("absolutely_abstract_creative_concept")
+ transformed_concept_str = transform_string("creative_concept")
+ transformed_file_name = transform_string("./app/views/account/scaffolding/completely_concrete/tangible_things/_index.html.erb")
+ if (transformed_abstract_str == transformed_concept_str) && File.exist?(transformed_file_name)
+ replace_in_file(
+ transformed_file_name,
+ "#{transformed_abstract_str} = @#{transformed_abstract_str} || @#{transformed_concept_str}",
+ "#{transformed_abstract_str} = @#{transformed_concept_str}"
+ )
+ end
+
table_cell_options = []
if first_table_cell
table_cell_options << "url: [:account, tangible_thing]"
end
@@ -1391,12 +1419,25 @@
# add user permissions.
add_ability_line_to_roles_yml
end
+ # Add factory setup in API controller test.
unless cli_options["skip-api"]
- scaffold_replace_line_in_file("./test/controllers/api/v1/scaffolding/completely_concrete/tangible_things_controller_test.rb", build_factory_setup.join("\n"), "# 🚅 super scaffolding will insert factory setup in place of this line.")
+ test_name = transform_string("./test/controllers/api/v1/scaffolding/completely_concrete/tangible_things_controller_test.rb")
+ test_lines = File.open(test_name).readlines
+
+ # Shift contents of controller test after skipping `unless scaffolding_things_disabled?` block.
+ class_block_index = Scaffolding::FileManipulator.find(test_lines, "class #{transform_string("Api::V1::Scaffolding::CompletelyConcrete::TangibleThingsControllerTest")}")
+ new_lines = Scaffolding::BlockManipulator.shift_block(lines: test_lines, block_start: test_lines[class_block_index], shift_contents_only: true)
+ Scaffolding::FileManipulator.write(test_name, new_lines)
+
+ # Ensure variables built with factories are indented properly.
+ factory_hook_index = Scaffolding::FileManipulator.find(new_lines, RUBY_FACTORY_SETUP_HOOK)
+ factory_hook_indentation = Scaffolding::BlockManipulator.indentation_of(factory_hook_index, new_lines)
+ indented_factory_lines = build_factory_setup.map { |line| "#{factory_hook_indentation}#{line}\n" }
+ scaffold_replace_line_in_file(test_name, indented_factory_lines.join, new_lines[factory_hook_index])
end
# add children to the show page of their parent.
unless cli_options["skip-parent"] || parent == "None"
scaffold_add_line_to_file(
@@ -1488,11 +1529,11 @@
File.write(routes_path, <<~RUBY)
collection_actions = [:index, :new, :create]
# 🚅 Don't remove this block, it will break Super Scaffolding.
- begin do
+ begin
namespace :#{routes_namespace} do
shallow do
resources :teams do
end
end
@@ -1503,15 +1544,39 @@
retry
end
begin
routes_manipulator.apply([routes_namespace])
- Scaffolding::FileManipulator.write("config/routes.rb", routes_manipulator.lines)
+ Scaffolding::FileManipulator.write(routes_path, routes_manipulator.lines)
rescue => _
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/ ."
end
+ # If we're using a custom namespace, we have to make sure the newly
+ # scaffolded routes are drawn in the `config/routes.rb` and API routes files.
+ if cli_options["namespace"]
+ draw_line = "draw \"#{routes_namespace}\""
+
+ [
+ "config/routes.rb",
+ "config/routes/api/#{BulletTrain::Api.current_version}.rb"
+ ].each do |routes_file|
+ original_lines = File.readlines(routes_file)
+
+ # Define which line we want to place the draw line under in the original routes files.
+ insert_line = if routes_file.match?("api")
+ draw_line = " #{draw_line}" # Add necessary indentation.
+ "namespace :v1 do"
+ else
+ "draw \"sidekiq\""
+ end
+
+ new_lines = Scaffolding::BlockManipulator.insert(draw_line, lines: original_lines, within: insert_line)
+ Scaffolding::FileManipulator.write(routes_file, new_lines)
+ end
+ end
+
unless cli_options["skip-api"]
begin
api_routes_manipulator = Scaffolding::RoutesFileManipulator.new("config/routes/api/#{BulletTrain::Api.current_version}.rb", child, parent, cli_options)
api_routes_manipulator.apply([BulletTrain::Api.current_version.to_sym])
Scaffolding::FileManipulator.write("config/routes/api/#{BulletTrain::Api.current_version}.rb", api_routes_manipulator.lines)
@@ -1521,10 +1586,10 @@
end
end
unless cli_options["skip-parent"]
- if parent == "Team" || parent == "None"
+ if top_level_model?
icon_name = nil
if cli_options["sidebar"].present?
icon_name = cli_options["sidebar"]
else
puts ""