Language-specific value in grails inList constraint - grails

Users of my application have the possibility of choosing some values from list. The values for that list are in simple domain class, Foo, which looks like that:
class Foo{
String name
static mapping = {
id name: 'name', generator: 'assigned'
version: false
}
}
Foo looks the same for every language my app uses. In another class I have a constraint saying that Bar must be in list of Foo. Sometimes user doesn't know what to choose, so he may choose something like "I'm not sure" (so this option should be in list to to meet the inList constraint). Thing is, "I'm not sure" is written differently in different languages. How can I append this value based on current messages to inList constraint?

In your controller you could do:
def theList = foo.list().name // Get any array of strings.
// If you actually need > 1 field then you probably need to
// put the g.message below in a map
theList << g.message(code:"im.not.sure")

I don't believe inList constraint will help you here - it's designed for a simpler use case than yours.
I'd add a method to the class getLanguages() that handles this, and then since you seem to be interested in validation, write a custom validator to make sure right values are saved.

Related

grails: how to properly edit/update a collection?

I just wasted half a day trying to figure this out, reading about some workarounds, and thinking "it can't be that bad - there must be a straightforward to do edit a collection in Grails, whethere using scaffolded views or my own."
Let's say I have this domain object:
class TreeGroup {
String name
List<Tree> trees
static hasMany = ['trees': MyTree]
}
Just to explain the choice of data structure - I need my records to be unique, but in the order I set. That's why I chose List, AFAIK one cannot rely on order in a Set. So there are 2 pieces to this question - 1) how to remove from any Collection, for example a Set, 2) is List the best replacement for Set in this context (preserving order).
I want to be able to create a group record with no trees in it and make 4 updates:
edit/save
edit the group record to reference 2 trees A and B
add another tree C
remove A
remove B and C
And obviously, I want the desired state after every step. Currently though, I can only add records, and if I even edit/save to list, the list elements are added to it again.
I am using the multiple select tag for this. It looks like this:
<g:select name="trees" from="${allTrees}" optionKey="id"
multiple="true" class="many-to-many"
value="${trees ? trees*.id : treeGroupInstance?.trees*.id}" />
and that's fine, in the sense that it generates an HTTP header with these variables on update:
_method:PUT
version:19
name:d5
trees:1
_action_update:Update
But the data binder only adds new elements, it never lets you edit a list.
What is the cleanest way to do it ? Is it me, not reading something obvious, or is this a design flaw of grails data binding (and of so, when/how will it be fixed) ?
Is there a way perhaps via a hidden HTTP parameter to clear the list before (re)adding elements ?
Thanks
I ended up doing this:
private repopulate(def domainObject, String propertyName, Class domainKlaz) {
if (params[propertyName] != null) {
domainObject[propertyName].clear()
domainObject[propertyName].addAll(
params[propertyName].collect { domainKlaz.get(it) }
)
}
}
and I am calling it in update controller method before save(), for every collection. OMG how ugly.

Determine Data Type

I have this code in my controller:
def cols = grailsApplication.getDomainClass('com.archie.Build').persistentProperties.collect {it.name}
The code above will allow me to list all the property names I have in Build class. Now, I would like to include also the properties data type, ie. boolean, String etc...
Somewhat like the output is:
[floorType:String, floorWidth:Float, ......]
Maybe not exactly like that, or maybe similar, but as long as I can return their data type. Can someone help? Thank you.
Each entry in persistentProperties is a GrailsDomainClassProperty, and this provides access to the type of the property as a Class object:
def props = [:]
grailsApplication.getDomainClass('com.archie.Build'
).persistentProperties.each {
props[it.name] = it.type.name
}
Or just pass the persistentProperties array itself through to the GSP, then extract .name and .type there.
You may also wish to consider using constrainedProperties instead of/in addition to the persistentProperties. The constrainedProperties map lists only those properties that are mentioned in the domain class constraints block, but the iterator over this map is guaranteed to return the properties in the order they are listed in the constraints. This is how the default scaffolding operates, as I'm not aware of any way to control the order of the persistentProperties array.

GORM mapping: make an index unique

I'm feeling a little slow today. I'm trying to do something that I think is very simple. I have a Domain class with a property called 'name'. I want 'name' to have an index, and I want the index to require that the 'name' is unique. I've set the unique constraint and tried creating an index. I can't make sense out of the Gorm docs as to how I add the unique attribute to the index. Here's some code:
class Project {
String name
static hasMany = [things:Things]
static mapping = {
name index:'name_idx'
}
static constraints = {
name(unique:true)
}
}
All is well with the above, except when do "show indexes from project" in mysql it shows my name key as not unique. I know the problem is that I am not specifying unique in the mapping, but quite frankly the docs for gorm are making my head hurt. I see all kinds of stuff about columns, but I can't find a single example anywhere on the web that shows what I want to do. I don't need complex mappings or compound keys, I just want to know the syntax to add the unique attribute to the mapping declaration above. Any advice welcome.
I also did a grails export-schema and see the following:
create index name_idx on project (name);
Nothing in that to indicate this index requires unique values
A related followup question would be once I succeed in making that index unique, what type of error should I expect when I go to save a Project instance and the name is not unique? Is there a specific exception thrown? I realize that even if I check that a given 'name' is unique there's still a possibility that by the time I save it there may be a row with that name.
I'm quite sure the syntax to do what I want is simple but I just can't find a simple example to educate myself with. I've been to this page but it doesn't explain HOW the uniqueness is enforced. I'd like to enforce it at the name index level.
The indexColumn allows additional options to be configured. This may be what you're looking for.
static mapping = {
name indexColumn:[name:'name_idx', unique:true]
}
Grails Documentation for indexColumn
If you put only the unique constraint the GORM send DDL to create an unique index on database.
static constraints = {
name nullable: false, unique: true
}

how to set Personalizable attribute to generic list in webpart?

I develop web part with custom editor part and faced with this question.
Is it possible in web part set Personalizable attribute to generic List?
For example I want something like this:
[WebBrowsable(false)]
[Personalizable(PersonalizationScope.Shared)]
public List<AnnouncementItem> Announcements
{
get { return _announcements; }
set { _announcements = value; }
}
Is it possible, and what kind of types at all can be used as "Personalizable"?
Thanks.
Solution:
I use a custom EditorPart to select multiple lists using AssetUrlSelector, but I need a way to personalize this collection for end user.List<of custom objects> doesn't work, but I found that List<string> (and only string) work perfectly. So, I get required lists in EditorPart and pass their to the web part using List<string>.
Try using a custom EditorPart to add/remove items from the collection. I've never built a web part that personalized a collection so I don't know if it works but I'd definitely try the collection with an EditorPart. If it doesn't work, serialize XML into a string property.
Your question does not seem to match your code. Your code shows a collection of custom objects. I doubt an end user will be able to set such a property. To have a property that points to a generic list, you would probably be better off defining the property as a string that contains the URL to a list.

db4o - unique constraints on a group of fields

I would like to have unique constraints operate on more than 1 field for several entities. How can I achieve this with db4o?
Thanks,
Walter
Currently db4o doesn't support the UniqueConstrain on multiple fields. You can set unique-constrains only field by field, but not combine them.
#Ladlestein Well the intention is good, but it doesn't work. db4o manageds objects by it referencial identity. When you apply the unique-constrain on the Foo.name, you ensure that the reference is unique. So no other object can have the same reference to a name object. But you're not interested that the reference is unique, but you want to have a unique content of the names.
Sounds like a composite key. Can you create a new class that contains the key-constituting fields, and use a member variable with that type in place of the key-constituting fields in your original class?
i.e. where you had
class Foo {
String given_name;
String family_name;
}
instead use
class Name {
String given_name;
String family_name;
}
class Foo {
Name name;
}
and make Foo.name the unique field?

Resources