Rethink how we check for namespaced `has_many` class names
gazayas opened this issue · comments
I've been looking into these TODOs from the Transformer, and on the surface they didn't seem too difficult, but the issue is definitely more complicated than first expected:
# 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
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"
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
The problem
The first block runs when Super Scaffolding Projects::Deliverable
within bundle exec test/bin/setup-super-scaffolding-system-test
. Here's the output we get when checking for the transformed string
pry(#<Scaffolding::Transformer>)> transform_string("completely_concrete_tangible_things")
=> "deliverables"
child
is Project::Deliverables
though, so although we should be getting projects_deliverables
, we get deliverables
so it's cutting off the namespace and will always add the class_name
option. It's technically adding it to the right place, but the check isn't entirely accurate.
Somewhat close solution
I ended up using the following:
[1] pry(#<Scaffolding::Transformer>)> child
=> "Projects::Deliverable"
[2] pry(#<Scaffolding::Transformer>)> parent
=> "Project"
[3] pry(#<Scaffolding::Transformer>)> transform_string("scaffolding_completely_concrete_tangible_things")
=> "projects_deliverables"
However, when classfying it, we just get this:
ProjectsDeliverable
We could somehow use a regexp to insert ::
in the proper places, but I feel like this still doesn't cover the core issue. I know we call class_name
when the database table has a different name than what we're working with, but I'm having trouble trying to flesh out what would be a good model setup to make sure this part runs as desired.
Questions
- What's an example model design we can refer to when working with this logic? In other words, what
rails g model
/Super Scaffolding combination is the most ideal to check this part of the code? - Do we want to skip namespaced models? Would it just be common sense that the database table would carry the same name as the
child
given in the Transformer?
Final thoughts
Our Super Scaffolding system tests have been working up until now with these unless
statements, but it would definitely be better to have a firm grasp on this part in case we run into any related problems in the future.
Still, it's not an easy one so I think it'll take me some time to work on it.
Although the main Super Scaffolding system test isn't failing, I noticed this output from the setup script and it seems to be related to the files we're trying to adjust around the TODOs in this issue:
Couldn't find 'app/views/account/deliverables/index.json.jbuilder'
Couldn't find 'app/views/account/deliverables/show.json.jbuilder'
Couldn't find 'app/views/account/deliverables/index.json.jbuilder'
Couldn't find 'app/views/account/deliverables/show.json.jbuilder'
I was just trying to resolve these earlier today, and found that using the following at the beginning of the transform_string
method retrieved the proper string:
path_without_scaffolding_hook = "account/completely_concrete/tangible_things"
path_with_scaffolding_hook = "account/scaffolding/completely_concrete/tangible_things"
string = string.gsub(path_without_scaffolding_hook, path_with_scaffolding_hook)
Still a little confused on this one, but I just thought this was significant enough to comment on.
I had this one logged away in my notes as unfinished and it was bothering me for a bit, but looking back on this one, I see that I had already taken care of it.