Read Strings from an Object - grails

sorry for this simple question. However, I am confused.
I want to read all Strings from the database.
Basically I am having a EmailSettings emailAddresses = new EmailSettings() object in my controller and want to read all emails saved in the emailSettings Domain object. The class looks like that:
class EmailSettings {
String emailAddress
static constraints = {
emailAddress(blank: false, nullable: false, email: true)
}
}
My problem is I do not get the saved email addresses out of the emailAddresses Object. I tried it with list(), getEmailAddress(like emailAddresses.getEmailAddress().toString(), which is null, even though in the db ARE email addresses saved under this domain object), but it does not work or I get an exception.
Any suggestion how to get the email addresses, which are saved in the db as an array?
I appreciate your answer!

You are creating a new domain instance by newifying it, which will never give you the results that is persisted in db. To get emailAddress from all EmailSettings in db, you can use as:
EmailSetting.all*.emailAdress
or
EmailSetting.withCriteria {
projections {
property 'emailAddress'
}
}
or can also use DetachedCriteria with above projection.
UPDATE
First approach will be expensive because all of the rows will be fetched and then emailAddress from each row will be derived. I totally missed mentioning why I had the second approach with usage of Criteria. Using Projections, you would only get the properties you would need instead of fetching the row itself. Thanks to Graeme.

Related

How to return a composite object in Neo4j/Cypher

I'd like to return a composite object from Neo4j using cypher to tidy up my queries.
To give an example, I have a user account object that has permissions stored as relationships. The permissions are complex objects so can't be nested, they are now linked by the relationship [:HAS_PERMISSION]. What i'd like to do is return the full complex object with the permissions already nested, like in the example JSON object below
e.g.
permissions:
{
action:'delete',
resource:'blog posts'
}
{
action:'edit',
resource:'users'
}
core user account:
{
username:'Dave',
email:'dave#test.com'
}
What i'd like:
{
username:'Dave',
email:'dave#test.com'
permissions: [{action:'delete', resource:'blog posts'},{action:'edit', resource:'users'}]
}
The query I currently have:
MATCH(user:UserAccount)-[:HasPermission]->(permission:Permission)
WITH {user:user, permissions:collect(permission)} AS UserAccount
RETURN UserAccount
The problem is this doesn't quite return what i'm after, it returns this:
{
user: {
username:'Dave',
email:'dave#test.com'
},
permissions: [{action:'delete', resource:'blog posts'},{action:'edit', resource:'users'}]
}
Please note: I'd really like to add the permissions list to the existing user object i'm returning please. I'd like to know how to save me having to explicitly declare all of the properties I need on the new object (if it's possible).
You can design the objects as you need:
MATCH(user:UserAccount)-[:HasPermission]->(permission:Permission)
WITH { username:user.username,
email: user.email,
permissions:collect(permission)
} AS UserAccount
RETURN UserAccount
Update
You can use apoc.map.setKey:
MATCH(user:UserAccount)-[:HasPermission]->(permission:Permission)
WITH user, collect(permission) as permissions
CALL apoc.map.setKey( user, 'permissions', permissions ) YIELD value as UserAccount
RETURN UserAccount
Since Neo4J 3.1 you can use Map projections
MATCH (user:UserAccount)-[:HasPermission]->(permission:Permission)
WITH user, collect(permission) as permissions
RETURN user{.*, permissions: permissions}
You can use the set keyword to set a property in any object, we can use this to our advantage.
However Neo4j only allows us to store primitive arrays as collections in properties and does not allow us to store a map such as
[{action:'delete', resource:'blog posts'},{action:'edit',
resource:'users'}]
so we will need to simplify your permissions node model a little.
What you will end up getting is something along the lines of
{ username:'Dave', email:'dave#test.com' permissions: ['delete
blog posts','edit users'] }
The advantage is that you can have everything in just one object and take the contents of the entire UserAccount node.
MATCH(user:UserAccount)-[:HasPermission]->(permission:Permissions)
WITH user AS UserAccount, collect(permission.action +" "+ permission.resource) as permissions set UserAccount.permissions=permissions
return UserAccount
TLDR: Its possible to get the data without formatting the entire object like #stodb's example. But this method cannot output complex map collections and can only output primitive arrays as collections.

How to nullify the fields that fail validation and save the domain?

Suppose there is a domain as defined below.
class Book {
String title
Author author
}
Now, i save an instance of this domain. The author domain has some constraints. So, during save the validation for author fails now instead of not saving the whole domain i want to nullify the author(The author can be null) and save the title string as it was. In other words how do i nullify any number of fields whose validation failed and save rest of the properties values? Is there a convenient way to do so? Thanks!
This could be one of following :
In beforeInsert hook do something like below:
def beforeInsert() {
this.validate()
if(this.hasErrors()){
// get all errors and iterate through it and set the field to null for same
}
}
While saving the domain you could use
domain.save(validate:false)
Thanks!!

Grails/Gorm: how to filter a list of domain objects without affecting the database

Say we have something like the standard Book domain object and bookCategory object. In my controller I want to return a subset of list of books to the view. That subset is not achievable using a find query. When I try to filer the return object, it deletes relationships from the database!
I tried this:
class BookCategory{
String name
static hasMany = [books:Book]
}
class Book{
String title
}
def myController() {
def categories
categories = BookCategory.list()
def user = getCurrentUser()
categories.each { category ->
category.books.removeAll { book ->
!isBookBannedForThisUser(book.title, user)
}
[bookCategories: categories]
}
}
The problem is that it permanently removes these books from the categories for all users from the database!!!
I tried putting the method in a service and using a readonly transaction, but this did not help.
I assume that even if I copy all the categories and books into new list, they will still update the DB as they will still have the book IDs (which I need)
Saving to the database when you dont say save() is very dangerous. is there a way to disable this feature completely?
There is a fundamental flaw in your approach. Do not modify your domain instances if you don't intend to have the changes persisted. Doing so is going to cause you headaches.
Your domain model is suppose to be your system of record. Any changes to it are suppose to be persisted.
If you need to gather up data and manipulate it without having it reflected in your domain model then use a DTO (data transfer object) or similar pattern.
Simply calling .discard() will discard the changes you have made from being persisted when the session automatically flushes.
Instead of working against the framework, and disabling behavior, change your approach to be correct.

grails validation when fetching rows

Is it possible to fetch a default value in grails if a column is null? If I were to represent following query via grails domain object then how could I achieve it:
SELECT IFNULL(empsalary,0.00) from Employee;
Domain object:
class Employee{
Integer id,
Float empsalary
static constraints = {
id unique: true, blank:false
empsalary nullable:true
}
}
making empsalary nullable false isn't an option due to existing data
validator on empsalary seems to work when inserting rows but not while data fetch
we can consider writing say getEmpSalary() method on domain and perform check there but there are several other fields we need to do this so trying to avoid massive code changes
If you want a default value to come out of the database without having to code anything into your classes, I suggest you update every row where it is null and set it to 0 in the database. If data is getting inserted from another application and that application is allowing a null value, put a 'DEFAULT 0' on your database column.
Grails also offers an "afterLoad" event which is run when a domain object gets loaded from the database. See the documentation here: http://grails.org/doc/2.3.7/guide/GORM.html.
I think you can do this with HQL:
def salary = Employee.executeQuery('SELECT COALESCE(empsalary, 0.0) FROM Employee')[0]
See this SO Question.
Please try setting Float empsalary = 0.0 in your domain object.

Modify params before saving domain object

I needed a domain class that held a list of Strings. It seems fairly well-known that GORM can't handle this, so I've worked around it. At first I tried using getters and setters in the domain class, but that caused problems. Then I found on Stack Overflow a way to use afterLoad() and beforeValidate() to rewrite properties as shown below. This has worked well to allow me to turn the List into a String for persistence and back to a List for use in the app.
class Entries {
// persisted to database
String _entry
// exposed to app
List entry
static transients = ['entry'] //don't try to persist the List
def afterLoad() {
// split the String from the database into a List
entry = _entry?.split('\\|')
}
def beforeValidate() {
// join the List into a String for persisting
_entry = entry.join('|')
}
static constraints = {
_entry maxSize:4000
}
}
This works fine programmatically. The only problem is that the Grails scaffolding can't deal with this, even if I try to enter a pipe-delimited string. I understand the reason why is that the scaffolding creates a form field for _entry, so entry is null when it tries to save the object. And beforeValidate() relies on a List of Strings to work.
I tried to get around this in the controller, by setting params.entry = params._entry, prior to the call to new Entries(params). [I recognize that this is not a perfect solution, but this was my first pass at getting the form working.] And then I added a test in beforeValidate() to set entry = _entry if entry was null. Basically:
EntriesController.groovy:
params.entry = params._entry // I added this line
def entriesInstance = new Entries(params)
Entries.groovy:
def beforeValidate() {
if( entry == null ) entry = _entry // I added this line
_entry = entry.join('|')
}
I thought that would allow me to enter pipe-delimited strings into the scaffolded Create Entries form and get something into the database.
To my surprise, though, I found that both entry and _entry were null in beforeValidate(), even though I printed and verified that params contained both keys in the controller. I don't understand why this happens. How did my adding a new key to params result in nulls arriving in the domain class?
The follow-up question is, of course, what's the right way to make the scaffolded Create Entries form accept a pipe-delimited String that makes it into the database?
I needed a domain class that held a list of Strings. It seems fairly well-known that GORM can't handle this, so I've worked around it.
I don't agree with you here
class Xyz {
static hasMany = [entries: String]
}
Should create a seperate table to hold your list of strings (It will actually be a Set). Here are the docs

Resources