0

I've ran into a problem which causes link_to @resource to fail.

My view:

<% @test_thing = Bar.first #This one belongs to Foo.first %>
<%= link_to "test link", @test_thing %>

produces this error:

NoMethodError
undefined method `bar_path' for #<#<Class:0x007fd799bc1088>:0x007fd799bc8400>

Why does rails not produce the correct route using thing1_thing2_path?

routes.rb:

resources :foo, as: "thing1", path: "thing2" do
  resources :bar, as: "thing2", path: "thing2"
end

In my models, "Foo" has_many :bars and "Bar" belongs_to :foo

rake routes:

thing1_thing2_index GET    /thing2/:thing1_id/thing2(.:format)          bar#index
                    POST   /thing2/:thing1_id/thing2(.:format)          bar#create
  new_thing1_thing2 GET    /thing2/:thing1_id/thing2/new(.:format)      bar#new
 edit_thing1_thing2 GET    /thing2/:thing1_id/thing2/:id/edit(.:format) bar#edit
      thing1_thing2 GET    /thing2/:thing1_id/thing2/:id(.:format)      bar#show
                    PATCH  /thing2/:thing1_id/thing2/:id(.:format)      bar#update
                    PUT    /thing2/:thing1_id/thing2/:id(.:format)      bar#update
                    DELETE /thing2/:thing1_id/thing2/:id(.:format)      bar#destroy
       thing1_index GET    /thing2(.:format)                            foo#index
                    POST   /thing2(.:format)                            foo#create
         new_thing1 GET    /thing2/new(.:format)                        foo#new
        edit_thing1 GET    /thing2/:id/edit(.:format)                   foo#edit
             thing1 GET    /thing2/:id(.:format)                        foo#show
                    PATCH  /thing2/:id(.:format)                        foo#update
                    PUT    /thing2/:id(.:format)                        foo#update
                    DELETE /thing2/:id(.:format)                        foo#destroy
               root GET    /                                            bar#index

I'm using rails 4, but I had the same problem with rails 3.
I fell like it's a bug in rails, or am I doing something wrong?

jomo
  • 14,121
  • 4
  • 29
  • 30

2 Answers2

1

Do not rename your routes. Remove the as: argument:

resources :foo, path: "thing2" do
  resources :bar, path: "thing2"
end

Apart from that, you need to hand it both objects in order to produce the correct path:

<%= link_to "test link", [@test_thing.foo, @test_thing] %>
janfoeh
  • 10,243
  • 2
  • 31
  • 56
  • Same problem: undefined method `foo_bar_path' for #<#:0x007f2e3b6eabe8> – jomo Dec 15 '13 at 16:59
  • 1
    @HansWürstchen Ah, you're renaming the route with `:as`. Remove that from your routes and it'll work as expected. – janfoeh Dec 15 '13 at 18:13
  • well that's the whole problem. I do want the renamed routes. – jomo Dec 15 '13 at 19:03
  • @HansWürstchen what for? Maybe we can find another way to achieve that. – janfoeh Dec 15 '13 at 19:12
  • for example when you have `albums` and `album_images`, but also got `xyz_images` for other resources, you wouldn't like to have a path like `album/13/album_image/37` but rather `album/13/image/37`. – jomo Dec 16 '13 at 18:57
  • 1
    @HansWürstchen You are confusing `as:` and `path:` - they have different purposes. `as:` defines how the *route helper* is named (eg. `album_album_image_path`). `path:` defines how *the URL* looks (eg. `resources :album_images, path: 'images'` => `/album/13/images/37`). So you can have custom URLs that still work automatically with link_to. – janfoeh Dec 16 '13 at 19:26
  • thanks! worked :) but i'm still wondering why it can't handle `as:` - maybe a bug? – jomo Dec 21 '13 at 17:34
  • @HansWürstchen no, it works like it is supposed to - it renames the route helpers. Rails builds on conventions: hand `link_to` an object of class `AlbumImage`, and it looks for an `album_image_path`. If there isn't one, because you renamed `album_image_path` to `foo_path` by declaring `resources :album_image, as: :foo`, you will have to pass the link to `link_to` directly, because you broke Rails' convention. – janfoeh Dec 21 '13 at 17:53
0

Have you tried passing the link explicitly? Something like:

<%= link_to "test link", bar_path(@test_thing) %>

...or whatever the correct *_path(variable) you should be using?

(Sorry, the test, and bar, and thing1, thing2 things got really confusing over here :P)