Grails

Documentation for chain method is incorrect with regards to the override behavior in Grails 1.2

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 1.2 final
  • Fix Version/s: 1.2.1, 1.3-M1
  • Component/s: Documentation
  • Labels:
    None
  • Environment:
    java 1.6.0_16-b01, Ubuntu 9.04 (32 bit), Grails 1.2

Description

Issue 2447 is being observed in grails 1.2 again. When using chain rather than render to return the user to the create action after validation/save failed results in no errors and previously entered information not being rendered.

Activity

Hide
Jeff Brown added a comment -

Rob,

If you can attach a simple demonstrative application that would be helpful. As it is, I cannot reproduce the problem which may be because I am not clear on the problem you are reporting or maybe there is some other significant factor in your app.

Show
Jeff Brown added a comment - Rob, If you can attach a simple demonstrative application that would be helpful. As it is, I cannot reproduce the problem which may be because I am not clear on the problem you are reporting or maybe there is some other significant factor in your app.
Hide
Rob Vugts added a comment -

I have attached a trivial test application. When you run the application, go into the task controller, create a new task and press 'save' without entering a name.
In grails 1.1.2 errors will be rendered (the name cannot be blank), whereas with grails 1.2 no errors are rendered as no error information is held in the flash scope.

When I replace the call to the chain method in the save action from: chain(action:'create', model:[taskInstance:task]) to render(view:'create', model:[taskInstance:task]), then everything works fine.

On the page: http://grails.org/Validation, the use of the chain method as an alternative to the render method is described. To me the use of chain is preferred since the chain method renders the create view, but my browser is showing the URL associated with the save action.

Show
Rob Vugts added a comment - I have attached a trivial test application. When you run the application, go into the task controller, create a new task and press 'save' without entering a name. In grails 1.1.2 errors will be rendered (the name cannot be blank), whereas with grails 1.2 no errors are rendered as no error information is held in the flash scope. When I replace the call to the chain method in the save action from: chain(action:'create', model:[taskInstance:task]) to render(view:'create', model:[taskInstance:task]), then everything works fine. On the page: http://grails.org/Validation, the use of the chain method as an alternative to the render method is described. To me the use of chain is preferred since the chain method renders the create view, but my browser is showing the URL associated with the save action.
Hide
Jeff Brown added a comment -

Your controller looks like this:

grails-app/controllers/TaskController.groovy
class TaskController {

    def scaffold = true

    def save = {
        def task = new Task(params)
        if (task.save(flush:true)) {
            redirect(action:show, id:task.id)
        }
        else {
            chain(action:'create', model:[taskInstance:task])
        }
    }
}

You are using the default scaffolded create action which looks like this:

grails-app/controllers/TaskController.groovy
class TaskController {

    def create = {
        def taskInstance = new Task()
        taskInstance.properties = params
        return [taskInstance: taskInstance]
    }

}

When you call chain() in your save action you are passing a model that contains a value for the taskInstance. That taskInstance has errors associated with it. The create action is returning a model which also includes a value of the taskInstance. That taskInstance does not have errors associated with it. The model that is passed in to your view is created by starting with the model that was passed to the chain() method and then adding to that all of the entries in the model that were returned by the create action so the taskInstance created in the create action replaces the taskInstance that you put in the model that you passed to chain. By the time the view is rendered, the taskInstance that is in the model is the one that contains no errors. In your create action, if you grab the taskInstance that is in chainModel, the errors are there.

I think this is behaving as designed. Graeme, can you verify that this is the intended behavior?

Show
Jeff Brown added a comment - Your controller looks like this:
grails-app/controllers/TaskController.groovy
class TaskController {

    def scaffold = true

    def save = {
        def task = new Task(params)
        if (task.save(flush:true)) {
            redirect(action:show, id:task.id)
        }
        else {
            chain(action:'create', model:[taskInstance:task])
        }
    }
}
You are using the default scaffolded create action which looks like this:
grails-app/controllers/TaskController.groovy
class TaskController {

    def create = {
        def taskInstance = new Task()
        taskInstance.properties = params
        return [taskInstance: taskInstance]
    }

}
When you call chain() in your save action you are passing a model that contains a value for the taskInstance. That taskInstance has errors associated with it. The create action is returning a model which also includes a value of the taskInstance. That taskInstance does not have errors associated with it. The model that is passed in to your view is created by starting with the model that was passed to the chain() method and then adding to that all of the entries in the model that were returned by the create action so the taskInstance created in the create action replaces the taskInstance that you put in the model that you passed to chain. By the time the view is rendered, the taskInstance that is in the model is the one that contains no errors. In your create action, if you grab the taskInstance that is in chainModel, the errors are there. I think this is behaving as designed. Graeme, can you verify that this is the intended behavior?
Hide
Rob Vugts added a comment -

Thanks Jeff for the detailed analysis.

I understand what you are saying, but this is definitely a change in behaviour between version 1.1.x and 1.2. Also, looking at the section "Display Errors in the View" on http://grails.org/Validation, where it says: "In this case we use the render method to render the right view, alternatively you could chain the model back to a "create" action:

chain(action:create,model:[user:u])"

I don't think it is working as designed.Maybe the new behaviour is a better design, but then this change should be documented, the web page updated and ideally there should be a new example on how the chain method can still be used.

Regards,
Rob

Show
Rob Vugts added a comment - Thanks Jeff for the detailed analysis. I understand what you are saying, but this is definitely a change in behaviour between version 1.1.x and 1.2. Also, looking at the section "Display Errors in the View" on http://grails.org/Validation, where it says: "In this case we use the render method to render the right view, alternatively you could chain the model back to a "create" action: chain(action:create,model:[user:u])" I don't think it is working as designed.Maybe the new behaviour is a better design, but then this change should be documented, the web page updated and ideally there should be a new example on how the chain method can still be used. Regards, Rob
Hide
Graeme Rocher added a comment -

If I recall there was another open JIRA saying that you should be able to override the chained model with the one you return, hence the change. I would say that yes it is a documentation issue and we should update the upgrade notes and the relevant sections on the topic.

Show
Graeme Rocher added a comment - If I recall there was another open JIRA saying that you should be able to override the chained model with the one you return, hence the change. I would say that yes it is a documentation issue and we should update the upgrade notes and the relevant sections on the topic.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: