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

link_to / form_for doesn't work for singular resource #1769

Closed
Godisemo opened this Issue Jun 19, 2011 · 67 comments

Comments

Projects
None yet
@Godisemo
Copy link

Godisemo commented Jun 19, 2011

In my routes I have

resource :company

and in my views

<% form_for(@store) do |f| %><% end %>

When

new action gets an error when rendering

undefined method hash_for_companies_path' for #Module:0x00000102bfd3f0`

The stack trace reviels that the problem occurs in

lib/action_dispatch/routing/polymorphic_routes.rb:133:in polymorphic_url'`

edit action can render without errors but the forms url is /company.4 where 4 is the id of the company.

This seems to be a bug that has been around for a very long time so I think it's time to fix it.

@pixeltrix

This comment has been minimized.

Copy link
Member

pixeltrix commented Jun 19, 2011

You're right the error has been around for a long while however a clean solution doesn't readily represent itself. The polymorphic_url helper has no 'intelligence' in how it operates - it has no information about what you've declared as resources in your routes.rb. All it has to go on it the name of the model and how that maps to the named url helpers.

In your case when passing a new Company instance it tries to map to the plural path as that's the standard route for the create action. The question is how to determine a singular resource from a regular resource - suggestions are welcome. The best solution I can think of is to try a respond_to? first and if it doesn't then try the singular option - I'll take a look at it.

@ghost ghost assigned pixeltrix Jun 19, 2011

@gucki

This comment has been minimized.

Copy link

gucki commented Jul 18, 2011

Ah, didn't know there's already a ticket for htis. So here's my post from the mailing list:

What about making the polymorphic routing in rails to try a plural route first. If it fails, try a singleton route. If it fails, raise.

This is not the nicest and most performant way (the result could be cached in production so it doesn't really matter in the end) but I guess it should solve most cases. Or is this too much magic?

@wildchild

This comment has been minimized.

Copy link
Contributor

wildchild commented Aug 20, 2011

I am wondering why this ticket pointed to 3.2 milestone?

@pixeltrix

This comment has been minimized.

Copy link
Member

pixeltrix commented Aug 20, 2011

Because it’s not a blocker for the 3.1 release and it may require too many changes to go into a patch release.

@mikeni

This comment has been minimized.

Copy link

mikeni commented Mar 9, 2012

i think this bug should be written in rails guides somewhere.

for anyone using a singular resource, they will eventually find themselves on this bug page. better to announce first

@maximeg

This comment has been minimized.

Copy link
Contributor

maximeg commented Mar 14, 2012

Still occurring.

@mikeni

This comment has been minimized.

Copy link

mikeni commented Mar 16, 2012

for now i just use scope =(

@phantomwhale

This comment has been minimized.

Copy link

phantomwhale commented Apr 8, 2012

Yep, my first time with the singular resource form, and I walked smack into this bug. Would be great to see a fix in an upcoming version - don't see any target milestone, so I presume it's not under active development at the moment ?

@kjakub

This comment has been minimized.

Copy link

kjakub commented Apr 14, 2012

Yep, here too, my first time with singular resource, lost 3h coz i was blaming myself like a first

@glebm

This comment has been minimized.

Copy link
Contributor

glebm commented May 3, 2012

+1

@felipero

This comment has been minimized.

Copy link
Contributor

felipero commented May 4, 2012

I believe respond_with has the same problem.

@pixeltrix

This comment has been minimized.

Copy link
Member

pixeltrix commented May 4, 2012

@felipero yes it will - as will anything where you can pass a model instance and get a url.

I haven't forgotten about this issue, it's just trickier than it seems to fix. The problem is there is no easy way to discern whether a model maps to a singular or a regular resource url. Checking for the presence of a collection url doesn't work as the resource may have been specified with :except => :index and trying to rescue route generation errors doesn't work because passing an instance to a singular resource url helper will generate a url with the format set to the id and no exception.

The only apparent way I can think of doing it is by creating a data structure that keeps a track of whether a set of routes is a singular resource and then querying that data structure in polymorphic_url. However before I or someone else can go ahead with that there needs to be a discussion whether we want the overhead of that structure.

@felipero

This comment has been minimized.

Copy link
Contributor

felipero commented May 4, 2012

Well, it is a non-blocking issue. Thanks for you prompt answer. :)

@zelig

This comment has been minimized.

Copy link

zelig commented Jun 16, 2012

I think someone ought to patch this. My thinking would not be along the lines of trying routes to fail (and fall back on the plural as in the comments in the rails issue) but go after association reflections.

Can we make the assumption that behind every nested resource form there is an activerecord association? No but we can test it

for form_for [a, b] (of classes A, B) if there is a model class A with has_many assoc to B, we can safely assume, expect that routes are set up to support a plural ("a_bs_path") for create. If there is a has_one we can safely assume, expect that routes are set up to support a singular ("a_bs_path"). If we find none, we fall back to the plural as the status quo educated guess. My 2 cents. Is this against modularity and decoupling MVC?

@pixeltrix

This comment has been minimized.

Copy link
Member

pixeltrix commented Jun 16, 2012

@zelig firstly, I think anything like that is tying your models to your routes too much. Secondly, what about non-AR models, and finally it doesn't fix the problem for top-level singular resources, e.g;

class Basket < ActiveRecord::Base
end

resource :basket

There's nothing in the model that's going to help with that - the only way it to store the fact that it's a singular resource and query that when generating the url. Adding metadata to the model won't help as a model may sometimes be a singular resource (/account) or a multiple resource (/admin/users/1).

@zelig

This comment has been minimized.

Copy link

zelig commented Jun 16, 2012

Surely this doesn't solve all problems but in the special case of nested AR resources, plurality can be reasonably guessed using model class associations, for others (i.e., top-level resource or non-AR models or models with implicit associations) the plural is a decent guess. This sounds to me a simple improvement but maybe the caveat is that it is not the right solution.

So where would you store resource singularity so that polyorphic_url could access this info? In case people are interested in fixing this ugly duckling.

@jakevose

This comment has been minimized.

Copy link

jakevose commented Jul 17, 2012

Add me to the list of people who just lost a bunch of time trying to figure out the "right" way to work around this and thinking myself crazy before stumbling upon this obscure reference to a long-standing, known bug.

@pjg

This comment has been minimized.

Copy link
Contributor

pjg commented Oct 17, 2012

Add me to the list of people who just lost a bunch of time trying to figure out the "right" way to work around this and thinking myself crazy before stumbling upon this obscure reference to a long-standing, known bug.

And me as well.

@pjg

This comment has been minimized.

Copy link
Contributor

pjg commented Oct 18, 2012

To anyone stumbling upon this issue, the workaround is quite simple. Given:

resource :billing_info

You generate the form_for call like this:

= form_for @billing_info, url: billing_info_path do |f|
@gmile

This comment has been minimized.

Copy link
Contributor

gmile commented Oct 18, 2012

@pjg one of the nice features of form_for is to generate a proper url, based on object's persistance state, i.e. autodetect a path with either _create or _update affixes. That said, i'm unsure if the solution you propose will handle both cases at the same time. Will it?

@pjg

This comment has been minimized.

Copy link
Contributor

pjg commented Oct 19, 2012

Yeah, it does handle both :create and :update actions.

@asymmetric

This comment has been minimized.

Copy link

asymmetric commented Nov 23, 2012

It would be really nice to have this fixed, or at least to have the problem prominently documented somehow. Just spent 2hrs thinking it was an error on my end!

@jlbenc

This comment has been minimized.

Copy link

jlbenc commented Dec 17, 2012

Wasted 2+ hours hunting this issue down, :(

Thanks @pjg for your workaround! 👍

@gaurish

This comment has been minimized.

Copy link
Contributor

gaurish commented Dec 30, 2012

Today, I faced issue too. solved via workaround given Thanks @pjg 👍

@hasghari

This comment has been minimized.

Copy link

hasghari commented Jan 15, 2013

I agree with @mikeni that this bug should be documented in the Rails guides.

athal7 pushed a commit to athal7/rails that referenced this issue Apr 1, 2013

Andrew Thal
Add tests to demonstrate form_for issues with a singular resource. Is…
…sue rails#1769

These failing tests were written in an attempt to demonstrate the issues
discussed in rails#1789 related to attempting to use form_for with a singular
resource. I am aware from the discussion that the fix will most likely
not be an easy one, but I figured it could be helpful to have tests to
demonstrate the issue, and I hope that these tests serve that purpose.
@justinj656

This comment has been minimized.

Copy link

justinj656 commented May 6, 2015

The workaroud I use is to add as: to change the path helper for singular resource, like
resource company, as: :companies

@philipgiuliani

This comment has been minimized.

Copy link

philipgiuliani commented Jul 21, 2015

Why a bug like this isn't fixed yet?

@notrab

This comment has been minimized.

Copy link

notrab commented Aug 8, 2015

@philipgiuliani I'm sure you'll discover, judging by the comments above, there isn't any easy way to do this without polluting other classes within Rails for this behaviour.

The workaround is quite simple and to be honest, I don't see a problem. Throw it in the docs and just be done with it. Adding url: to the form declaration isn't so hard work for singular routes.

😴

@rails-bot

This comment has been minimized.

Copy link

rails-bot commented Dec 23, 2015

This issue has been automatically marked as stale because it has not been commented on for at least
three months.

The resources of the Rails team are limited, and so we are asking for your help.

If you can still reproduce this error on the 4-2-stable, 4-1-stable branches or on master,
please reply with all of the information you have about it in order to keep the issue open.

Thank you for all your contributions.

@caromedellin caromedellin referenced this issue Jan 31, 2016

Closed

Match views #29

maclover7 added a commit to maclover7/rails that referenced this issue Feb 7, 2016

@maclover7 maclover7 added attached PR pinned and removed stale labels Feb 7, 2016

maclover7 added a commit to maclover7/rails that referenced this issue Feb 7, 2016

Add singular resource support to `polymorphic_path`
A somewhat less invasive redo to rails#23535. The problem that makes rails#1769 so
hard to solve, is that `polymorphic_path` is only provided with an
database object, so this makes it hard to reinvent the routing tree.
This is the best solution I could come up with.
@rafaelfranca

This comment has been minimized.

Copy link
Member

rafaelfranca commented Feb 11, 2016

@schuetzm

This comment has been minimized.

Copy link
Contributor

schuetzm commented Feb 11, 2016

@rafaelfranca Care to explain why you closed this issue? The comment you referenced says it is still open "because it's a difficult problem to solve". Has it finally been fixed?

@rafaelfranca

This comment has been minimized.

Copy link
Member

rafaelfranca commented Feb 11, 2016

Oops! Looks like I linked to the wrong comment. I could not find the comment that I explained that it is fine to use the :url option and that this problem is not something that we need to fix.

#23138 may fix this issue introducing a new API.

@matkoniecz

This comment has been minimized.

Copy link
Contributor

matkoniecz commented May 14, 2016

Why it is closed? #23138 is not merged and it is explicitly documented as existing bug in http://guides.rubyonrails.org/v4.1/routing.html

@azul

This comment has been minimized.

Copy link
Contributor

azul commented May 18, 2016

@matkoniecz - it's documented as you said including a workaround with the url param. And there is a bug that may fix this in the longer run. I think that is why it's closed. #23138 will track the progress on the fix now.

pixeltrix added a commit that referenced this issue Feb 20, 2017

Add custom polymorphic mapping
Allow the use of `direct` to specify custom mappings for polymorphic_url, e.g:

  resource :basket
  direct(class: "Basket") { [:basket] }

This will then generate the following:

  >> link_to "Basket", @Basket
  => <a href="/basket">Basket</a>

More importantly it will generate the correct url when used with `form_for`.

Fixes #1769.

pixeltrix added a commit that referenced this issue Feb 21, 2017

Add custom polymorphic mapping
Allow the use of `direct` to specify custom mappings for polymorphic_url, e.g:

  resource :basket
  direct(class: "Basket") { [:basket] }

This will then generate the following:

  >> link_to "Basket", @Basket
  => <a href="/basket">Basket</a>

More importantly it will generate the correct url when used with `form_for`.

Fixes #1769.
@IamNaN

This comment has been minimized.

Copy link
Contributor

IamNaN commented May 16, 2017

For anyone landing here via google, this is what got implemented: http://edgeguides.rubyonrails.org/routing.html#singular-resources

In short, add something like resolve('User') { [:user] } after you define the singular resource in routes.rb, where 'User' is the class name and :user is the resource name.

@tomrossi7

This comment has been minimized.

Copy link
Contributor

tomrossi7 commented Oct 20, 2017

Couldn't this be fixed in the latest rails implementation by changing the behavior of form_with?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment