From d4759bccaa1efffb0b62db760fe2cc032888bc34 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Tue, 4 Jun 2024 15:44:38 -0500 Subject: [PATCH 01/12] wip --- .../scaffolders/join_model_scaffolder.rb | 37 +++++++++++++++---- .../lib/scaffolding/transformer.rb | 5 ++- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index db929e6ad..d3e9f9dd6 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -33,35 +33,56 @@ def run check_class_name_for_namespace_conflict(child) primary_parent = argv[1].split("class_name=").last.split(",").first.split("}").first + primary_parent_attribute_name = argv[1].split("{").first.delete_suffix("_id") + secondary_parent = argv[2].split("class_name=").last.split(",").first.split("}").first + secondary_parent_attribute_name = argv[2].split("{").first.delete_suffix("_id") # There should only be two attributes. attributes = [argv[1], argv[2]] - unless @options["skip-migration-generation"] - attributes_without_options = attributes.map { |attribute| attribute.gsub(/{.*}$/, "") } - attributes_without_id = attributes_without_options.map { |attribute| attribute.delete_suffix("_id") } - attributes_with_references = attributes_without_id.map { |attribute| attribute + ":references" } + attributes_without_options = attributes.map { |attribute| attribute.gsub(/{.*}$/, "") } + attributes_without_id = attributes_without_options.map { |attribute| attribute.delete_suffix("_id") } + attributes_with_references = attributes_without_id.map { |attribute| attribute + ":references" } + unless @options["skip-migration-generation"] generation_command = "bin/rails generate model #{child} #{attributes_with_references.join(" ")}" puts "Generating model with '#{generation_command}'".green `#{generation_command}` + + string_to_replace = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: true" + string_to_replace_with = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: { to_table: #{primary_parent.tableize} }" + + puts "need to replace" + puts string_to_replace + puts "with" + puts string_to_replace_with + + string_to_replace = "t.references :#{secondary_parent_attribute_name}, null: false, foreign_key: true" + string_to_replace_with = "t.references :#{secondary_parent_attribute_name}, null: false, foreign_key: { to_table: #{secondary_parent.tableize} }" + + puts "need to replace" + puts string_to_replace + puts "with" + puts string_to_replace_with end # Pretend we're doing a `super_select` scaffolding because it will do the correct thing. attributes = attributes.map { |attribute| attribute.gsub("{", ":super_select{") } attributes = attributes.map { |attribute| attribute.gsub("}", ",required}") } - transformer = Scaffolding::Transformer.new(child, [primary_parent], @options) + transformer = Scaffolding::Transformer.new(child, [primary_parent], @options, primary_parent_attribute_name) # We need this transformer to reflect on the class names _just_ between e.g. `Project` and `Projects::Tag`, without the join model. - has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options) + has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options, primary_parent_attribute_name) # We need this transformer to reflect on the association between `Projects::Tag` and `Projects::AppliedTag` backwards. - inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options) + inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options, secondary_parent_attribute_name) # We need this transformer to reflect on the class names _just_ between e.g. `Projects::Tag` and `Project`, without the join model. - inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options) + inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options, secondary_parent_attribute_name) + + debugger # However, for the first attribute, we actually don't need the scope validator (and can't really implement it). attributes[0] = attributes[0].gsub("}", ",unscoped}") diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index e8c8640c1..53772096b 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -5,7 +5,7 @@ require "scaffolding/attribute" class Scaffolding::Transformer - attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find + attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find, :attribute_name def update_models_abstract_class end @@ -37,7 +37,7 @@ def no_parent? def update_action_models_abstract_class(targets_n) end - def initialize(child, parents, cli_options = {}) + def initialize(child, parents, cli_options = {}, attribute_name = parents.first.underscore) self.child = child self.parent = parents.first self.parents = parents @@ -45,6 +45,7 @@ def initialize(child, parents, cli_options = {}) self.class_names_transformer = Scaffolding::ClassNamesTransformer.new(child, parent, namespace) self.cli_options = cli_options self.additional_steps = [] + self.attribute_name = attribute_name end RUBY_NEW_FIELDS_PROCESSING_HOOK = "# 🚅 super scaffolding will insert processing for new fields above this line." From d0465a5cff15fba9a46c917499b905d7340b0446 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Wed, 5 Jun 2024 16:02:06 -0500 Subject: [PATCH 02/12] more wip --- .../scaffolders/join_model_scaffolder.rb | 15 +++++++++------ .../lib/scaffolding/class_names_transformer.rb | 8 +++++--- .../lib/scaffolding/transformer.rb | 18 +++++++++++++----- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index d3e9f9dd6..fe1b769ca 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -30,6 +30,8 @@ def run end child = argv[0] + child_attribute_name = child.underscore.tr("/", "_") + check_class_name_for_namespace_conflict(child) primary_parent = argv[1].split("class_name=").last.split(",").first.split("}").first @@ -50,6 +52,9 @@ def run puts "Generating model with '#{generation_command}'".green `#{generation_command}` + # TODO: Maybe this should go in a transformer + # TODO: Actually manipulate the migration + string_to_replace = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: true" string_to_replace_with = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: { to_table: #{primary_parent.tableize} }" @@ -71,18 +76,16 @@ def run attributes = attributes.map { |attribute| attribute.gsub("{", ":super_select{") } attributes = attributes.map { |attribute| attribute.gsub("}", ",required}") } - transformer = Scaffolding::Transformer.new(child, [primary_parent], @options, primary_parent_attribute_name) + transformer = Scaffolding::Transformer.new(child, [primary_parent], @options) # We need this transformer to reflect on the class names _just_ between e.g. `Project` and `Projects::Tag`, without the join model. - has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options, primary_parent_attribute_name) + has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options, child_attribute_name, secondary_parent_attribute_name) # We need this transformer to reflect on the association between `Projects::Tag` and `Projects::AppliedTag` backwards. - inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options, secondary_parent_attribute_name) + inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options) # We need this transformer to reflect on the class names _just_ between e.g. `Projects::Tag` and `Project`, without the join model. - inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options, secondary_parent_attribute_name) - - debugger + inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options, child_attribute_name, primary_parent_attribute_name) # However, for the first attribute, we actually don't need the scope validator (and can't really implement it). attributes[0] = attributes[0].gsub("}", ",unscoped}") diff --git a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb index 821e4f712..45037e41d 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb @@ -1,10 +1,12 @@ class Scaffolding::ClassNamesTransformer - attr_accessor :child, :parent, :namespace + attr_accessor :child, :parent, :namespace, :child_attribute_name, :parent_attribute_name - def initialize(child, parent, namespace = "account") + def initialize(child, parent, namespace = "account", child_attribute_name, parent_attribute_name) self.child = child self.parent = parent self.namespace = namespace + self.child_attribute_name = child_attribute_name + self.parent_attribute_name = parent_attribute_name end def belongs_to_needs_class_definition? @@ -171,7 +173,7 @@ def replacement_for(string) when "absolutely_abstract_creative_concepts" parent_class_name_in_context.underscore.tr("/", "_").pluralize when "completely_concrete_tangible_things" - class_name_in_parent_context.underscore.tr("/", "_").pluralize + parent_attribute_name&.pluralize || class_name_in_parent_context.underscore.tr("/", "_").pluralize when "absolutely_abstract/creative_concepts" parent_class_name_in_context.underscore.pluralize when "completely_concrete/tangible_things" diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 53772096b..da0fd3531 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -5,7 +5,7 @@ require "scaffolding/attribute" class Scaffolding::Transformer - attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find, :attribute_name + attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find, :child_attribute_name, :parent_attribute_name def update_models_abstract_class end @@ -37,15 +37,16 @@ def no_parent? def update_action_models_abstract_class(targets_n) end - def initialize(child, parents, cli_options = {}, attribute_name = parents.first.underscore) + def initialize(child, parents, cli_options = {}, child_attribute_name = nil, parent_attribute_name = nil) self.child = child self.parent = parents.first self.parents = parents self.namespace = cli_options["namespace"] || "account" - self.class_names_transformer = Scaffolding::ClassNamesTransformer.new(child, parent, namespace) + self.class_names_transformer = Scaffolding::ClassNamesTransformer.new(child, parent, namespace, child_attribute_name, parent_attribute_name) self.cli_options = cli_options self.additional_steps = [] - self.attribute_name = attribute_name + self.child_attribute_name = child_attribute_name + self.parent_attribute_name = parent_attribute_name end RUBY_NEW_FIELDS_PROCESSING_HOOK = "# 🚅 super scaffolding will insert processing for new fields above this line." @@ -606,7 +607,14 @@ def add_has_many_association def add_has_many_through_associations(has_many_through_transformer) has_many_association = add_has_many_association - has_many_through_string = has_many_through_transformer.transform_string("has_many :completely_concrete_tangible_things, through: :$HAS_MANY_ASSOCIATION") + has_many_through_parts = [ + "has_many :completely_concrete_tangible_things", + "through: :$HAS_MANY_ASSOCIATION" + ] + if has_many_through_transformer.parent_attribute_name.present? + has_many_through_parts << "class_name: \"Scaffolding::CompletelyConcrete::TangibleThing\"" + end + has_many_through_string = has_many_through_transformer.transform_string(has_many_through_parts.join(", ")) has_many_through_string.gsub!("$HAS_MANY_ASSOCIATION", has_many_association) add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) end From 050fd2940a93f21bd3f1c4df3c05cd78dd95932b Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Wed, 5 Jun 2024 16:12:54 -0500 Subject: [PATCH 03/12] allow these to be nil --- .../lib/scaffolding/class_names_transformer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb index 45037e41d..4be8b1e77 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb @@ -1,7 +1,7 @@ class Scaffolding::ClassNamesTransformer attr_accessor :child, :parent, :namespace, :child_attribute_name, :parent_attribute_name - def initialize(child, parent, namespace = "account", child_attribute_name, parent_attribute_name) + def initialize(child, parent, namespace = "account", child_attribute_name = nil, parent_attribute_name = nil) self.child = child self.parent = parent self.namespace = namespace From 56397e093d4f4ebbb729501b4d99b71990f6cc1e Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Wed, 5 Jun 2024 16:30:32 -0500 Subject: [PATCH 04/12] looks like the migration is already handled, yay --- .../scaffolders/join_model_scaffolder.rb | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index fe1b769ca..5d5431e97 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -43,33 +43,14 @@ def run # There should only be two attributes. attributes = [argv[1], argv[2]] - attributes_without_options = attributes.map { |attribute| attribute.gsub(/{.*}$/, "") } - attributes_without_id = attributes_without_options.map { |attribute| attribute.delete_suffix("_id") } - attributes_with_references = attributes_without_id.map { |attribute| attribute + ":references" } - unless @options["skip-migration-generation"] + attributes_without_options = attributes.map { |attribute| attribute.gsub(/{.*}$/, "") } + attributes_without_id = attributes_without_options.map { |attribute| attribute.delete_suffix("_id") } + attributes_with_references = attributes_without_id.map { |attribute| attribute + ":references" } + generation_command = "bin/rails generate model #{child} #{attributes_with_references.join(" ")}" puts "Generating model with '#{generation_command}'".green `#{generation_command}` - - # TODO: Maybe this should go in a transformer - # TODO: Actually manipulate the migration - - string_to_replace = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: true" - string_to_replace_with = "t.references :#{primary_parent_attribute_name}, null: false, foreign_key: { to_table: #{primary_parent.tableize} }" - - puts "need to replace" - puts string_to_replace - puts "with" - puts string_to_replace_with - - string_to_replace = "t.references :#{secondary_parent_attribute_name}, null: false, foreign_key: true" - string_to_replace_with = "t.references :#{secondary_parent_attribute_name}, null: false, foreign_key: { to_table: #{secondary_parent.tableize} }" - - puts "need to replace" - puts string_to_replace - puts "with" - puts string_to_replace_with end # Pretend we're doing a `super_select` scaffolding because it will do the correct thing. From a1df68c54034827a1393b15769542df7694868c3 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 6 Jun 2024 11:51:24 -0500 Subject: [PATCH 05/12] This may be a better approach --- .../scaffolders/join_model_scaffolder.rb | 6 ++++-- .../lib/scaffolding/attribute.rb | 8 ++++++++ .../lib/scaffolding/class_names_transformer.rb | 2 +- .../lib/scaffolding/transformer.rb | 16 +++++++++++++--- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index 5d5431e97..143c7bc8b 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -36,9 +36,11 @@ def run primary_parent = argv[1].split("class_name=").last.split(",").first.split("}").first primary_parent_attribute_name = argv[1].split("{").first.delete_suffix("_id") + primary_parent_attribute = argv[1] secondary_parent = argv[2].split("class_name=").last.split(",").first.split("}").first secondary_parent_attribute_name = argv[2].split("{").first.delete_suffix("_id") + secondary_parent_attribute = argv[2] # There should only be two attributes. attributes = [argv[1], argv[2]] @@ -87,8 +89,8 @@ def run transformer.suppress_could_not_find = false # Add the `has_many ... through:` association in both directions. - transformer.add_has_many_through_associations(has_many_through_transformer) - inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer) + transformer.add_has_many_through_associations(has_many_through_transformer, attributes[1]) + inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer, attributes[0]) additional_steps = (transformer.additional_steps + has_many_through_transformer.additional_steps + inverse_transformer.additional_steps + inverse_has_many_through_transformer.additional_steps).uniq diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index c027c9991..af984758e 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -58,6 +58,14 @@ def association_class_name name.split("_id").first end + def association_table_name + association_class_name.tableize + end + + def class_name_matches? + self.name_without_id.tableize == self.options[:class_name].tableize.tr("/", "_") + end + def is_association? is_belongs_to? || is_has_many? end diff --git a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb index 4be8b1e77..96127dce4 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb @@ -173,7 +173,7 @@ def replacement_for(string) when "absolutely_abstract_creative_concepts" parent_class_name_in_context.underscore.tr("/", "_").pluralize when "completely_concrete_tangible_things" - parent_attribute_name&.pluralize || class_name_in_parent_context.underscore.tr("/", "_").pluralize + class_name_in_parent_context.underscore.tr("/", "_").pluralize when "absolutely_abstract/creative_concepts" parent_class_name_in_context.underscore.pluralize when "completely_concrete/tangible_things" diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index da0fd3531..9d3afc13d 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -605,17 +605,25 @@ def add_has_many_association has_many_string.split(",").first.split(":").last end - def add_has_many_through_associations(has_many_through_transformer) + def add_has_many_through_associations(has_many_through_transformer, attribute_definition) + + # TODO: Do we need a real index here, instead of 0? + attribute = Scaffolding::Attribute.new(attribute_definition, :crud_field, 0) has_many_association = add_has_many_association has_many_through_parts = [ "has_many :completely_concrete_tangible_things", "through: :$HAS_MANY_ASSOCIATION" ] - if has_many_through_transformer.parent_attribute_name.present? + + unless attribute.class_name_matches? has_many_through_parts << "class_name: \"Scaffolding::CompletelyConcrete::TangibleThing\"" end has_many_through_string = has_many_through_transformer.transform_string(has_many_through_parts.join(", ")) has_many_through_string.gsub!("$HAS_MANY_ASSOCIATION", has_many_association) + unless attribute.class_name_matches? + #debugger + has_many_through_string.gsub!("has_many :#{attribute.association_table_name}" ,"has_many :#{attribute.name_without_id.tableize}") + end add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) end @@ -639,6 +647,7 @@ def add_attributes_to_various_views(attributes, scaffolding_options = {}) # add attributes to various views. attributes.each_with_index do |attribute_definition, index| + #debugger attribute = Scaffolding::Attribute.new(attribute_definition, scaffolding_options[:type], index) if attribute.is_first_attribute? && ["trix_editor", "ckeditor", "text_area"].include?(attribute.type) @@ -1151,9 +1160,10 @@ def set_default_#{attribute.name} end - class_name_matches = attribute.name_without_id.tableize == attribute.options[:class_name].tableize.tr("/", "_") + class_name_matches = attribute.class_name_matches? # but also, if namespaces are involved, just don't... + # TODO: Should this also be extracted to the attribute.class_name_matches? method? if attribute.options[:class_name].include?("::") class_name_matches = false end From 672ccca13d37a01a5c22ea943b65dad97846ab2c Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 6 Jun 2024 12:00:34 -0500 Subject: [PATCH 06/12] Clean up some unused stuff --- .../scaffolders/join_model_scaffolder.rb | 13 ++++--------- .../lib/scaffolding/class_names_transformer.rb | 6 ++---- .../lib/scaffolding/transformer.rb | 14 ++++++++------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index 143c7bc8b..1686bf194 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -30,17 +30,10 @@ def run end child = argv[0] - child_attribute_name = child.underscore.tr("/", "_") check_class_name_for_namespace_conflict(child) - primary_parent = argv[1].split("class_name=").last.split(",").first.split("}").first - primary_parent_attribute_name = argv[1].split("{").first.delete_suffix("_id") - primary_parent_attribute = argv[1] - secondary_parent = argv[2].split("class_name=").last.split(",").first.split("}").first - secondary_parent_attribute_name = argv[2].split("{").first.delete_suffix("_id") - secondary_parent_attribute = argv[2] # There should only be two attributes. attributes = [argv[1], argv[2]] @@ -62,13 +55,13 @@ def run transformer = Scaffolding::Transformer.new(child, [primary_parent], @options) # We need this transformer to reflect on the class names _just_ between e.g. `Project` and `Projects::Tag`, without the join model. - has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options, child_attribute_name, secondary_parent_attribute_name) + has_many_through_transformer = Scaffolding::Transformer.new(secondary_parent, [primary_parent], @options) # We need this transformer to reflect on the association between `Projects::Tag` and `Projects::AppliedTag` backwards. inverse_transformer = Scaffolding::Transformer.new(child, [secondary_parent], @options) # We need this transformer to reflect on the class names _just_ between e.g. `Projects::Tag` and `Project`, without the join model. - inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options, child_attribute_name, primary_parent_attribute_name) + inverse_has_many_through_transformer = Scaffolding::Transformer.new(primary_parent, [secondary_parent], @options) # However, for the first attribute, we actually don't need the scope validator (and can't really implement it). attributes[0] = attributes[0].gsub("}", ",unscoped}") @@ -89,6 +82,8 @@ def run transformer.suppress_could_not_find = false # Add the `has_many ... through:` association in both directions. + # We pass the "opposing" attribute so that both the association name and the + # class name get wired up correctly transformer.add_has_many_through_associations(has_many_through_transformer, attributes[1]) inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer, attributes[0]) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb index 96127dce4..821e4f712 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/class_names_transformer.rb @@ -1,12 +1,10 @@ class Scaffolding::ClassNamesTransformer - attr_accessor :child, :parent, :namespace, :child_attribute_name, :parent_attribute_name + attr_accessor :child, :parent, :namespace - def initialize(child, parent, namespace = "account", child_attribute_name = nil, parent_attribute_name = nil) + def initialize(child, parent, namespace = "account") self.child = child self.parent = parent self.namespace = namespace - self.child_attribute_name = child_attribute_name - self.parent_attribute_name = parent_attribute_name end def belongs_to_needs_class_definition? diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 9d3afc13d..3b41bf30c 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -5,7 +5,7 @@ require "scaffolding/attribute" class Scaffolding::Transformer - attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find, :child_attribute_name, :parent_attribute_name + attr_accessor :child, :parent, :parents, :class_names_transformer, :cli_options, :additional_steps, :namespace, :suppress_could_not_find def update_models_abstract_class end @@ -37,16 +37,14 @@ def no_parent? def update_action_models_abstract_class(targets_n) end - def initialize(child, parents, cli_options = {}, child_attribute_name = nil, parent_attribute_name = nil) + def initialize(child, parents, cli_options = {}) self.child = child self.parent = parents.first self.parents = parents self.namespace = cli_options["namespace"] || "account" - self.class_names_transformer = Scaffolding::ClassNamesTransformer.new(child, parent, namespace, child_attribute_name, parent_attribute_name) + self.class_names_transformer = Scaffolding::ClassNamesTransformer.new(child, parent, namespace) self.cli_options = cli_options self.additional_steps = [] - self.child_attribute_name = child_attribute_name - self.parent_attribute_name = parent_attribute_name end RUBY_NEW_FIELDS_PROCESSING_HOOK = "# 🚅 super scaffolding will insert processing for new fields above this line." @@ -621,7 +619,11 @@ def add_has_many_through_associations(has_many_through_transformer, attribute_de has_many_through_string = has_many_through_transformer.transform_string(has_many_through_parts.join(", ")) has_many_through_string.gsub!("$HAS_MANY_ASSOCIATION", has_many_association) unless attribute.class_name_matches? - #debugger + # This handles the case where you're generating a join model where you want association names + # to be different than the class name, so it'll transform something like this: + # has_many :memberships, through: :assignments, class_name: "Membership" + # into something like this: + # has_many :assigned_to_memberships, through: :assignments, class_name: "Membership" has_many_through_string.gsub!("has_many :#{attribute.association_table_name}" ,"has_many :#{attribute.name_without_id.tableize}") end add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) From 88f57093908229cf89cb233d595a52ed7de476f4 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 6 Jun 2024 12:09:50 -0500 Subject: [PATCH 07/12] Some clean up --- .../scaffolders/join_model_scaffolder.rb | 5 +++-- .../lib/scaffolding/attribute.rb | 6 ++++++ .../lib/scaffolding/transformer.rb | 14 +++----------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb index 1686bf194..a5012f76c 100644 --- a/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb +++ b/bullet_train-super_scaffolding/lib/bullet_train/super_scaffolding/scaffolders/join_model_scaffolder.rb @@ -30,8 +30,8 @@ def run end child = argv[0] - check_class_name_for_namespace_conflict(child) + primary_parent = argv[1].split("class_name=").last.split(",").first.split("}").first secondary_parent = argv[2].split("class_name=").last.split(",").first.split("}").first @@ -83,7 +83,8 @@ def run # Add the `has_many ... through:` association in both directions. # We pass the "opposing" attribute so that both the association name and the - # class name get wired up correctly + # class name get wired up correctly in cases where they don't match. For instance + # if you want an `assigned_to_membership` relationship to the `memberships` table. transformer.add_has_many_through_associations(has_many_through_transformer, attributes[1]) inverse_transformer.add_has_many_through_associations(inverse_has_many_through_transformer, attributes[0]) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index af984758e..bd1142395 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -63,6 +63,12 @@ def association_table_name end def class_name_matches? + # if namespaces are involved, just don't... + # TODO: I'm not entirely sure that extracting this conditional was the right thing to do. + # Are there scenarios where we want to assume a match even when namespaces are involved? + if self.options[:class_name].include?("::") + return false + end self.name_without_id.tableize == self.options[:class_name].tableize.tr("/", "_") end diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 3b41bf30c..830fa9ac2 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -1162,16 +1162,8 @@ def set_default_#{attribute.name} end - class_name_matches = attribute.class_name_matches? - - # but also, if namespaces are involved, just don't... - # TODO: Should this also be extracted to the attribute.class_name_matches? method? - if attribute.options[:class_name].include?("::") - class_name_matches = false - end - # unless the table name matches the association name. - unless class_name_matches + unless attribute.class_name_matches? if migration_file_name # There are two forms this association creation can take. replace_in_file(migration_file_name, "foreign_key: true", "foreign_key: {to_table: \"#{attribute.options[:class_name].tableize.tr("/", "_")}\"}", /t\.references :#{attribute.name_without_id}/) @@ -1188,7 +1180,7 @@ def set_default_#{attribute.name} # if the `belongs_to` is already there from `rails g model`.. scaffold_replace_line_in_file( "./app/models/scaffolding/completely_concrete/tangible_thing.rb", - class_name_matches ? + attribute.class_name_matches? ? "belongs_to :#{attribute.name_without_id}#{optional_line}" : "belongs_to :#{attribute.name_without_id}, class_name: \"#{attribute.options[:class_name]}\"#{optional_line}", "belongs_to :#{attribute.name_without_id}" @@ -1198,7 +1190,7 @@ def set_default_#{attribute.name} # however, this won't do anything if the association is already there. scaffold_add_line_to_file( "./app/models/scaffolding/completely_concrete/tangible_thing.rb", - class_name_matches ? + attribute.class_name_matches? ? "belongs_to :#{attribute.name_without_id}#{optional_line}" : "belongs_to :#{attribute.name_without_id}, class_name: \"#{attribute.options[:class_name]}\"#{optional_line}", BELONGS_TO_HOOK, From e62a33a73b4c79dae8daf7767abddffe26ea8576 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 6 Jun 2024 12:40:18 -0500 Subject: [PATCH 08/12] clean up --- bullet_train-super_scaffolding/lib/scaffolding/attribute.rb | 2 +- bullet_train-super_scaffolding/lib/scaffolding/transformer.rb | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index bd1142395..a99869342 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -58,7 +58,7 @@ def association_class_name name.split("_id").first end - def association_table_name + def association_name association_class_name.tableize end diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 830fa9ac2..8c36a9779 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -624,7 +624,7 @@ def add_has_many_through_associations(has_many_through_transformer, attribute_de # has_many :memberships, through: :assignments, class_name: "Membership" # into something like this: # has_many :assigned_to_memberships, through: :assignments, class_name: "Membership" - has_many_through_string.gsub!("has_many :#{attribute.association_table_name}" ,"has_many :#{attribute.name_without_id.tableize}") + has_many_through_string.gsub!("has_many :#{attribute.association_name}" ,"has_many :#{attribute.name_without_id.tableize}") end add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) end @@ -649,7 +649,6 @@ def add_attributes_to_various_views(attributes, scaffolding_options = {}) # add attributes to various views. attributes.each_with_index do |attribute_definition, index| - #debugger attribute = Scaffolding::Attribute.new(attribute_definition, scaffolding_options[:type], index) if attribute.is_first_attribute? && ["trix_editor", "ckeditor", "text_area"].include?(attribute.type) From 65abca62f180bab295201a20fa41c6564239403e Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 6 Jun 2024 12:43:28 -0500 Subject: [PATCH 09/12] linter --- bullet_train-super_scaffolding/lib/scaffolding/attribute.rb | 4 ++-- bullet_train-super_scaffolding/lib/scaffolding/transformer.rb | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index a99869342..a00bafc5a 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -66,10 +66,10 @@ def class_name_matches? # if namespaces are involved, just don't... # TODO: I'm not entirely sure that extracting this conditional was the right thing to do. # Are there scenarios where we want to assume a match even when namespaces are involved? - if self.options[:class_name].include?("::") + if options[:class_name].include?("::") return false end - self.name_without_id.tableize == self.options[:class_name].tableize.tr("/", "_") + name_without_id.tableize == options[:class_name].tableize.tr("/", "_") end def is_association? diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 8c36a9779..9cd896090 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -604,8 +604,6 @@ def add_has_many_association end def add_has_many_through_associations(has_many_through_transformer, attribute_definition) - - # TODO: Do we need a real index here, instead of 0? attribute = Scaffolding::Attribute.new(attribute_definition, :crud_field, 0) has_many_association = add_has_many_association has_many_through_parts = [ @@ -624,7 +622,7 @@ def add_has_many_through_associations(has_many_through_transformer, attribute_de # has_many :memberships, through: :assignments, class_name: "Membership" # into something like this: # has_many :assigned_to_memberships, through: :assignments, class_name: "Membership" - has_many_through_string.gsub!("has_many :#{attribute.association_name}" ,"has_many :#{attribute.name_without_id.tableize}") + has_many_through_string.gsub!("has_many :#{attribute.association_name}", "has_many :#{attribute.name_without_id.tableize}") end add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) end From 52dc390747d48da90f9700511fd399b1ca30ae68 Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 13 Jun 2024 15:06:54 -0500 Subject: [PATCH 10/12] Account for when it should be singular --- bullet_train-super_scaffolding/lib/scaffolding/attribute.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index a00bafc5a..62057c415 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -59,7 +59,8 @@ def association_class_name end def association_name - association_class_name.tableize + plural_association_name = association_class_name.tableize + is_has_many? plural_association_name : plural_association_name.singularize end def class_name_matches? From ee2cb701b0dc75ff99ee3a9df54a95dbffb78daf Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 13 Jun 2024 15:11:05 -0500 Subject: [PATCH 11/12] Oops --- bullet_train-super_scaffolding/lib/scaffolding/attribute.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index 62057c415..e5270008f 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -60,7 +60,7 @@ def association_class_name def association_name plural_association_name = association_class_name.tableize - is_has_many? plural_association_name : plural_association_name.singularize + is_has_many? ? plural_association_name : plural_association_name.singularize end def class_name_matches? From 15c41de9ade5558801e3fa0f90c22ea14fcd10bb Mon Sep 17 00:00:00 2001 From: Jeremy Green Date: Thu, 13 Jun 2024 15:37:14 -0500 Subject: [PATCH 12/12] Fix --- bullet_train-super_scaffolding/lib/scaffolding/attribute.rb | 5 ++--- .../lib/scaffolding/transformer.rb | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb index e5270008f..303ec9b99 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/attribute.rb @@ -58,9 +58,8 @@ def association_class_name name.split("_id").first end - def association_name - plural_association_name = association_class_name.tableize - is_has_many? ? plural_association_name : plural_association_name.singularize + def plural_association_name + association_class_name.tableize end def class_name_matches? diff --git a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb index 9cd896090..96b882cd6 100644 --- a/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb +++ b/bullet_train-super_scaffolding/lib/scaffolding/transformer.rb @@ -622,7 +622,7 @@ def add_has_many_through_associations(has_many_through_transformer, attribute_de # has_many :memberships, through: :assignments, class_name: "Membership" # into something like this: # has_many :assigned_to_memberships, through: :assignments, class_name: "Membership" - has_many_through_string.gsub!("has_many :#{attribute.association_name}", "has_many :#{attribute.name_without_id.tableize}") + has_many_through_string.gsub!("has_many :#{attribute.plural_association_name}", "has_many :#{attribute.name_without_id.tableize}") end add_line_to_file(transform_string("./app/models/scaffolding/absolutely_abstract/creative_concept.rb"), has_many_through_string, HAS_MANY_HOOK, prepend: true) end