Reputation: 3
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
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
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 ;)
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
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
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