Grails findBy query with foreign key - grails

I'm trying to fetch a user profile picture from the DB by calling the getProfiePicture() method on User object.
Method call from view:
<p>${user.getProfilePicture()}</p>
User.groovy domain class:
class Picture {
User user
String url
boolean profile = false
boolean verified = true
static belongsTo = [user: User]
static constraints = {
}
}
Picture.groovy domain class:
class User {
static hasMany = [pictures: Picture]
String uid = UUID.randomUUID().toString()
String username
String password
String getProfilePicture() {
log.debug("ID: " + id)
log.debug("UID: " + uid)
log.debug("Pictures: " + pictures)
return Picture.findByUserIdAndProfile(id, true)
}
}
Picture table:
Problem
I'm getting this error when I'm trying to get the profile picture:
Class
org.codehaus.groovy.grails.exceptions.InvalidPropertyException
Message
No property found for name [userId] for class [class foo.Picture]
What am I doing wrong?
I'm using:
Grails 2.4.4

The getProfilePicture() method inside your User domain class should return the following:
Picture.findByUserAndProfile(this, true)
The reason you're getting that error is because you are trying to find a Picture instance by userId, a field which doesn't exist.

You can implement getProfilePicture as following:
String getProfilePicture() {
Picture.where { user == this && profile == true}.first().url
}
Alternatively you can use a dynamic Finder (as shown in the comments). By the way: the Picture Class does not need to create the user Attributes twice. static belongsTo = [user: User] is enough.

Related

The user name is stored in an a connected object

I'm using grails and I have the following domain classes:
class User {
transient springSecurityService
String password
static belongsTo = [person: Person]
}
And
class Person {
String name
String emailAddress
....
}
I would like to use the person object's email address as the username in Spring Security.
According to the Spring Security manual, that just takes setting the property of grails.plugins.springsecurity.userLookup.usernamePropertyName to the non-"username" field.
I've tried person.emailAddress, and that doesn't work.
How can I get Spring security to use the Person reference to the User? I can't put the password on the Person class, and I've tried to use inheritance (that brings up other issues).
So I've traced this down to GormUserDetailsService, where this is being called and implimented. The code that is used to find the user is:
def user = User.findWhere((conf.userLookup.usernamePropertyName): username)
if (!user) {
log.warn "User not found: $username"
How would I structure the userNamePropertyName so that I could get it look through the child property?
It's bad idea. Just replace email to User, but if you want to use this field in person, create link to this field.
class User {
transient springSecurityService
String password
String email
static belongsTo = [person: Person]
}
and Person:
class Person {
String name
String emailAddress
....
String getEmail(){
user.email //if relations OneToOne
}
static hasOne = [user:User] //if relations OneToOne
}
You should stay relations OneToOne, because I can't imaginate in what case it should be OneToMany
UPD. Or you can try try this one:
class User extends Person{..}
and in spring security config write just email, but i'm not sure.

How to write constraints for hasMany properties in grails

I have three classes in grails application
class Category {
String name
}
class Application {
String name
static hasMany =[specialCategoryies:SpecialCategory]
}
class SpecialCategory {
Category category
Integer points
static belongsTo =[application:Application]
}
Here while I am saving the applicationInstance I don't want save duplicate
specialCategories values like ..specialCategories does not have same
category value again ..
application.addToSpecialCategoryies(newSpecialCategory(category:Category.get(1),points:2))
application.addToSpecialCategoryies(newSpecialCategory(category:Category.get(1),points:3))
here i application instance should rise error that category value repeated..
so how define constraints for hasMany properties in domain class......?
suggest how to write constraints to avoid duplicate values of category
You might try using a custom validator in your Application constraints section. For example, one way to check for duplicate property values is to collect the values into an array and compare them to the corresponding unique array (with duplicated elements removed):
class Application {
String name
static hasMany =[specialCategoryies:SpecialCategory]
static constraints = {
specialCategoryies validator: { specialCategories, obj ->
def specialCategoriesIdArray = specialCategories.collect {it?.category?.getId()}
return (specialCategoriesIdArray.size() == specialCategoriesIdArray.unique().size())?true:'application.validator.specialcategoryduplicate.error'
}
}
}
When trying to save a special category with an existing category, it will throw a validation error when saving. You can test with the following:
def cat1 = new Category(name:"Cat 1").save(flush:true)
def cat2 = new Category(name:"Cat 2").save(flush:true)
def app = new Application()
app.name = "Test"
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(1), points:2))
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(2), points:2))
app.addToSpecialCategoryies(new SpecialCategory(category: Category.get(1), points:3))
if ( app.save(flush:true) ){
log.info "Saved!"
} else {
log.error "NOT Saved. Error:"
app.errors.each {
log.error it
}
}

Prevent grails from fetching domain object

I have an image which belongs to a user
class Image {
static belongsTo = [user: User]
String name
String path
}
class User {
String name
}
How can I get the user Id without fetching the user in the database :
myService.doIt(Image.get(1).user.id)
fetches the user (I just need the id here)
Use the dynamic "fooId" property for a domain class property "foo":
myService.doIt(Image.get(1).userId)

Grails one-to-many / wrongly deleting all "manys"

i have the following (simplified) domain classes
class Filter {
String name
static hasMany = [answers:Answer]
static belongsTo = [user:User]
}
class User {
String name
static hasMany = [answers:Answer, filters:Filter]
}
class Answer {
String text
}
Then i add answers to the user which is working perfectly. The problem occurs when i delete 1 answer of a user:
def delete = {
def answer = Answer.get(params.id)
def users = User.withCriteria() {
answers{
eq("id", answer.id)
}
}
for (user in users)
user.removeFromAnswers(answer)
answer.delete(flush:true)
redirect(action:"index")
}
What happens here is that ALL user --> answer associations get deleted.
I only want to delete this 1 answer and of cause all associations the answer is used.
I know this has to do with the missing belongsTo, but i can't use it because a ansswer can either belong to a user or to an filter...
You can add the belongsTo to set them to nullable:
class Answer {
String text
static belongsTo = [user:User, filter:Filter]
static constraints = {
user nullable:true
filter nullable:true
}
}
and then just delete the Answer directly in the Controller:
def delete = {
def answer = Answer.get(params.id)
answer.delete(flush:true)
}
GORM will take care of the rest the cascading for you.

grails - how to save ArrayList in db

I use grails-1.3.2 and hbase plugin.
I have some difficulty in creating one-to-Many association with
hbase (i can work with hibernate), so
i decided to try create one-to-Many association with using ArrayList.
Here are my domain classes and controllers:
class Contacts {
String con
static constraints = {}
}
class ContactsController {
def create = {
def contact = new Contacts()
contact.con = params.con
contact.save(flush:true)
}
}
class User {
String firstname
String lastname
// static hasMany = [contact: Contacts]
static ArrayList<Contacts> contact
static constraints = {}
}
class UserController{
def create = {
def user = new User()
user.properties = params
user.save(flush: true)
}
def addContact = {
def user = User.get(params.userID)
def contact = Contacts.get(params.contactID)
user.contact.add(contact)
user.save(flush:true)
}
}
In addContact action user.contact = null, so it can not work.
In user does nor appear contact field.
Can someone help me understand what i have to do for saving ArrayList in db?
I don't know anything about hbase, but the static contact property of the User class looks very suspicious. The fact that this property is static, implies that every user has the same contact list, which seems unlikely to be the desired behaviour.
In a standard GORM domain model - assuming you want each User to have their own contact list - this would be defined
class User {
String firstname
String lastname
static hasMany = [contact: Contacts]
}
Although it looks like we're also defining a static property here, it's actually just the definition of how the Contact and User classes are related (AKA mapping) that is static. The contact property that is dynamically added to the User class is non-static.
Aside
I recommend renaming the Contacts class to Contact and the contact property to contacts. The GORM mapping would then look like this:
class User {
String firstname
String lastname
static hasMany = [contacts: Contact]
}

Resources