Richard
Richard

Reputation: 3

Grails controllers dynamic finders

I'm kinda new to Grails so I need help with this matter. Imagine I have these classes:

Class User{
String name
String nr

}

class Computer{

String processor
String ram
User user
}

Class Room{
String roomNr
Computer computer
}

I want to do a controller like this:

def print= {

        def user = User.get(1)

        def computer = Computer.findAllByUser(user) // all computers filtered by User

        [computer: computer]       
    }

The controller works good, but I want to be able to pass not only the computer instances, but also the Room's with that computer id's. I dont know how to do it, but would be something like this (same controller, same action):

def print= {

        def user = User.get(1)

        def computer = Computer.findAllByUser(user) // all computers filtered by User
        def room = Room.findAllByComputer(computer) ##

        [computer: computer]       
    }

Well, this is wrong because, where the ### is, 'computer' represents a list of id's and not a single id. As I am passing a list of computers to be printed in my gsp inside a g: each tag like this: (it. Processor, it. Ram). I dont know how to get all the rooms which are using the current computer in the each tag. This is a bit hard to explain, but basically my output would be:

<g:each in="${computer}"
Computer1:
Processor: ${it.processor}
Ram: ${it.ram}
Room: ????? (How to get here??)
</g:each>

Upvotes: 0

Views: 233

Answers (4)

Jim Norman
Jim Norman

Reputation: 749

You can use <g:set> to acquire a room reference inside your <g:each>. That way, the controller is not concerned with rooms. Generally, I like to gather all pertinent information that feeds the GSP in the controller, but there are exceptions, as in the case of some ancillary details.

Upvotes: 0

jjczopek
jjczopek

Reputation: 3379

I came up with something like this, but I didn't test it.

Controller:

def print = {

  def user = User.get(1)
  def computer = Computer.findAllByUser(user)
  def rooms = [:]

  // get rooms for that computer
  computer.each{

    def computerRooms = Room.findAllByComputer(it) // find all rooms where current computer is
    rooms.put(it.id, computerRooms) // map all the rooms with computer id

  }

  [computer: computer, rooms: rooms]      
}

View:

<g:each in="${computer}">
  Computer1:
  Processor: ${it.processor}
  Ram: ${it.ram}
  Rooms: <g:join in="${rooms[it.id]}" delimiter=", "/>
</g:each>

Rooms map uses computer id as a key and list of all rooms where that computer is as value. Of course If I understood you correctly ;)

EDIT

If you need access room details, you can replace join tag with another each tag, like this:

<g:each in="${computer}" >
  Computer1:
  Processor: ${it.processor}
  Ram: ${it.ram}
  Rooms: <br/>
  <g:each in="${rooms[it.id]}">
    Room id: ${it.id}
    Room number: ${it.number}
  </g:each>
</g:each>

And you can also implement the Room class toString() method, because join tag uses it to render text:

Class Room{
  String roomNr
  ...

  String toString(){
    roomNr
  }
}

Now when you use join tag on list of Room class instances, it will print room number.

Upvotes: 1

BadSkillz
BadSkillz

Reputation: 2003

It looks like you don't send the room variable to the view

[computer: computer]

Should be:

[computer:computer, room:room]

Upvotes: 0

hvgotcodes
hvgotcodes

Reputation: 120198

make the relationship bidirectional. Right now you store which Room has which Computer, but you don't go the other way, so you can follow a Computer to its Room. Check out

http://grails.org/doc/1.0.x/guide/5.%20Object%20Relational%20Mapping%20(GORM).html

specifically section 5.2.1.2, on bidirectional one-to-many relationships.

Be aware that Grails is build on best of breed technologies. One of those is hibernate. Being familiar with the underlying technologies will only help you.

So after all that, what I am getting at is your Computer class should have a reference to the Room that it is in. The Room class should have a list of Computers (assuming more than one computer can be in a room). The difficulty you will have is in understanding the cascading behaviour of hibernate, which depends on how you set up the relationship. If you run into trouble update this question or start a new one with the specific issue.

Upvotes: 2

Related Questions