Search code examples
grailsgroovycontrollergsp

Grails database action and view rendering


I'm trying to add a simple functionality to my Grails project that similarily to youtube will allow users to like/unlike an article. There's a very primitive page to display articles with their likes and a controller that makes 'liking' possible. Alas, whenever this method is called, it tries to render an unexisting view instead of coming back to the previous one. Here's the .gsp body code:

<g:each in="${articles}" var="article">
        <table class="table-bordered">
            <tr>Article title: ${article.title}</tr><br>
            <tr>Author: ${article.author}</tr><br>
            <tr>Page: ${article.page}</tr><br>
            <tr>Likes: ${article.getLikesCount()}</tr><br>
            <g:link resource="Article" action="articleLiked" id="${article.id}" params="[articleId: article.id]">Like it!</g:link>
        </table>
    </g:each>

And this is my controller's 'like' method code:

def articleLiked(Article article){
        ServiceUser user = springSecurityService.currentUser
        ArticleLike al = ArticleLike.findByArticleAndServiceUser(article, user)
        if(al){
            al.liked = true
        }else{
            al = new ArticleLike(Article: article, ServiceUser: user, liked: true)
        }
        al.save()
        showArticleList()
    }

As a result, I've got this exception:

Error 500: Internal Server Error

URI
    /article/articleLiked/1
Class
    javax.servlet.ServletException
Message
    Could not resolve view with name '/article/articleLiked' in servlet with name 'grailsDispatcherServlet'

Also, even after I manually go back to the articleList page, the value of getLikesCount() method output is still 0. What's causing all this trouble?

UPDATE:

Just in case you were wondering, my showArticleList() method looks like this:

def showArticleList(){
        render (view: 'articleList',  model: [ articles: getArticle(), articleLikes: getArticleLike()]);
    }

Solution

  • OK, I've found the problem. I've changed the Article declaration line to

    Article article = Article.findById(params.getIdentifier())
    

    and what is more, the problem was also within my if-else - I've been creating new ArticleLike object by using types as arguments instead of field names declared in my Domain class, so it should be

    }else{
                al = new ArticleLike(article: article, serviceUser: user, liked: true)
            }
    

    instead of

    else{
                    al = new ArticleLike(Article: article, ServiceUser: user, liked: true)
                }