How to insert data to four tables from one view in Grails? - grails

I have four domain classes in my Grails based web application (first I've ever made):
class Receipt
{
String title
Date dateCreated
static hasMany = [articles: Article]
static constraints =
{
title blank: false, unique: true
}
}
class Article
{
String name
Quantity quantity
TypeOfArticle typeOfArticle
static hasOne = [quantity:Quantity, typeOfArticle:TypeOfArticle]
static constraints =
{
quantity unique: true
}
}
class Quantity
{
Integer quantity
Article article
}
class TypeOfArticle
{
String type
Article article
}
How can I add one Receipt together with all details on one view?
I want to make it look like on this picture:
http://i.stack.imgur.com/uNVzW.png
I hope you'll be able to help me! Thank you in advance!

You might want to look up Command Objects. It looks like you are trying to have someone enter data into one form that spans multiple classes. You can create a Command Object that has fields from all four classes. You use that object for the gsp fields, then capture in the controller method and validate the data; then create your actual Receipt, Article, etc.

You can get parameter in your controller action,In action you can simply write object.propertyName=params.propertyName and after getting all parameters you can simply store it by calling object.save(). you can do the same process for all four tables..

Related

How to make ID column visible in the list view

I have the following Groovy Domain class and generated scaffold controller for it.
When I create a Book row in the table, the ID column is invisible on the list view.
Is there anyway to make ID column visible on the view? I tried visible:true but it seems not making any difference.
class Book {
String bookAuthor
static constraints = {
bookAuthor blank: false, maxSize:30
}
static mapping = {
version false
id generator: 'sequence',
params: [sequence:'s_book_seq']
}
}
Edit the generated scaffolding views and add an id field manually. If you need to do this for a large number of domain classes, modify the scaffolding templates instead; you can install the templates using grails install-templates, they will be copied into src/templates

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

grails: scaffolding create view for domain with hasMany relation

Let's assume the following (simplified) domain classes:
class Person {
static hasMany = [stringProperties: StringProperty]
static constraints = {
}
}
and
class StringProperty {
String name
String value
static constraints = {
name blank:false
value blank: true
}
}
When scaffolding generates the create view, there is no option in the gsp to create a StringProperty from Person.
Does a plugin exist or does somebody know a best practice, that can render a sort of create ui that allows to create members of a hasmany relation.
I'm just asking before i take the time to modify the scaffolding templates.
This is one of the areas where a plugin or enhanced scaffolding would be welcomed by the community. If I had the time I would take the information presented here and make a plugin for it. I have used this approach a few times and it works well.

domains have some common fields,extends domain or embedded?

when i design database.I use embedded to embed common fields.but it's can't init dateCreated and createdBy,what'd i do?extends domain or embedded is right way to handle common fields?
code to say?
class Created {
Date dateCreated
Long createdBy
def beforeInsert()
{
dateCreated= new Date()
createdBy=0
}
}
class Updated {
Date lastUpdated
Long updatedBy
//it works?
def beforeUpdate(){
lastUpdated=new Date()
updatedBy=0
}
//it works?
def beforeInsert(){
lastUpdated=new Date()
updatedBy=0
}
}
class CreatedUpdated {
Created created
Updated updated
//Must use the embedded option, or the type of exception, can not find CreatedUpdated
static embedded = ['created','updated']
}
class Term {
String name
CreatedUpdated createdUpdated
static embedded = ['createdUpdated']
Term parent
static hasMany =[terms:Term]
static mapping = {
version false
}
String toString()
{
name
}
static constraints = {
name unique:true,size: 1..20
parent nullable: true
createdUpdated display:false,nullable:true
terms display:false
url url: true
}
}
or use extends?
class Term extends CreatedUpdated{
String name
Term parent
static hasMany =[terms:Term]
static mapping = {
version false
}
String toString()
{
name
}
static constraints = {
name unique:true,size: 1..20
parent nullable: true
terms display:false
url url: true
}
}
`
what is right to me?
I'd definitely make this example embedded rather than inherited. I don't think you should make this call based solely on the fact that objects contain common fields. Instead, you should use inheritance if it makes sense for your model using standard OO design techniques. For example, if "myClass is a myBaseClass" doesn't hold true, inheritance is probably the wrong solution.
In general, I'd stay away from classes like CreatedUpdated that are just a collection of properties and not an actual object from your domain. Java/Groovy has only single inheritance, so this only works if you have one base class like this.
Also, for that particular case, created and updated timestamps can automatically be applied by GORM. If you're using spring security, check out the audit-trail plugin for automatically creating createdBy and updatedBy columns.
In this particular case audit-trail plugin should suffice the requirements. However if you have such requirement for other fields wherein no plugin is available, then one of the possible solution could be to inject such common fields at compile time via AST Transformation. Internally audit-trail plugin uses this concept to inject those fields. Depending upon your requirement you can either use Global AST Transformations or Local AST Transformations.

Resources