Why some recently added fields are not initialized by constructor - grails

Groovy will all it's dynamic possibilities is still new to me and I'm kind of lost why below code does not work.
def luke = new FooPerson(firstName: "Luke", lastName: "Skywalker", initials: "LS", login: "luke", password: "luke" )
Above gives me proper values for firstName, lastName and initials and for login and password I get null.
If with above code I call
luke.setLogin("luke")
luke.setPassword("luke")
I will get proper value of all fields.
All five fields are declared in class
class Person {
static constraints = {
}
String firstName
String lastName
String initials
String login
String password
}
that my lovely FooPerson inherits from. My problematic fields were not initially in the Person class. I added them recently and obviously this causes groovy some stress.
Of course I can work around this, but I want to understand WHY it's working that weird way.

As noted by #dmahapatro upgrading to grails 2.2.4 solves the problem.
I've looked into release notes of Grails 2.2.4 and I don't see anything meaningful that could be connected to this, but it solves the problem.

Related

Read Strings from an Object

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.

Angular JS and Grails REST Service

I am creating a simple web app using groovy-grails and angular JS. I have 4 domain objects (Developer, Tester, Programmer) that all extend Person. In my bootstrap.groovy file, I have created new Developers, Testers, and Programmers, but when I run my app, it doesn't populate the table with whats in the Bootstrap.Groovy file. Whenever I take (extends Person) off of the class header, and add String firstName, then it finds the name of the Developer, Tester and Programmer. I also tried extending an abstract Person class (not a domain object), and that failed as well. See Below:
//domain object
class Person{
int id;
String firstName;
String lastName;
}
//domain object, non working copy
class Developer extends Person{
}
//domain object, working copy
class Developer{
int id;
String firstName;
String lastName;
}
//Boostrap.groovy
new Developer(id: 2, firstName: 'Foo', lastName: 'Ninja');
Thanks,
Butler_Alfred
Try removing the id from your domain classes. Grails adds this field for you implicitly.
Also, when you create a new Developer instance in Bootstrap.groovy, don't pass in your own id. One will be automatically set when the developer instance is persisted.
Developer developer = new Developer(firstName: 'Foo', lastName: 'Ninja')
assert developer.id == null // id is null before save
developer.save()
assert developer.id != null // id is assigned after save

Magical Record import with already existing data

I'm trying to use Magical Record to import data into my CoreData db.
I'm working on the entity Person at the moment.
A Person has firstName, lastName, personID attributes. (I know I don't need the idString, I'm not using it internally, it is used to talk back to the server).
Anyway, if I already have the person...
firstName - John
lastName - Smith
personID - 1
And I download the JSON...
[
{
firstName: John,
lastName: Doe,
id: 1
},
{
firstName: Michael,
lastName: Caine,
id: 2
},
{
firstName: Angelina,
lastName: Jolie,
id: 3
}
]
I'd want the import to add Michael and Angelina and to update John Smith to John Doe because it already exists with the same id vs personID.
I've set the mappedKeyName between id and personID.
Is it possible to do this? I've been reading this blog... http://www.cimgf.com/2012/05/29/importing-data-made-easy/ about automatic mapping of key names etc... and wondered if I could exploit this to do what I want?
I have read the part about relatedByAttribute from the blog but I'm not sure where I should be setting it and what to?
Should I set it on the entity Person? Or the attribute personID? And what should I set it to? "id"? Or something else?
I'm not sure if you're using the relatedByAttribute setting in the userInfo area of your Core Data model. You don't mention that in your issue here. I suggest you double check that. And to clarify, it's called relatedByAttribute because the string you put into the value section is the CoreData attribute which relates the entities, no the json (or other object) data. So, check those two things and if there still a problem, please open a ticket on github, preferably with a unit test that helps describe the problem.

Inheritance for domain class in Grails or a flag would do?

I am making a website where Doctors and Patient both can login.
class Doctors {
String firstName
String lastName
String email
String password
String hospitalName
String NPINumber
}
And patients
class Patients{
String firstName
String lastName
String email
String password
}
As it is evident that there are lot of overlapping fields which are only used for authetication/login purpose, I was wondering if inheritance is a good idea or should I just create a flag in a single class.
So two options are:
OPTION-1
class Users{
String firstName
String lastName
String email
String password
}
class Doctors extends Users {
String hospitalName
String NPINumber
}
class Patients extends Users{
}
OPTION-2
class Users{
String firstName
String lastName
String email
String password
boolean isDoctor
String NPINumber
String hospitalName
}
I am not sure which of these designs I should choose so that it is extendable in future!
Option 1 is more OO for sure. However, I would still make a little bit of a change in order to make the design even better. Instead of extending User, why not have a User property which contains some of the common attributes. Extending the User class could make your design more complex. Maybe this topic can help you.
Also, as a suggestion, don't use the classes' names in the plural form. Imagine it's an entity for itself and not a collection of entities. Clearly your class Doctor, for example, represents one doctor specifically. Not more than one. So you should use Doctor, Patient and User.
Hope it helps.

Grails select will not return correct data

This a continuation of this question.
I have an Address class which contains basic street address information. I also have a User class which has the attributes physicalAddress, mailingAddress, cargoDestinations, and cargoSources. The User class looks something like this:
class User {
String username
String password
String firstName
String lastName
String businessName
String phoneNumber
Address physicalAddress
Address mailingAddress
static hasMany = [accounts:Account, cargoSources:Address, cargoDestinations:Address, cargoes:Cargo, loadsLogged:Load, loadsDelivered:Load]
Set accounts, cargoSources, cargoDestinations, cargoes
static mappedBy = [loadsLogged:"loggedBy", loadsDelivered:"deliveredBy"]
//some other stuff after this
And the Address class looks something like this:
class Address {
static belongsTo = [user:User]
String streetAddress
String city
String state
String zip
BigDecimal taxRate
//some other stuff after this
I followed the tutorial here for the most part. In step 5 my template looks like this:
<g:select
from="${account.user.cargoDestinations}"
name="cargoDestinations" value="">
</g:select>
The problem is that instead of returning only cargoDestinations, the template returns ALL addresses associated with that user. If I change from="${account.user.cargoDestinations}" to from="${account.user.physicalAddress}" or from="${account.user.mailingAddress}" I get the expected result, so I know my problem has something to do with how the cargoDestinations variable is mapped. How can I go about fixing this without changing my class files too much?
The way you have your addresses mapped, they all link back to the user on the user_id column. You'll need to add some fields to Address to distinguish how they're related to User, similar to how you've mapped Loads. For example:
class Address {
static belongsTo = [cargoSourceFor: User, cargoDestinationFor: User]
...
}
class User {
...
static hasMany = [cargoSources:Address, cargoDestinations:Address]
static mappedBy = [cargoSources: "cargoSourceFor", cargoDestinations: "cargoDestinationFor"]
...
}
If you're familiar with SQL, doing a grails schema-export and looking at target/ddl.sql can be helpful when setting up mappings.
I ended up adding several boolean fields to my address class, which made the design simpler and much easier to work with. This way I only need one class instead of several nearly identical classes. The boolean fields in the Address class now indicate if an address is a physical address, mailing address, cargo source, etc., or all of the above. As #ataylor pointed out, this system makes it so an address object can only be associated with one user from my User class, but it does not seem like that will ever be an issue. The worst case is that a multiple users would have the same address in real life, and my program would require the creation of a separate address object for each of those users, even though the addresses in question would be identical.

Resources