Override Grails dateCreated and lastUpdated for test data only? - grails

I have several Grails 2.1 domain classes that include dateCreated and lastUpdated fields that GORM manages automatically, eg:
class Person {
Date dateCreated
Date lastUpdated
String name
}
I want Grails to automatically fill in these fields at runtime, but I also want to create some test data where I can manually define the values of these dates. The trouble is that Grails automatically sets the values if these fields with an interceptor even when I have specifically set them.
I have seen this SO question which describes how to allow changes to dateCreated, but I need to change lastUpdated as well. Is this possible?

Whoops, my mistake, the approach in the other question does work, but the entity in question was separately being saved somewhere else. It also seems that you need an explicit flush to make things work:
def withAutoTimestampSuppression(entity, closure) {
toggleAutoTimestamp(entity, false)
def result = closure()
toggleAutoTimestamp(entity, true)
result
}
def toggleAutoTimestamp(target, enabled) {
def applicationContext = (ServletContextHolder.getServletContext()
.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT))
def closureInterceptor = applicationContext.getBean("eventTriggeringInterceptor")
def datastore = closureInterceptor.datastores.values().iterator().next()
def interceptor = datastore.getEventTriggeringInterceptor()
def listener = interceptor.findEventListener(target)
listener.shouldTimestamp = enabled
null
}
def createTestPerson() {
def luke = new Person(name: "Luke Skywalker")
withAutoTimestampSuppression(luke) {
def lastWeek = new Date().minus(7)
luke.dateCreated = lastWeek
luke.lastUpdated = lastWeek
luke.save(failOnError: true, flush: true)
}
}

If it is an integration test you can use an hql update statement to manually set lastUpdated.

Related

Groovy/Grails iterating the list and formatting the number using NumberFormat(US style)

I have a Employee domain class and properties name,age,salary,annualPackage.
When I call Employee.list(). All the properties will be persisted.
Now I want to apply numberformat for salary and annualPackage properties.I can achieve it by:
NumberFormat.getNumberInstance(Locale.US).format(Employee.salary.get(0))
But How to format all the values of salary and annualPackage inside the list.
This should do it
def formatter = java.text.NumberFormat.getNumberInstance(Locale.US)
def formattedValues = Employee.list().collect {
[
salary = formatter.format(it.salary)
annualPackage = formatter.format(it.annualPackage)
]
}
You can do this way
List<Employee> employees = Employee.list()
def formatter = java.text.NumberFormat.getNumberInstance(Locale.US)
def formatted = employees.collect { formatter.format(it.salary) }
Note: you should use getCurrencyInstance(Locale.US) instead of getNumberInstance(Locale.US)

get a specific property for a domain in Grails

i'm making a tables cleaning service that takes the table name and the date field as arguments , here is the service code :
def cleanTables(tableName , dateField) {
def comparisonDate
def numOfRecordsDeleted
use (TimeCategory){
comparisonDate=new Date() -1.year
}
numOfRecordsDeleted=tableName.where { dateField <=comparisonDate }.deleteAll()
log.info("deleted : " +numOfRecordsDeleted)
}
i'm successfully passing to this service the table name but i can't pass the date field , so how to get a specific property from a domain for example a domain named Payments got a property dateCreated , so i pass to my service Payments and dateCreated.
With where queries you have access to criteria query methods such as eq(), or in this case, le(). Those methods take the name of the property as an argument, which is what you need. I tweaked the code a bit because you're actually interacting with domain classes, not tables. Small distinction, until you start working with HQL.
def cleanDomainClass(String domainClassName, String dateField) {
def domainClass = Class.forName("some.package.$domainClassName")
def comparisonDate = use (TimeCategory) { new Date() -1.year }
def numOfRecordsDeleted = domainClass.where { le(dateField, comparisonDate) }.deleteAll()
log.info("deleted : $numOfRecordsDeleted")
}

Sorting Parent and Child in Grails Controller

Hi I'm trying to perform a sort in a controller of parent and child before rendering a json file but I'm not sure how to go about doing it. Here's what I have (excerpt of original code):
class Parent{
static hasMany = [children:Child]
String name
Date dateCreated
}
class Child {
static belongsTo = [parent:Parent]
String name
Date dateCreated
}
In my controller .groovy file I have :
def list(){
def result = Parent.listOrderByDateCreated(order: "desc")
.... more code ....
withFormat{
json {render result as JSON}
xml {render result as XML}
}
}
and the above works (parent is sorted by date created) but I'm not sure how can I sort all the children by date created within the list.
Thank you for your help in advance. Also I'm using Grails 2.3.2
One way is to assume you always want the children sorted by the dateCreated. Add the following to your Parent domain:
static mapping = {
children sort: 'dateCreated'
}
Another way would be to do the sort after you've pulled the results:
def sortedChildren = parent.children.sort { it.dateCreated }
If there is a fancier "grailsier" way to do this via finders or criteria, I do not know.

How can i set default value in grails domain class

Is there any way to set a default value to domain class property?
I have a class called PayMethod, where I want the name property to default to "Cash" and I want this default value when I create this table, is this possible using Constraints?
package abc
import util.UserUtil
import embed.AuditUser
class PayMethod {
String name = "Cash"
AuditUser audit = new AuditUser()
static embedded = ['audit']
static constraints = {
name blank: false, size: 5..30, unique: true
}
static mapping = {
table 't01i0010'
id column: 'F_ID', precision: 4, scale: 0
name column: 'F_NAME', length: 30, defaultValue: 'Cash'
version column: 'F_REVISION'
}
def authUserService
int insertIndex = 0
int updateIndex = 0
static transients = ['authUserService', 'insertIndex', 'updateIndex']
def beforeInsert = {
audit.entryUser = UserUtil.user()
audit.entryDate = new Date();
}
def beforeUpdate = {
audit.reviseUser = UserUtil.user()
audit.reviseDate = new Date();
}
def afterInsert = {
if(insertIndex == 0){
def user = audit.entryUser
def date = audit.entryDate
log.info "POST INSERT => ENTERER: ${user} ENTERED: ${date}"
}
insertIndex++
}
def afterUpdate = {
if(updateIndex == 0){
def user = audit.reviseUser
def date = audit.reviseDate
log.info "POST UPDATE => REVISE: ${user} REVISED: ${date}"
}
updateIndex++
}
}
This will be possible in 2.2 which should be released this week or next. See http://jira.grails.org/browse/GRAILS-5520 for the relevant feature request. The syntax will be
static mapping = {
name defaultValue: "'Cash'"
}
For now you'll need to do what you're doing - set the value as the default value of the field. You can manually update the database schema, or do the work as part of a migration.
To build on the previous answer, you can use the defaultValue attribute in Grails 2.2 but you need to be careful to put double and single quotes around default values for String properties and double quotes around integer properties so that the default values appear correctly in the DDL. So, for instance, you need to use:
static mapping = {
myStringProperty defaultValue: "'Cash'"
myIntProperty defaultValue: "0"
}
If you only use single quotes, you will end up with an error like "Column "CASH" not found"
Also, as far as I can tell, default values do not work for properties that are enums.
Had the same issue and using static mapping didn't work for me either (using 2.2.3); the below link provided me a functional answer (set the default value in your object declarations):
http://grails.1312388.n4.nabble.com/How-to-set-a-default-value-for-column-td1383753.html
For String, encapsulate with quotes; int/integer should just be the value.
Hope this helps!

where is bidirectional ? grails one-to-one, testing bidirectional (continue)

class Book {
String title
Date releaseDate
String ISBN
static belongsTo = [person:Person] // it makes relationship bi-directional regarding the grails-docs
}
class Person {
Book book; // it will create person.book_id
String name
Integer age
Date lastVisit
static constraints = {
book unique: true // "one-to-one". Without that = "Many-to-one".
}
}
There is a test which test if it is real bidirectional or not. As i understand it.
public void testBidirectional() {
def person = new Person(name:"person_c1", age: 99, lastVisit: new Date())
def book = new Book(
title:"somebook_c1",
ISBN: "somebook_c1",
releaseDate: new Date()
)
person.setBook (book)
assertNotNull(person.save())
def bookId = person.getBook().id
Book thatBook = Book.get(bookId)
assertNotNull(thatBook.person) // NULL !!!
}
So, i save a person with a book, and then i got that book from db by id. Then from that book i try to get back the person which book should refer to (because it should be bidirectional, right?). Eventually i got null instead of an instance of the person.
The questing is: how to make that test working?
i have found the solution how to get it working, but still can not understand why it does not work without 'refresh', see below:
public void testBidirectional() {
def person = new Person(name:"person_c1", age: 99, lastVisit: new Date())
def book = new Book(
title:"somebook_c1",
ISBN: "somebook_c1",
releaseDate: new Date()
)
person.setBook (book)
def p = person.save()
assertNotNull p
person.refresh() //load the object again from the database so all the changes made to object will be reverted
//person = Person.get(p.id) // BUT this also gets the object from db ...?
def bookId = person.getBook().id
assertNotNull bookId
def thatBook = Book.get(bookId)
assertNotNull(thatBook.person)
}
So, here as you can see i use 'refresh' to get it working, but why it does not work without 'refresh' but with the following line after 'refresh' - this one:
person = Person.get(p.id) // BUT this also gets the object from db ...?
If i just want to get object from database by id, then it would be without bidirectional?
Your problem is probably caused by the way that Hibernate works. Grails used Hibernate under the hood.
Even when you call "save", the object person may (and usually) not saved in database. That's because Hibernate is programmed to optimize the query, so it often waits to perform all query at then end of the Hibernate session.
That means if you don't call "refresh", the book-person relation (person.setBook) is still in memory, but not saved in database. Hence you can't get the book.person from book.
To enforce the save, you can use "refresh" like the previous answer, or use flush:true.
I still not try, but it's very likely that you will produce desired results with:
person.save(flush:true)

Resources