Grails: How to assign domain field = someValue fetching from database - grails

Suppose I have two domains:
class Country {
String name
String Desc
static hasMany = [organizations: Organization]
}
class Organization {
String name
Country country
static belongsTo = [country:Country]
}
Note: In case of create Organization, countries will be listed in a combobox.
Suppose I have 4 row in my database which I have fetched from bootstrap.
**Name** **Desc**
US USA
CA CAN
NP NEP
IN IND
I want to assign USA as a default value while create a Organization. Is there a way to do it from domain level not gsp?

I think the load method is your best bet, although it requires that you know the id of the instance that you want to be the default. It's not a good idea to hard-code this because it could change in the future. But you can look it up when the app starts and save the id, e.g.
class BootStrap {
def grailsApplication
def init = {
def usa = Country.findByName('US')
grailsApplication.config.COUNTRY_US_ID = usa.id
}
}
Use whatever Config key you want of course.
Then change the Organization class to call load in its constructor:
import grails.util.Holders
class Organization {
Organization() {
if (Holders.config.COUNTRY_US_ID) {
country = Country.load(Holders.config.COUNTRY_US_ID)
}
}
String name
static belongsTo = [country:Country]
}
Note that I removed the Country country property because it's redundant; adding that belongsTo creates a property with the same name as the map key ("country") and with the same type as the map value (Country). It doesn't hurt to have it, but it's not needed.
The reason load is appropriate here is that it doesn't hit the database until you access a persistent property other than id. So you're configuring it to lazily retrieve the real instance if necessary, but if you overwrite the value with a different instance, you won't have wasted a database lookup for the initial population. Turn on SQL logging to verify this.

Related

Creating one-to-many & many-to-many for same domain class in grails

I want to create a domain class as like , One user can post many orders [Bidirectional] and one order can be liked by many users [unidirectional].
I have written a domain class as shown below ,
Class User {
String userName;
List orders
static hasMany = [Order]
}
Class Order {
String orderId
String orderName
//Indicates this order belongs to only one user
static belongsTo =[owner : User ] // Bidirectional
//Indicates order can be liked by many users
static hasMany = [likedUser : User] //Unidirectional
}
But I am getting am error saying invalid schema . Any body please help...
This post looks similar to my question but I am not getting , Please help.
First, order is a reserved word in SQL. Since GORM by default creates a table with the same name as your class, you'll need to either rename your class or provide a different name to use when mapping to SQL tables.
For example:
class Order {
static mapping = {
table 'user_order'
}
// ...
}
Another problem is that Order contains two associations to User. You need to tell GORM which one of these that is the bi-directional association from User to Order. That can be achieved using mappedBy, like this:
class User {
String userName
static hasMany = [orders: Order]
static mappedBy = [orders: 'owner']
}
Hope this helps.

Need some explanation to understand how Grails works

I'm new to Grails, some things are still vague for me.
I want to create a Twitter-like app. As a user has both a followers and a following groups, I've created a GroupMyTwitter domain.
What I don't understand, is the logic behind this. My GroupMyTwitter domain is like this :
class GroupMyTwitter
{
String name;
static constraints = { name blank : false; }
static hasMany = [users:UserMyTwitter];
static belongsTo = [owner:UserMyTwitter];
}
Then every time I create a user I also create two groups associated to him :
GroupMyTwitter followers = new GroupMyTwitter (
name:"followers",
owner: user).save(flush: true, failOnError: true)
// And same for followings
Now I simply wonder... how can I access these groups to get the followers/ings count, add or delete some?
Thanks for your help.
Based on the hasMany and belongsTo variables gorm automatically creates some instance fields for you:
static hasMany = [users:UserMyTwitter];
This will create a field users of type Set inside GroupMyTwitter.
You can access this Set like any other field:
followers.users.add(userA) // add a user
followers.users.remove(userB) // remove a user
followers.users.size() // number of users
// don't forget to save the group after you modfied the `users` collection:
followers.save(failOnError: true)
Depending on your needs it might be useful to use a List instead of a Set:
class GroupMyTwitter {
List users
static hasMany = [users:UserMyTwitter];
...
}
This causes Gorm to use a List for the users collection instead of a Set.
A List has a defined order and allows you to access certain elements by index:
UserMyTwitter user = followers.users[4] // get the 5th user

GORM/Grails - add extra column to a joinTable expression

I have a Domain Class setup similar to this
class NewsStory {
String headline
static hasMany = [channels:Channel]
static mapping = {
table 'NewsStory'
addresses joinTable:[name:'Article_Channel', key:'ArticleId', column:'ChannelId']
}
}
in the Article_Channel table i need to have an extra column populated called ArticleType say. Its value will always be the same e.g. 'news' for this domain class, but will be differnt for others e.g. 'blog'
Channel is just something like 'Security' etc
Is there a way?
Thanks
One option would be be to create your own many-to-many mapping class and add the field in there.
http://grails.org/Many-to-Many+Mapping+without+Hibernate+XML
So, for example:
class ArticleChannel {
NewsStory newsStory
Channel channel
String articleType
}
Then, your NewsStory and Channel classes would hasMany the ArticleChannel class.

In Grails, how can I order eagerly fetched domain records?

Greetings, I would like to order eagerly fetched domain objects that another domain class owns in a 1:m relationship, but cannot figure how to do this. When I try with a simplified project, I get an error. Below are my attempts:
class Picture {
String name
static hasMany = [comments:Comment]
static mapping = {
comments(lazy:false, sort:'content', order:'desc')
}
}
class Comment {
String content
Date dateCreated
static belongsTo = [Picture]
}
Now, when testing how the record fetch with println Picture.get(1) as JSON, I get the following error:
java.sql.SQLException: Column not found: COMMENTS0_.CONTENT in statement [select comments0_.picture_comments_id as picture1_0_, comments0_.comment_id as comment2_0_ from picture_comment comments0_ where comments0_.picture_comments_id=? order by comments0_.content desc
Without sort:'content', order:'desc', the Comments are in random order but no error.
I ended up doing the ordering after the list of children was already fetched, at the time I need them in the code. Something like this:
def sortedComments = myPicture.comments.sort{it.content}.reverse()
Has the advantage of allowing unlimited sorting configurations as needed, as opposed to only one as retrieved by default.

Sorting query results according to parent property in grails

Is it possible in grails to sort query results according to a property of a parent class in a relationship. E.g. I have a user domain class which has a one to many relationship with a list of Tasks.
When showing the list page of the Tasks domain class, I want to be able to sort the list of tasks by the associated User name.
class User {
String name
String login
String group
List tasks = new ArrayList()
static hasMany = [tasks:Task]
}
class Task {
String summary
String details
User user
static belongsTo = [user:User]
}
I can do something like this
Task.list([sort:"user", order:"asc"])
But this sorts by the user.id, is there a way to specify the sort to be on the user.name?
You can do it using Criteria
def criteria = Task.createCriteria()
def taskList = criteria.list {
createAlias("user","_user")
order( "_user.name")
}
iirc, grails sorts by using toString() and since you have not supplied one, it uses the id.

Resources