Change Grails REST format / controller / <id> / <action>

I had a little chat with this yesterday and failed miserably. I want to convert:

 "/$controller/$action?/$id?" 

To

 #in psudo "/$controller/$id?/$action?" #ideal regex "\/(\w+)(\/\d+)?(\/\w+)?" 

The most obvious way failed is "/$controller/$action?/$id?"

I can write a regex to do this, but it's hard for me to find a way to use true regexs (I found RegexUrlMapping , but couldn't find out how to use it), and also can't find documentation on how to assign a group to a variable.

My question has two parts:

  • How to define a URL resource with a true regex.
  • How to associate a "group" with a variable. In other words, if I define a regular expression, how to bind it to a variable as $ controller, $ id, $ action

I would also like to be able to support .json / user / id.json notation


Other things I tried that I thought would work:

 "/$controller$id?$action?"{ constraints { controller(matches:/\w+/) id(matches:/\/\d+/) action(matches:/\/\w+/) } } 

also tried:

 "/$controller/$id?/$action?"{ constraints { controller(matches:/\w+/) id(matches:/\d+/) action(matches:/\w+/) } } 
+4
source share
1 answer

The way grails handle this is to install

 grails.mime.file.extensions = true 

at Config.groovy . This will cause Grails to disable the file extension before applying URL mappings, but make it available for use withFormat

 def someAction() { withFormat { json { render ([message:"hello"] as JSON) } xml { render(contentType:'text/xml') { //... } } } 

To do this, you just need the URL mapping "$controller/$id?/$action?"

I don’t know how to use regular expressions the way you want in URL mappings, but you can get a direct mapping using the fact that you can specify closures for parameter values ​​that are evaluated at runtime by accessing others parameters:

 "$controller/$a?/$b?" { action = { params.b ?: params.a } id = { params.b ? params.a : null } } 

which says: "If b set, then use it as an action and a as id , otherwise use a as an action and set id to null ." But this will not give you a good inverse mapping, i.e. createLink(controller:'foo', action:'bar', id:1) will not create anything reasonable, you will have to use createLink(controller:'foo', params:[a:1, b:'bar'])

Edit

The third opportunity you could try is to combine

 "/$controller/$id/$action"{ constraints { controller(matches:/\w+/) id(matches:/\d+/) action(matches:/\w+/) } } 

with additional

 "/$controller/$action?"{ constraints { controller(matches:/\w+/) action(matches:/(?!\d+$)\w+/) } } 

using a negative lookahead to ensure that two matches do not intersect.

+2
source

All Articles