Is there a way to generate a scaffold for Rails models that have either a has_and_belongs_to_many or has_many :through relationship? If not, is there a developmental reason why some basic form of this functionality has not been included? Rails requires developers to generate and edit a "custom" "join table migration." Is the necessary attention to detail a way of reminding Rails developers of some important fact or is this simply an example of how Rails is a 'work in progress?'
A quick Stackoverflow search for:
"has_and_belongs_to_many" yields 821 questions
"has_many :through" yields 933 questions
... and many of these start with "How do I..." So it seems the topic is not trivial and relevant to SO users. I Guess I am wondering why it has not received attention. Is the matter more complex than it seems? The feature set for Rails seems so extensive. I keep wondering why scaffolding for associations with join tables has been omitted.
Please focus your answer toward the assertions above or "include statement like, "A scaffolding would have to include..." or "A rails generate script would need..."
Thanks!
I like your question, I have wondered for myself why this is not included in Rails (and as I suspect not available as a Gem). Here are some of the reasons why that could be a problem. I will them explain at the typical example with assemblies
and parts
.
Scaffolding works by using generators to create files. If you migrate to a newer version, there is sometimes the option to update existing files by doing the following steps:
That implies that there is no notion of adding to files or changing files. EDIT: This is not true, there are mechanisms to add to files and even change in files.
If you look at the generation of e.g. has_many :through
(should be similar to has_and_belongs_to_many
) you have to do the following things:
Add a migration that creates the join table.
==> Should be possible for scaffolding by doing: rails g scaffold_hmt Assembly Part
Add a model for that join model.
==> Should be possible for scaffolding by the previous scaffold.
Change existing models to include the lines:
assembly.rb: has_many 'assemblies_parts'; has_many :parts, :through => 'assemblies_parts'
part.rb: has_many 'assemblies_parts'; has_many :assemblies, :through => 'assemblies_parts'
==> So no scaffolding possible
has_many
views, however.So as a summary, a scaffold could be worth a try (see the following paragraph). The RailsGuides to Creating and Customizing Rails Generators & Templates seems plausible at least. And a solution that generates parts of files, names them accordingly and helps in the output of the scaffold on the console to do the rest by hand could be worth a try.
I have tried yesterday to come up with a partial solution, you may have a look at it at GitHub. It works like that:
scaffold_hmt
(stands for has_many :through
) to your rails application directory lib/generators
.rails g scaffold_hmt Assembly Part
.It fails to change the files:
assembly.rb
part.rb
The reason for that is that the finding of the right place is not trivial. As a workaround, it prints out what should have inserted into the files.
c:\apps\ruby\rails3\minds>rails generate scaffold_hmt Assembly Part
create db/migrate/20111011135944_create_assemblies_parts.rb
create app/models/assemblies_part.rb
Try to insert into file: app/models/assembly.rb the following statements:
has_many :assemblies_parts
has_many :parts, :through => :assemblies_parts
insert app/models/assembly.rb
Try to insert into file: app/models/part.rb the following statements:
has_many :assemblies_parts
has_many :assemblies, :through => :assemblies_parts
insert app/models/part.rb
Give it a try and see if that will help you.