Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Namespaced route with super scaffolding is missing sortable routes #511

Open
jagthedrummer opened this issue Sep 1, 2023 · 10 comments · Fixed by #774
Open

Namespaced route with super scaffolding is missing sortable routes #511

jagthedrummer opened this issue Sep 1, 2023 · 10 comments · Fixed by #774

Comments

@jagthedrummer
Copy link
Contributor

https://discord.com/channels/836637622432170028/836637623048601633/1146858936356577431

In that discord link @wesgarrison reports:

New namespaced resource with super-scaffold with --sortable and the route can't be found with <%= url_for [:reorder, :account, context, collection] %>

rails routes does not show me the route.

I see draw "concerns" at the top of the config/routes

Looks like the sortable gem adds a concern for the route, but super scaffold only adds it for 1 of the conditional branches

add_concern(:sortable) if transformer_options["sortable"]

Looks like that was it, I added , concerns: [:sortable] to the route for the namespaced child and now I see the routes

@gazayas
Copy link
Contributor

gazayas commented Sep 21, 2023

I scaffolded the following, and the routing was properly scaffolded for me:

rails g model Project::Site team:references title:string
bin/super-scaffold crud Project::Site Team title:text_field --sortable

Result

namespace :project do
  resources :sites, concerns: [:sortable]
end
--[ Route 29 ]----------------------------------------------------------------------------------------------------------------------------------
Prefix            | reorder_account_team_project_sites
Verb              | POST
URI               | /account/teams/:team_id/project/sites/reorder(.:format)
Controller#Action | account/project/sites#reorder

rails g + scaffold commands

Hey @wesgarrison, I know in the Discord chat you talked about providing these commands, do you remember what you wrote when you ran into this issue? Maybe I'm overlooking something with the example I provided above.

@wesgarrison
Copy link
Contributor

Sorry, I forgot I said I would do this!

rails g model Listings::Contact listing:references first_name:string last_name:string prefix:string suffix:string \
position:string cell:string email:string 

bin/super-scaffold crud Listings::Contact Listing,Edition,Team first_name:text_field last_name:text_field \
prefix:super_select suffix:super_select \
position:text_field cell:phone_field email:email_field --sortable

I have not used --sortable in the last month, but I could try to replicate another command to see if it's still happening if that's helpful. Or, if it's working for you we can just close and move on.

@gazayas
Copy link
Contributor

gazayas commented Feb 13, 2024

Ran this today with the following commands since we updated the scaffolders.

> rails g super_scaffold Edition Team name:text_field
> rails g super_scaffold Listing Edition,Team name:text_field
> rails g super_scaffold Listings::Contact Listing,Edition,Team first_name:text_field last_name:text_field prefix:super_select suffix:super_select position:text_field cell:phone_field email:email_field --sortable

Confirmed that I'm getting the same error with url_for. It turns out the Project::Site example I provided in a previous comment works fine, it's just an issue when the namespaced model refers to a parent model. I think I'll start looking into this one next.

@swombat
Copy link
Contributor

swombat commented Apr 3, 2024

Hi there - I'm still having issues with Namespaced parent models and --sortable. I've documented them in this Discord thread: https://discord.com/channels/836637622432170028/836637623048601633/1224762468803412138

@swombat
Copy link
Contributor

swombat commented Apr 3, 2024

In short, afaict two things seem to be going wrong:

  1. the sort_order is not being added by the auto-generated migration.
  2. the helper that creates the routes in the erb files generates routes that are slightly different from the routes generated by routes.rb file.

So for example, with the super-scaffold:

rails generate super_scaffold Ideas::Scripts::Section Ideas::Script,Idea,Channel,Team name:text_field contents:trix_editor structure_description:trix_editor is_favorite:boolean is_selected:boolean version:number_field created_by_id:super_select{class_name=IntelligenceApi} --sortable

Then in accounts/ideas/scripts/sections/_index.html the url_for url_for [:reorder, :account, context, collection] ends up looking for a path helper called reorder_account_ideas_script_sections_path when what's coming from routes.rb is reorder_account_idea_scripts_sections_path:

reorder_account_idea_scripts_sections POST /account/ideas/:idea_id/scripts/sections/reorder(.:format) account/ideas/scripts/sections#reorder

I haven't tried creating a fresh project to test this but I imagine it is reproducible if you just create a fresh project, create a namespaced item, and then try to use that as a parent in the chain for a sortable namespaced item.

@jagthedrummer jagthedrummer reopened this Apr 3, 2024
@swombat
Copy link
Contributor

swombat commented May 9, 2024

I assume this isn't being looked at yet. If someone could suggest a starting point I might have a look...

@jagthedrummer
Copy link
Contributor Author

@swombat here's what I'd suggest as a way to start looking into this.

First get your local copy of the starter repo linked up to use a local copy of the core gems. I have the starter repo and the core repo in the same projects folder, so the hierarchy looks like this:

projects
  |- bullet_train
  |- bullet_train-core

Then in the bullet_train directory run bin/hack --link ../bullet_train-core.

That will alter the Gemfile to point at the local gems instead of using the published versions.

So now when you run a super scaffolding command you'll be running your local code, and you can add logging statements or debugger lines to any of the core gems to try to figure out what's going on.

In the core repo the bullet_train-super_scaffolding/lib/scaffolding/transformer.rb file is one of the big contributors to the scaffolding process so that might be a good place to start looking. From there you should be able to trace what's happening.

This sounds at least somewhat related to another --sortable bug that we squashed recently, so you might see if the changes in this PR have fixed this issue for you, and if not, it might suggest a place to start debugging.

@swombat
Copy link
Contributor

swombat commented May 19, 2024

Cool, I'm looking into it.

I've set it up as suggested. I can confirm, in case it was still in doubt, that this issue is at least still partially open.

Running the following generators one after the other:

rails generate super_scaffold Project Team name:text_field --sortable
rails generate super_scaffold Projects::Widget Project,Team name:text_field --sortable
rails generate super_scaffold Projects::Widgets::Item Projects::Widget,Project,Team name:text_field --sortable

All execute without errors. The first two work totally fine. But here is the migration created by the third one:

class CreateProjectsWidgetsItems < ActiveRecord::Migration[7.1]
  def change
    create_table :projects_widgets_items do |t|
      t.references :widget, null: false, foreign_key: {to_table: 'projects_widgets'}
      t.string :name

      t.timestamps
    end
  end
end

It's missing the sort_order present in the previous migration:

class CreateProjectsWidgets < ActiveRecord::Migration[7.1]
  def change
    create_table :projects_widgets do |t|
      t.references :project, null: false, foreign_key: true
      t.integer :sort_order
      t.string :name

      t.timestamps
    end
  end
end

So I'll hunt this one down first before looking at whether the routes are working.

@swombat
Copy link
Contributor

swombat commented May 19, 2024

This commit fixes the missing sort_order:

4edafb2?diff=split&w=1

However, after running the migration, the app will still fail because of the incorrect route, once you click on the parent of the third object (Projects::Widgets::Item):

13:32:46 web.1              | ActionView::Template::Error (undefined method `new_account_projects_widget_item_path' for an instance of #<Class:0x000000013cc55d40>):
13:32:46 web.1              |     40:         <% unless hide_actions %>
13:32:46 web.1              |     41:           <% if context == widget %>
13:32:46 web.1              |     42:             <% if can? :create, Projects::Widgets::Item.new(widget: widget) %>
13:32:46 web.1              |     43:               <%= link_to t('.buttons.new'), [:new, :account, widget, :item], class: "#{first_button_primary(:item)} new" %>
13:32:46 web.1              |     44:             <% end %>
13:32:46 web.1              |     45:           <% end %>
13:32:46 web.1              |     46: 

The actual routes defined:

                                                                   reorder_account_widget_items POST     /account/widgets/:widget_id/items/reorder(.:format)                                                                                                   account/projects/widgets/items#reorder
                                                                           account_widget_items GET      /account/widgets/:widget_id/items(.:format)                                                                                                           account/projects/widgets/items#index
                                                                                                POST     /account/widgets/:widget_id/items(.:format)                                                                                                           account/projects/widgets/items#create
                                                                        new_account_widget_item GET      /account/widgets/:widget_id/items/new(.:format)                                                                                                       account/projects/widgets/items#new
                                                          reorder_account_project_widgets_items POST     /account/projects/:project_id/widgets/items/reorder(.:format)                                                                                         account/projects/widgets/items#reorder
                                                                      edit_account_widgets_item GET      /account/widgets/items/:id/edit(.:format)                                                                                                             account/projects/widgets/items#edit
                                                                           account_widgets_item GET      /account/widgets/items/:id(.:format)                                                                                                                  account/projects/widgets/items#show
                                                                                                PATCH    /account/widgets/items/:id(.:format)                                                                                                                  account/projects/widgets/items#update
                                                                                                PUT      /account/widgets/items/:id(.:format)                                                                                                                  account/projects/widgets/items#update
                                                                                                DELETE   /account/widgets/items/:id(.:format)                                                                                                                  account/projects/widgets/items#destroy
preview_resources_projects_widgets_item GET    /resources/projects_widgets_items/:id/preview(.:format)                                            avo/projects_widgets_items#preview
       resources_projects_widgets_items GET    /resources/projects_widgets_items(.:format)                                                        avo/projects_widgets_items#index
                                        POST   /resources/projects_widgets_items(.:format)                                                        avo/projects_widgets_items#create
    new_resources_projects_widgets_item GET    /resources/projects_widgets_items/new(.:format)                                                    avo/projects_widgets_items#new
   edit_resources_projects_widgets_item GET    /resources/projects_widgets_items/:id/edit(.:format)                                               avo/projects_widgets_items#edit
        resources_projects_widgets_item GET    /resources/projects_widgets_items/:id(.:format)                                                    avo/projects_widgets_items#show
                                        PATCH  /resources/projects_widgets_items/:id(.:format)                                                    avo/projects_widgets_items#update
                                        PUT    /resources/projects_widgets_items/:id(.:format)                                                    avo/projects_widgets_items#update
                                        DELETE /resources/projects_widgets_items/:id(.:format)                                                    avo/projects_widgets_items#destroy

@swombat
Copy link
Contributor

swombat commented May 19, 2024

As per the conversation at https://discord.com/channels/836637622432170028/1225882536203518124 I feel a bit stuck on how to fix the routes (at least the first one I see breaking). I need some advice.

The line causing the issue is:

              <%= link_to t('.buttons.new'), [:new, :account, widget, :item], class: "#{first_button_primary(:item)} new" %>

The error it causes is:

13:32:46 web.1              | ActionView::Template::Error (undefined method `new_account_projects_widget_item_path' for an instance of #<Class:0x000000013cc55d40>):

The relevant route is:

                                                                        new_account_widget_item GET      /account/widgets/:widget_id/items/new(.:format)                                                                                                       account/projects/widgets/items#new

Defined by, in routes.rb:

        resources :projects, concerns: [:sortable] do
          scope module: 'projects' do
            resources :widgets, only: collection_actions, concerns: [:sortable] do
              scope module: 'widgets' do
                resources :items, only: collection_actions, concerns: [:sortable]
              end
            end

            namespace :widgets do
              resources :items, except: collection_actions, concerns: [:sortable]
            end
          end
        end

        namespace :projects do
          resources :widgets, except: collection_actions, concerns: [:sortable]
        end

I see two possible solutions here, but I don't like either of them:

  1. Patch Rails' url helper to handle namespaced models differently? Yuck.
  2. alter the template to use the new_account_widget_item_path() directly instead of using the url helper? Kinda yuck too, but the least bad of the two choices I see.

Anyone see another option?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants