Problem with GRAILS select - trying to insert a number for a field that appears as text in dropdown list - grails

Here is the domain class I have defined:
package mypackage
public enum UFModeType {
I(0),
O(1),
R(3)
Integer mode
public UserFileModeType(Integer mode) {
this.mode = mode;
}
static list() {
[I, O, R]
}
}
This is a property of another domain Parent where it is as follows:
package mypackage
class Parent {
String name
... ... ...
UFModeType uFMode
static mapping = {
table 'parent_table_with_ufMode_col_as_number'
version false
tablePerHierarchy false
id generator:'sequence', params:[sequence:'myseq']
columns {
id column:'parentid'
uFMode column: 'UFMODE'
}
}
static constraints = {
userFileMode(nullable: true)
}
}
The gsp call for this looks like this:
g:select name="uFMode" from="${mypackage.UFModeType?.list()}" value="${parentInstance?.uFMode?.name()}" /
I have tried a lot of variants of the above in the gsp call but I am getting error that the db insert fails saying the entry of ufmode is invalid number, thus this is not being passed as a number. I printed the params in the controllers save and it shows this:
Params in save=[uFMode:I ...
I am sure I may be missing some minor thing in syntax, but I have tried a lot of things without much success, so any inputs will be greatly appreciated.
Thanks!

Try changing
value="${parentInstance?.uFMode?.name()}
to
value="${parentInstance?.uFMode?.mode()}
From the definition of UFModeType you give you do not have a name attribute.

Related

SYMFONY FORM ChoiceType, multiple=>true. How to by pass the need to implement Data Transformers

In a SYMFONY FORM (ORM is not use (PDO is used for DB query instead)).
I have a class MyEntityType in which the buildForm function has:
$builder->add('my_attribute',ChoiceType::class,array(
'choices'=>$listForMyAttribute,
'multiple'=>'true',
'attr'=>array('data-native-menu'=>'false'),
'label'=>'Multiple Select on my attribute'
));
My attribute is an array of an entity named MyEntity which has:
/**
* #Assert\NotBlank()
*/
private $myAttribute;
With a getter and a setter for that variable $myAttribute.
When I submit the form in the Controller, it doesn't pass the validation check and logs this error:
Unable to reverse value for property path "myAttribute" : Could not find all matching choices for the given values.
When I start to look for solution around this error message, it leads to something named "How to Use Data Transformers" in SYMFONY Cookbook; And it seems a solution would involve to create new Class and write a lot of code for something that one should be able to by-pass in a much straight forward way.
Does anyone have an idea?
My problem was that my array $listForMyAttribute was defined in the buildForm() function and its definition was relying on some conditional.
The conditional to make the array were met when this one was displayed for the first time.
After pushing the submit button, the buildForm was regenerated in the Controller, this second time, the condition were not met to make the array $listForMyAttribute as it was on the first display. Hence the program was throwing a "contraint not met error" because the value submited for that field could not be find.
Today I face exactly the same problem. Solution is simple as 1-2-3.
1) Create utility dummy class DoNotTransformChoices
<?php
namespace AppBundle\DataTransformer;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
class DoNotTransformChoices implements ChoiceListInterface
{
public function getChoices() { return []; }
public function getValues() { return []; }
public function getPreferredViews() { return []; }
public function getRemainingViews() { return []; }
public function getChoicesForValues(array $values) { return $values; }
public function getValuesForChoices(array $choices) { return $choices; }
public function getIndicesForChoices(array $choices) { return $choices; }
public function getIndicesForValues(array $values) { return $values; }
}
2) Add to your field the following additional option:
...
'choice_list' => new DoNotTransformChoices,
...
3) Congratulations!

Grails data binding field exclusion

I am using Grails 2.5 and use Grails databinding in request methods.
For a basic example of the situation consider the following:
Domain class
class Product {
String field1
String privateField
}
Controller
class ProductController {
def update(Product productInstance) {
productInstance.save()
}
}
If I pass an existing Product to the controller like
{"id":3, "privateField":"newValue","field1":"whatever"}
the old value of privateField is overwritten. I want to enforce, that privateField is never bound from a request and avoid checking if the field is dirty.
Is there a mechanism in Grails to achieve this?
If I have to do the dirty check, how can I discard the new value and use the old one?
Pretty sure there's a "bindable" constraint.
http://grails.github.io/grails-doc/2.5.x/ref/Constraints/bindable.html
class Product {
String field1
String privateField
static constraints = {
privateField bindable: false
}
}
Should keep that field from binding automatically.
You can enforce which values are bound, but you'll need to change your method signature to get more control of the data binding process.
class ProductController {
def update() {
def productInstance = Product.get(params.id)
bindData(productInstance, params, [exclude: ['privateField']]
productInstance.save()
}
}

propertyMissing doesn't work in Criteria?

So I've got a couple of classes with the following relationship:
class Foo {
Bar bar
/* ... other fields ... */
}
class Bar {
String name
}
In class Foo I've got a couple of named queries:
static namedQueries = {
userFoos { user ->
/* ... get Foos for this user ... */
}
limitFoos { colname, dir ->
order(colname, dir)
}
...which I can then chain together in a controller:
def foos = Foo.userFoos(currentUser).limit(colname, dir)
Pretty straightforward so far. The problem is when I try to sort on bar; I get the error:
could not resolve property: bar.name of: package.Foo.
Now, I also got this error when the queries were Criteria that were declared in the controller. So, I went and wrote a propertyMissing handler for Foo:
def propertyMissing(String name) {
if (name.contains(".")) {
def (String propertyname, String subproperty) = name.tokenize(".")
if (this.hasProperty(propertyname) && this."$propertyname".hasProperty(subproperty)) {
return this."$propertyname"."$subproperty"
}
}
}
I don't know if this is really the best way to do it, but it did work! However, now that I've moved the query into the class as a named query, propertyMissing doesn't appear to work anymore! Is this use not supported, or am I just missing something here?
EDIT
So I tried moving the Criteria back into the controller and sure enough, the sub-property sort did not work there either! So I guess Criteria just don't support propertyMissing at all :/
To answer dmahapatro's question, I am using jQuery DataTables to present the information. Clicking on a column header does an AJAX call to a controller action with parameters to indicate which column to sort on and in which direction. Once I determine the column name, I call the named queries like so:
def foosFilteredLimited = params.sSearch ?
Foo.userFoos(currentUser).filterFoos(params.sSearch).limitFoos(offset, max, colName, sortDir).list()
: Foo.userFoos(currentUser).limitFoos(offset, max, colName, sortDir).list()
(filterFoos takes a search string and narrows the results of userFoos.)
Try modifying limitFoos namedQuery as below and it should work. There is a caveat to it though. We cannot use bar.baz.name if required. ;)
limitFoos { column, ord ->
def colStrs = column.tokenize(/./).toList()
if( colStrs?.size() > 1 ) {
"${colStrs[0]}" {
order( "${colStrs[1]}", ord )
}
} else {
order(column, ord)
}
}

Id is set to NULL when trying to save DomainObject in Grails

I have two domain object with the same structure as the class Foo below
class Foo {
static mapping = {
id column: "old_id_column"
prop1 column: "old_prop_1"
... some more properties ...
}
}
class Bar {
... looks the same as Foo ...
}
and in the controllers of the classes I try to accomplish the same thing, creating a new object and saving it to the DB.
When I do this
class FooController {
def methodName() {
final Foo foo = new Foo()
foo.prop1 = "val1"
foo.prop2 = val2
etc.
foo.save(flush: true)
}
}
Everything works but when I try to do the same in the BarController i get the following exception
Cannot insert the value NULL into column 'old_id_column', table 'System.db.Bar'; column does not allow nulls.
I'm trying to model a legacy database so obviously I'm missing something in the configuration of the underlying DB but I can't find anything. Any ideas about things that could raise this exception?
You need to specify a generator
i.e.
id generator:'assigned', column: 'old_id_column', type: 'string'
See the documentation # http://grails.org/doc/latest/ref/Database%20Mapping/id.html

Grails - check if item has parent

I'm new to Grails, Groovy and GSP.
I have a domain class "ProductCategory".
class ProductCategory {
static constraints = {
}
static mapping = {
table 'product_category';
version false;
cache usage: 'read-only';
columns {
parent column: 'parentid';
procedure column: 'procid';
}
}
static hasMany = [children:ProductCategory];
ProductProcedure procedure;
Integer lineorder;
String name;
ProductCategory parent;
String templatelink;
char offline;
String toString() {
return id + " (" + name + ")";
}
}
Each category CAN have a parent. I am using an existing database, and the table has a column 'parentid' to do that. When a category has no parent (root level), its parentid is 0.
I have a GSP trying to show data about the parent if any.
<g:if test="${category.parent}">
hello
</g:if>
I was under the impression that this would test for existence.
It works fine if the category DOES have a parent, but as soon as parentid=0, it blows up.
No row with the given identifier exists: [ProductCategory#0]
I tried to check for ==0, but it didn't work, I assume because 'parent' is supposed to be an object.
So how can I make it so that it assumes that parentid=0 is the same as parent=null, or NO parent?
Thanks
I think I may have found the answer:
parent column: 'parentid', ignoreNotFound: true;
ignoreNotFound is nowhere on the documentation, but it seems to work!
parentid should not be equal to 0. It should be null.
What I don't understand in your question, is how can you have parentid == 0 ?
You don't need to handle the parentid manually. As soon as you define a domain class like this:
Class Foo {
Bar bar
}
Gorm/Grails will automatically create a foreign key column for you. And if you define the property nullable:
Class Foo {
Bar bar
static constraints = {
bar(nullable:true)
}
}
...you can just set it to null and test for null:
def f = new Foo(bar:null)
if (f.bar == null) { ... }

Resources