views:

77

answers:

2

Alright I asked a question before but wasn't quite sure about it. So I went ahead and waited till now to ask again.

Main Question

How do I add a new instance of the domain through the controller? I created a function named gather to read a file with data and then create a new Book with the specific information, however it is not adding it to the database at all.

I currently have a controller (bookController) and the domain for it.

My domain is quite simple:

class Book {

    static belongsTo = Author

    String toString() { bookNumber }

    Author bookAuthor
    String title


    static constraints = {
        bookAuthor()
        title()

    }
}

I just 'generated' my views so I have the basic create, edit, list, and show. I went ahead and added my own inside the controller called gather. For the gsp, I just copied over the 'list.gsp' as I just want the user to view the list of books once the gather function is completed.

Here is what my controller looks like (just the basic generated one plus gather):

package bookdemo

import bookClient

class BookController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    def index = {
        redirect(action: "list", params: params)
    }

    def gather = {

        def w = new bookClient()        //bookClient will gather books from txt files
        def hosts = ["localhost"]       //host to connect to

        w.queryData(hosts)          //grab information and parse
        def abc = w.bookList            //list of books
        w.printData(abc)            //print out list of books to make sure its not null

        int numberOfBooks = abc.size()  //list size


    //create book list and return it

        numberOfBooks.times {
        def bookInstance = new Book(Author:"$abc.author", Title:"$abc.title")
            return [bookInstance: bookInstance]
        }


    //params to show once adding books

        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [bookInstanceList: book.list(params), bookInstanceTotal: book.count()]
    }

    def list = {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [bookInstanceList: book.list(params), bookInstanceTotal: book.count()]
    }

    def create = {
        def bookInstance = new Book()
        bookInstance.properties = params
        return [bookInstance: bookInstance]
    }

    def save = {
        def bookInstance = new Book(params)
        if (bookInstance.save(flush: true)) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])}"
            redirect(action: "show", id: bookInstance.id)
        }
        else {
            render(view: "create", model: [bookInstance: bookInstance])
        }
    }

    def show = {
        def bookInstance = book.get(params.id)
        if (!bookInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
            redirect(action: "list")
        }
        else {
            [bookInstance: bookInstance]
        }
    }

    def edit = {
        def bookInstance = book.get(params.id)
        if (!bookInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
            redirect(action: "list")
        }
        else {
            return [bookInstance: bookInstance]
        }
    }

    def update = {
        def bookInstance = book.get(params.id)
        if (bookInstance) {
            if (params.version) {
                def version = params.version.toLong()
                if (bookInstance.version > version) {

                    bookInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'book.label', default: 'Book')] as Object[], "Another user has updated this Book while you were editing")
                    render(view: "edit", model: [bookInstance: bookInstance])
                    return
                }
            }
             bookInstance.properties = params
            if (!bookInstance.hasErrors() && bookInstance.save(flush: true)) {
                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])}"
                redirect(action: "show", id: bookInstance.id)
            }
            else {
                render(view: "edit", model: [bookInstance: bookInstance])
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
            redirect(action: "list")
        }
    }

    def delete = {
        def bookInstance = book.get(params.id)
        if (bookInstance) {
            try {
                bookInstance.delete(flush: true)
                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
                redirect(action: "list")
            }
            catch (org.springframework.dao.DataIntegrityViolationException e) {
                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
                redirect(action: "show", id: params.id)
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'book.label', default: 'Book'), params.id])}"
            redirect(action: "list")
        }
    }
}

The gsp shows up but for some reason my new books are not added. When I add a println in to test whether the information is in the list, it shows prints with the correct info. So I'm confused as to why it is not 'creating' the new book instance and adding it to the database.

Any suggestions?

Edit

Domain class for author:

class Author {

    static hasMany = [books:Book]

    String authorName
    String notes

    String toString() { authorName }


    static constraints = {
        machineName()
        notes(maxSize:500)
    }
}
+1  A: 

I would suggets you write some unit tests for you controller and/or domain objects. Your objects cannot be being created successfully with this code

new Book(Author:"$abc.author", Title:"$abc.title")

Also the return statement here makes no sense

    numberOfBooks.times {
    def bookInstance = new Book(Author:"$abc.author", Title:"$abc.title")
        return [bookInstance: bookInstance]
    }

It looks like you have cut and pasted code without understanding what the code is doing. I think you want something more like this...

    // iterate through the list of books and create the object array to pass back
    def bookListInstance = []
    w.bookList.each {
        def bookInstance = new Book(Author:it.author, Title:it.title)
        bookListInstance << bookInstance
    }
    // now return the list of domain objects
    return [bookInstance: bookListInstance]
Aaron Saunders
I went ahead and changed my gather action to replicate what you did above with my _athor = new Author("$abc.author") and it still did not add them in. It actually still produced the same info as before. Also, why would you expect to see that in the save action? (I just left it generated)
StartingGroovy
I said something "like"!, You have not provided enough code here for a complete solution... You have not shown what the Author Object looks like? You have not shown what the exception is, if any?
Aaron Saunders
There is no exception. I'll post up what the Author object looks like. My apologies Aaron, I haven't dealt with generated views before and I was thinking that doing something like this would be quite similar to the tutorials I had read. I wasn't questioning your work, just wondering why you might have done something like that :) At first I created the grails app without a db at all now im wanting to implement it and ran into the situation above. *posting author object in original question*
StartingGroovy
see edits, i tried to figure out what you are trying to do
Aaron Saunders
the return statement was something I saw in the 'create' action. I figured that was needed if I was using a gsp that had the same code. I didn't have any luck with doing something like your edited code. I tried a println on bookInstance and bookListInstance and both were null :/ all I'm wanting to do is have the database update the table with the data that is pulled from the file when the gather action is used. Perhaps there is another/more simple way of doing this?
StartingGroovy
Thank you for your help Aaron. I believe I figured out the issue. Also wanted to thank you for your time in putting together example code as it helped me understand a few more things
StartingGroovy
can you mark the answer as correct if your issue has been resolved?
Aaron Saunders
A: 

You're not calling .save() on any of the Book instances...

leebutts
Thank you for pointing that out, however this was the first thing I tried and it didn't change the outcome.
StartingGroovy
Well they will definitely not save unless you call that method. You must have had something else wrong as well. Check that the return value of save() is not null. If it is, there is a validation error stopping them from persisting
leebutts
Thanks, I'll check into that and post back.
StartingGroovy
I ended up starting my project over. I believe since I had my project in production mode it believe that some of the old variables were still supposed to be added into the table. Not sure why though. Anyways, I created a new project and am keeping it in test mode until fully ready. Thank you for your help :)
StartingGroovy