Sap
Sap

Reputation: 5291

New code in Grails generated controller

Since I have upgraded my Grails version the generated code in controller's save method has changed. I have gone through the documentation which explains each item separately but it would be great if someone can explain the request.withFormat part holistically.

The following snippet is taken from an automatically generated Save action. One thing that is puzzling me is. Which line here indicates, render "show" view after successful save operation?

def save(User userInstance) {
    if (userInstance == null) {
        notFound()
        return
    }

    if (userInstance.hasErrors()) {
        respond userInstance.errors, view:'create'
        return
    }

    userInstance.save flush:true

    request.withFormat {
        form multipartForm {
            flash.message = message(code: 'default.created.message', args: [
                message(code: 'user.label', default: 'User'),
                userInstance.id
            ])
            redirect userInstance
        }
        '*' { respond userInstance, [status: CREATED] }
    }
}    

Upvotes: 2

Views: 1966

Answers (2)

Cléssio Mendes
Cléssio Mendes

Reputation: 1016

It seems that this is an undocumented behavior of redirect. But looking at grails code we can figure out that it uses this convention:

If redirect takes just a PERSISTED object as argument, it will infer the show action url and use the object id as the url argument.

There is a Jira for that doc issue at https://jira.grails.org/browse/GRAILS-11862

Some more resources on that: http://grails.1312388.n4.nabble.com/New-controller-syntax-explained-td4654914.html

Regarding the withFormat snippet, it embraces three situations:
1) "form" A simple form submission excpecting an html response (enctype="application/x-www-form-urlencoded")
2) "multipartForm" A file upload form submission excpecting an html response (enctype="multipart/form-data")
3) "*" All other options, like json or xml in restfull requests

Situations 1 and 2 are handled by the same code.

Upvotes: 1

micha
micha

Reputation: 49542

request.withFOrmat can be used to return different response types depending on the request accept header.

The example from the documentation:

request.withFormat {
    html bookList:books // render html
    js { render "alert('hello')" } // render javascript
    xml { render books as XML } // render xml
}

In your example the controller can return two types of responses. One for multipart form requests and one that is used for all other requests:

request.withFormat {
    form multipartForm {
        // if it is a multipart form request -> add a flash message and redirect to another action
        flash.message = message(code: 'default.created.message', args: [
            message(code: 'user.label', default: 'User'),
            userInstance.id
        ])
        redirect userInstance
    }
    '*' { 
         // for all other request types, respond with the `userInstance` object
         respond userInstance, [status: CREATED] 
    }
}

Upvotes: 3

Related Questions