Grails
  1. Grails
  2. GRAILS-8730

Grails: groovy 'findAll' strange behaviour

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Not A Bug
    • Affects Version/s: 2.0 final
    • Fix Version/s: None
    • Component/s: Controllers
    • Labels:
      None

      Description

      It's really a very strange thing.

      Having the following domain classes:

      class Game {
          List messages = new ArrayList()
          static hasMany = [messages: Message]
      }
      
      class Message{
          static belongsTo = [game: Game]
      }
      

      Controller for Game domain class:

      class GameController{
          def listGameMessages () {
              def offset =  params.offset
              println "offset: "+offset
              def messages  = Game.get(params.id).messages
              println messages
              messages = messages.findAll{
                  it.id > offset
              }
              println messages
              //render messages as JSON
          }
      }
      

      Output with some params from web page:

      offset: 0
      [id: 1, id: 2, id: 3, id: 4, id: 5]
      []
      

      But integration tests for this method work absolutely correctly!

      @Test
      void testListGameMessages(){
          def game = new Game()
          (1..5).each{
              game.addToMessages(new Message())
          }
          game.save(flush: true, failOnError: true)
          def gameController = new GameController()
          println game.id
          gameController.listGameMessages(game.id, 0) // i changed method parametres a little
      }
      
      offset: 0
      [id: 1, id: 2, id: 3, id: 4, id: 5]
      [id: 1, id: 2, id: 3, id: 4, id: 5]
      

      What's wrong? It's not joke at all.

      UPDATE:
      If use a hardcoded value in controller closure like:

              messages = messages.findAll{
                  it.id > 0 // instead of 'offset' 
              }
      

      it works great for this value!

        Activity

        Hide
        Burt Beckwith added a comment -

        parameters are always strings. GORM converts the parameter to get() calls to the correct type for you, e.g. in your Game.get(params.id) call it converts the string to a Long. But this doesn't happen elsewhere, so your loop is comparing strings to Longs.

        Either convert the parameter to a Long explicitly:

        def listGameMessages() {
           def offset =  params.offset as Long
           println "offset: " + offset
           def messages  = Game.get(params.id).messages
           println messages
           messages = messages.findAll {
              it.id > offset
           }
           println messages
           //render messages as JSON
        }
        

        or use the new parameter binding feature from 2.0:

        def listGameMessages(Long offset) {
           println "offset: " + offset
           def messages  = Game.get(params.id).messages
           println messages
           messages = messages.findAll {
              it.id > offset
           }
           println messages
           //render messages as JSON
        }
        

        Your test passes because you're using numbers and not strings like you would get in a real controller request.

        Show
        Burt Beckwith added a comment - parameters are always strings. GORM converts the parameter to get() calls to the correct type for you, e.g. in your Game.get(params.id) call it converts the string to a Long. But this doesn't happen elsewhere, so your loop is comparing strings to Longs. Either convert the parameter to a Long explicitly: def listGameMessages() { def offset = params.offset as Long println "offset: " + offset def messages = Game.get(params.id).messages println messages messages = messages.findAll { it.id > offset } println messages //render messages as JSON } or use the new parameter binding feature from 2.0: def listGameMessages( Long offset) { println "offset: " + offset def messages = Game.get(params.id).messages println messages messages = messages.findAll { it.id > offset } println messages //render messages as JSON } Your test passes because you're using numbers and not strings like you would get in a real controller request.

          People

          • Assignee:
            Burt Beckwith
            Reporter:
            Ilya A.
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development