Domain object string field auto trimming - grails

After update from Grails 2.2.3 to Grails 2.3.5 (groovy 2.0.8->2.1.9) I found strange behavior
Domain object:
class Element {
String name
String title
static constraints = {
title nullable: true
}
}
During creation String field trims automatically and empty string replaced by null
def e = new Element(name:'', title:' sgg gg ')
assert e.name==null
assert e.title=='sgg gg'
I can't find this super feature in changelog of Grails & groovy. How I can disable it?

From: http://grails.1312388.n4.nabble.com/Grails-2-3-Data-Binding-String-Trimming-And-Null-Conversions-td4645255.html
The default behavior in Grails 2.3 is to trim strings during data binding. In addition to that, another default behavior is to convert empty strings (strings with nothing in them, not even spaces) to null during data binding. Those 2 things happen in that order so if you bind a String with nothing in it but spaces, the default behavior is to bind null because the String will be trimmed and then since it is empty it will be converted to null. This is a sensible default. There are separate config properties for disabling either of those behaviors.
// grails-app/conf/Config.groovy
grails.databinding.convertEmptyStringsToNull=false
grails.databinding.trimStrings=false
I believe it's mentioned here in the documentation

Related

Trim domain field by default

What is the best way to trim field value in domain?
My suggestion is to use beforeSave(), but would work something like this?
class Book {
String name = name?.trim()
}
You have a couple options depending on what behavior you want.
A custom setter, which will trim the value every time you set it
class Book {
String name
void setName(String name) {
this.name = name?.trim()
}
}
A custom getter, which will give you a trimmed value but not store it in the database
class Book {
String name
String getName() {
this.#name?.trim()
}
}
A hibernate event, like beforeSave() as you mentioned, which will only trim it before the object is persisted.
Well, you can enable automatic trimming of string in Grails (version 2.3+) by setting below property in Config.groovy file:
grails.databinding.trimStrings = true
This will automatic trim the string before save or update.
I have have noticed that Grails automatically does a .trim() on fields before persisting them. For example:
null
""
" "
All gets stored as null in Grails 2.3.7 for a nullable string. In addition:
" foobar "
gets stored as "foobar"
These results are using the default h2 database. So you might let Grails do the heavy lifting in this case.
Here is my hack for quickly trimming all fields in a domain object. I often receive JSON data that is not formatted in a way that would allow me to use data-binding techniques. This method can be called after updating or assigning all values in the domain instance.
class Book {
def trimFields() {
this.properties = this.properties
}
}
Requires this configuration which is set by default in Grails
grails.databinding.trimStrings = true
I know this is overkill but it's quick and easy to add to a domain class.

constraints in grails

Hi I am having some trouble getting my constraints to work in my grails project. I am trying to just make sure that the field for Site_ID is not left blank but it still accepts an blank input. Also I am trying to set the order in which the fields appear but even that is not reflecting on the page when I try it out. Here is the code:
package translation
class J2_Translations {
String Site_ID
String I18NKey
static constraints = {
Site_ID(blank:false)
I18NKey()
}
}
and here is my code for the controller, I am not doing anything special I just want the constraints to work
package translation
class J2_TranslationsController {
def scaffold = J2_Translations
}
thanks,
Ameya
Grails is a convention-over-configuration framework. Make sure you follow the standard Java naming conventions. Properties should be named with camel-case identifiers with the leading character in lowercase. For example:
String siteId
String i18nKey

How to set default value of TextBox empty string instead of null

I may be out of date, but one principle I adhere to is avoid nulls as much as possible.
However what I have found is that for a strongly typed view in which the user inputs the properties of an object I want to save, if some fields are not entered they are assigned as null.
Then when you try to save the changes, the validation fails.
So rather than set each property to an empty string, how can I automatically set each TextBox on a form to default to an empty string rather than a null?
You could put the following attribute on your string-properties in your model:
[DisplayFormat(ConvertEmptyStringToNull=false)]
So whenever someone posts a form with empty text-fields, these will be an empty string instead of null...
To be honest, I'd say your coding methodology is out of date and flawed. You should handle all possibilities, it's not hard. That's exactly what string.IsNullOrEmpty(value); is for.
I'm guessing your validation logic is something like:
if (value == string.Empty) { isValid = false; }
So it doesn't handle the null values. You should replace that check so it also checks for nulls.
string value1 = null;
string value2 = string.Empty;
string.IsNullOrEmpty(value1); // true
string.IsNullOrEmpty(value2); // true
An alternative solution to using attributes on each model property, as described in the accepted answer, is using a custom model binder, see string.empty converted to null when passing JSON object to MVC Controller
I ran across this problem when dealing with an old service that requires empty strings. I created an extension method:
public static string GetValueOrDefault(this string str)
{
return str ?? String.Empty;
}
So you can use this when you want to make sure any strings that are null become empty
yourString1.GetValueOrDefault();
yourString2.GetValueOrDefault();

How to get model binder to leave null strings as null?

My Sql Server database has some nullable nvarchar fields, and no nvarchar fields containing empty strings. I want to keep it this way, but the default MVC model binder seems to turn null strings into empty strings.
When a controller retrieves a null nvarchar database field, the null field turns into null string inside the controller, and from there the view renders them, say as blank text boxes. When the page is posted, the default model binder uses these blank text boxes to update the model, and the formerly null strings are changed to empty strings. When the data is updated back to the database, nulls are overwritten with empty strings.
What is the easiest way to get model binding to leave these nulls unchanged?
I know you are probably looking for something more sophisticated, but the default behavior of the ModelBinder is to convert empty form field values into the default value for the datatype of your model object property. String properties become empty, int properties become 0, etc.
You can obviously create a validation scheme that will check for string.empty and convert to null prior to updating the DB. For int form fields you will need to check for 0, and then convert to null.
Here's a hack I used a few months ago before I found the eden of stackoverflow. :) It's a pain, and doesn't scale well, but it works:
Basically, you override the binding inside of a partial linq object. If there's a value you know should always be null (but never legitimately empty) you can do the following. I used this for a string-based user id (SID).
partial void OnSubProcess_Owner_UserChanged()
{
if (string.IsNullOrEmpty(this.SubProcess_Owner_User))
this._SubProcess_Owner_User = null;
}
James
The right answer might be to override the default Model binder to add this functionality yourself.
Maybe you could have a NullValueAttribute that you could apply to string properties to identify the null value. Then make empty string a null value.
I am experiencing the same problem at the moment and will probably resort to this
I'm posting this answer to follow through on this question. After working with it for a while I came to see this problem as part of the general concern of model integrity. For a while I had implemented a solution inside my update stored procedures to catch empty strings and turn them to nulls, along the lines of mikerennick's answer above. Later I wanted also to make sure fields were trimmed and I happened to move the application to NHibernate (and most of the stored procedures went away). In the end I embedded some POCO logic to trim and check for empty strings (from whatever source) in the setters as so:
public MyClass {
private string _name;
public string Name {
get { return _name; }
set { _name = value.TrimToNullIfEmpty(); }
}
}
public static class StringExtensions {
public static string TrimToNullIfEmpty(this string s) {
string temp = (s ?? "").Trim();
return temp.Length == 0 ? null : temp;
}
}

How can fields in Grails represented by a combobox be made optional?

I'm doing my first experiments with Grails and am looking for a way to have fields represented by a combobox (such as one-to-one domain associations and numbers with a narrow range constraint) to be optional, i.e. there should be an empty entry in the combobox.
How can this be achieved? I've tried both adding a nullable:true constraint and listing the fields in the optionals static property, but neither produces the desired result.
These are my domain classes:
class Customer {
String name
}
class Book {
static optionals = ['year','loanedTo','loanedSince']
static constraints = {
title(blank:false)
author(blank:false)
year(range:1900..new Date().getAt(Calendar.YEAR), nullable:true)
loanedTo(nullable:true)
loanedSince(min:new Date())
}
String title;
String author;
Integer year;
Customer loanedTo;
Date loanedSince;
}
I've found that the nullable:true constraint actually does have the desired effect - however, it does not take effect immediately; you have to restart Grails to see it.
If you've generated your scaffolding code, you'll also have to regenerate it so that the option is present.
I don't think optionals is still supported: http://jira.codehaus.org/browse/GRAILS-472
The tag also has an attribute for a default, "not selected" value: noSelection. You can use it like this to have the drop-down default to "---" instead of your regular values:
noSelection="${['':'---']}"
In the controller, the default value shows up as an empty string, as specified in the first part of the value.

Resources