-
-
Notifications
You must be signed in to change notification settings - Fork 954
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
Support controller attribute in tags with resource attribute and resolve correct identity Fixes #13627 #13628
Support controller attribute in tags with resource attribute and resolve correct identity Fixes #13627 #13628
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you write a test that shows the bug and that this change fixes it?
Why can't I get the same treatment?
|
…rty that is not id. e.g. static mapping = { id: name: 'customId' }
Haha, sorry 😄! This changes the behavior of Grails and there should be a test showing and testing the correct behavior. And it should be a simple test to write. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the year and copyright owner in the header of DefaultLinkGenerator.groovy
: Copyright 2011-2024 the original author or authors.
if (ident) { | ||
return ident.toString() | ||
} | ||
} catch (MissingMethodException | IllegalStateException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
You can use exception parameter name
ignored
to signal that this is expected. -
I think it's fine to use try-catch here, until we find it's a performance problem or find a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -341,7 +365,8 @@ class LinkGeneratorSpec extends Specification { | |||
def generator = cache ? new CachingLinkGenerator(baseUrl, context) : new DefaultLinkGenerator(baseUrl, context) | |||
final callable = { String controller, String action, String namespace, String pluginName, String httpMethod, Map params -> | |||
[createRelativeURL: { String c, String a, String n, String p, Map parameterValues, String encoding, String fragment -> | |||
"${namespace ? '/' + namespace : ''}/$controller/$action".toString() | |||
|
|||
"${namespace ? '/' + namespace : ''}/$controller${parameterValues.id? '/'+parameterValues.id:''}/$action".toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my knowledge, most common in Grails is using /controller/action/id
. In the PR description you are using /controller/action/id
and /controller/id/action
. Should we be consistent, and use /controller/action/id
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do believe this needs to be namespace/controller/action/id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static mappings = {
"/$namespace/$controller/$action?/$id?(.$format)?" {
constraints {
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@matrei @jamesfredley I had made it a "restful mapping" for the test as it was specific to the test. To eliminate confusion, I just changed it to the format you guys are referring to.
@@ -289,6 +290,29 @@ class LinkGeneratorSpec extends Specification { | |||
cacheKey == "somePrefix[resource:org.grails.web.mapping.Widget->2]" | |||
} | |||
|
|||
// | |||
def 'resource links should use ident and allow controller override'() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
- You could add
@Issue('https://github.com/grails/grails-core/issues/13627')
on the test.
@@ -341,7 +365,8 @@ class LinkGeneratorSpec extends Specification { | |||
def generator = cache ? new CachingLinkGenerator(baseUrl, context) : new DefaultLinkGenerator(baseUrl, context) | |||
final callable = { String controller, String action, String namespace, String pluginName, String httpMethod, Map params -> | |||
[createRelativeURL: { String c, String a, String n, String p, Map parameterValues, String encoding, String fragment -> | |||
"${namespace ? '/' + namespace : ''}/$controller/$action".toString() | |||
|
|||
"${namespace ? '/' + namespace : ''}/$controller${parameterValues.id? '/'+parameterValues.id:''}/$action".toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do believe this needs to be namespace/controller/action/id
@@ -341,7 +365,8 @@ class LinkGeneratorSpec extends Specification { | |||
def generator = cache ? new CachingLinkGenerator(baseUrl, context) : new DefaultLinkGenerator(baseUrl, context) | |||
final callable = { String controller, String action, String namespace, String pluginName, String httpMethod, Map params -> | |||
[createRelativeURL: { String c, String a, String n, String p, Map parameterValues, String encoding, String fragment -> | |||
"${namespace ? '/' + namespace : ''}/$controller/$action".toString() | |||
|
|||
"${namespace ? '/' + namespace : ''}/$controller${parameterValues.id? '/'+parameterValues.id:''}/$action".toString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static mappings = {
"/$namespace/$controller/$action?/$id?(.$format)?" {
constraints {
}
}
}
linkParams.resource = new Widget(id: 1, name: 'Some Widget') | ||
|
||
then: | ||
link == "/bar/widget/1/show" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
linkParams.controller = 'widgetAdmin' | ||
|
||
then: | ||
link == "/bar/widgetAdmin/1/show" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the getResourceId(resourceAttribute) fix is big. I'm not sure how that had not come up before. |
#13627
Fixes the following
which should link to
/userAdmin/show/1
but instead renders
/user/show/1
Also fixes
Currently (bug) grails creates a link to
/sample/index
for this class instead of/sample/${sample.indent()}/show
because it does not have an id property and uses a static id mapping.Design Assumptions
If a resource is a
PersistentEntity
or aDomain
Artifact an attempt to callident()
is made, otherwise a MethodMissing exception occurs and a fallback to the id property is used.Reason for Incorrect Behavior
The following code is where it is problematic
https://github.com/grails/grails-core/blob/da8668daa13c9c1b2157535e11986f49615e8a4b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/DefaultLinkGenerator.groovy#L174-L189
and is correctly handled here:
https://github.com/grails/grails-core/blob/da8668daa13c9c1b2157535e11986f49615e8a4b/grails-web-url-mappings/src/main/groovy/org/grails/web/mapping/CachingLinkGenerator.java#L120-L139
https://github.com/grails/grails-core/blob/0daf7c69f98cd3f2f25ad990b52e005f7c976f5a/grails-core/src/main/groovy/grails/util/GrailsMetaClassUtils.java#L241-L248