Grails newbie - Scaffold question - Replace unique id with readable value(s)? - grails

I'm creating a web application with grails, and I'm working on the CRUD prototype using Scaffold. Out of the box, the scaffold will use the unique id (which makes sense) for foreign key values, and I'm wondering if I can easily replace the unique id with a readable value (such as a combination of two values from said table).
For example:
I have Location and RoomNumber domains that represent a Hotel location and room number. Each number therefore "belongs-to" a location. When I go to create a room, I have a drop-down auto-generated that allows me to pick from existing locations. These are unintuitive values though... such as "project.Location : 1"
I'd like to replace this "project.Location : 1" with the name, city, and state column values that correspond to id 1. Is this an easy thing to modify? I'd think there's some simple mapping that needs to be done...
Thanks in advance!

Turns out the solution is really simple... just need to implement the toString method in the corresponding Domain class. Received this answer from the Grails mailing list.

Related

Best Practice: Managing string list with entity framework and migration

I've been searching for the best practice for managing/storing a list of strings in the database optional with entity framework, but migration should be supported.
E.g.
I have a list of city-names which I like to store in a new table. This table contains all available citys in my project.
I've a property City in a Address class, which address one of the citys in my City-Table.
1. Is it better to set a reference to the entry in the City-Table or apply and store the value in the Address - Table ?
2. What's the best practice for creating the City-Table? Generating a class City in my Model seems to be a little bit too much overhead, but where can I manage/create it if I like to reference the entries in the Address?
It all comes down to what your application will be able to do. If you are planning to do some operations with cities, it would be wise to have them as separeted entities. Otherwise, you would have to query the Address table, and group the cities (which will offer some troubles, like people entering "Moron" and "MorĂ³n" as cities, for example).

Identifying and relating cities from different sources

I have different providers which passes me an excel with different cities, in each city they use some special code for their operations and more data useful to my business.
The problem is that I have a mess with all these cities:
I have my own cities in my database, around 9000 records.
Provider A gives me his excel or webservice to get around 6000.
Provider B gives me another 5000.
Provider C ... etc
Some of the cities given by my providers are already in my database and I only have to update the required data I need.
Otherwise, I have to insert that new city in my database.
And this, each time a provider gives me an update of these cities.
Well, the main problem is that I call a city differently from them, and they differently from each other... how to know if I already have that city or I have to create a new one since we use different names?
The way I see it, I only can achieve it manually. Comparing their cities with mines.
Of course, it's too much work so I made my own script, and implementing the levehnstein function for the database, I can automatically see the more coincident ones and select them by a click. The script does the rest (updates their special operation code for that city into my corresponding city stored in my database).
Even with it, I still feel like I'm missing something. If there was an unicode for those cities this would be much easier and automatic, but I don't have any code which identifies these cities more than my table identifier. Same for my providers, despite some of the use to provide me the postal code among the cities their provide, but not all.
Is there any better solution than mine for this? Any universal code that you usually use or any other aproatch?
Edit:
Well, each city belongs to a country. Of course, I'm considering that.
In my city table I have an Id for each destination, and then a column for the operation code of each provider (I know, this could be better represented with a relationship more), plus country code, zip, url for seo...
Respecting the solution mentioned by MagnusL, creating a Synonyms table, why would I need to store the synonyms? Regarding the script you mentioned with levehnstein and human interaction, that's exactly what I'm currently doing:
With each record provided by a provider and my destinations table. Given a provider city record, I'm showing the more coincident ones from my table.
But before this, I automatically link all those which are coincident in zip code and country.
It's a lot of work for updating my providers special operation code for each city. I am just curious about how people deal with this problem, I'm sure a lot of developers have to face this at some point.
If it is important that the cities are correctly matched, I would guess you must have some manual steps in your process. If you include names of smaller towns you will some day encounter that the same name could actually be two different places in two different countries. (Try Munich on Google Maps and you get one in Germany and one in North Dakota.)
A somewhat complicated, but I guess future proof, workflow is to use id numbers in place of city names in your main data table. Then set up a locations table with those id numbers as primary keys and your preferred name of the city followed by as many meta data columns as required for country code, zip code, WGS84 coordinates, continent name, whatever. Add another table for city name synonyms, with just id numbers and names (without UNIQUE constraint on the id column).
Let your import script try to match the city with help from as many meta data as possible (probably different meta data from different providers), together with the Levehnstein algorithm you mentioned, and let it be clever enough to ask for human interaction in those cases where no one or more than one city are matched. It can of course show you the closest possible guesses, so you can pick the right one and have it stored in the synonym table.
(Yes, it is a lot of coding to get there. If you find it worth it or not depends on how often you do these updates.)
Tip: Wikipedia has articles with different names on cities, i.e. https://en.wikipedia.org/wiki/List_of_names_of_European_cities_in_different_languages
What if you used an extra table for name translation?
IE, the table would have 2 columns: column A the name you use, column B, the name a provider uses. You might need to do adapt this table manually, to look like:
Bruxelles:Brussels
Bruxelles:Brussel
Bruxelles:Bruxelles
While importing, for the name of the city you would then use
select A where B = Brussels
In your agglomerated database, names would then be consistent.

Grails how to set _idx field when INSERTing data from outside of the Grails application?

I have a scaffolded Grails application with two domains, Person and Course. Person belongs to Course, and Course hasMany Persons. I have modified show.gsp for Course to list all of the Persons associated with the selected Course.
To achieve this, Course.groovy contains the following line:
List persons = new ArrayList()
And, as a result, the "person" database table contains a persons_idx field. I frequently will be adding new data to the "person" table outside of my Grails application, from an external website.
When INSERTing new data, how to I figure out what to set persons_idx as?
I had originally used a SortedSet instead of an ArrayList for persons, since I care about sorting. But since I am sorting on Person.lastName, and there will always be multiple people with the same last name, then the list will exclude those persons who have the same last names as others. I wish there was another way...
Thanks.
Having two applications manipulate the same Database is a thing to avoid, when possible. Can your 2nd application instead call an action on the controlling app to add a Person to the Course with parameters passed to specify each? That way, only one app is writing to the DB, reducing caching, index, and sequence headaches.
You also state that Person belongsTo Course... so you create a new Person for "Bob Jenkins" for each course that he's in? This seems excessive. You should probably look into a ManyToMany for this.
Without moving to a service, unfortunately, you'd want to change the indices on some if not many of the rows for the children of the Course you're trying to add a Person to, as that index is the sorted index for all the Persons in the Course.
I would suggest going back to a "Set", and do your sorting in the app. Your other question about sorting already told you not to override compareTo to just check the last name. If I were you, I'd forget about overriding compareTo at all (except to check IDs, if you want), and just use the sort() method, passing in a closure that correctly sorts the objects.

Custom fields in Rails that act as a template for future entries

I'm looking for some feedback on my current plan of implementing custom fields in rails. I'm new to rails and app development in general and would appreciate any comments from more experienced individuals.
Background
The app: Keep track of food and beverage tastings.
What I'm trying to model:
User creates a new sample type.
They call it: "Wine"
They decide for their company, they'd like to keep track of the following attributes: Origin, Grape Type, Company, Elevation,Temperature Kept, and more.
The only assumptions about a sample type that my database has made is that it has a Name. (eg. coffee, wine, etc.) the rest are all custom fields specified by the user.
Now that a sample type has been created.
The user begins to create samples of sample type wine.
They choose create sample, choose of type Wine.
The fields they must fill in are the ones they specified earlier.
In Origin they put: France, in Grape type: they put chardonnay, etc..
--
My plan of approach is as follows:
When a user creates the sample type, store the custom fields as an array or in some string format and keep it under a column called data.
SampleType
name
wine
data
[origin, grape_type, company, ...]
When a user wants to create a sample of type Wine:
I look up the sample type wine, for each key in the data column, it creates form fields.
When the user submits the data, I create a hash of all the custom fields names and their corresponding data. I serialize it and store it in a hash in a data column like such:
Sample
type
wine
data
{ origin: "France", grape_type: "Pinot Grigio, ... }
My plan at the moment is to use PostgreSQL's hstore to implement the hashing in the data column.
My questions are:
Is this a valid solution for what I'm trying to do?
Will I run into trouble when users change what custom fields they want?
Any other concerns I should take into account?
Is mongodb and other such db's a better choice for this type of model?
I've been using the following links as a reference:
http://schneems.com/post/19298469372/you-got-nosql-in-my-postgres-using-hstore-in-rails
http://blog.artlogic.com/2012/09/13/custom-fields-in-rails/
As well as many other stack overflow posts, however none seem to be using it in the way I mention above.
Any comments are appreciated.
jtgi, having done something like this more times than I want to remember, my first response was, "run away!" In my experience, the whole user-defined field thing is an ugly, hacky, nightmare. Soon, someone will ask, "can I search on grape?" or "I want to be able to input multiple values for grape." And on and on, and you will hate yourself for ever stepping down this path. :-)
That said, I think your approach is pretty decent. To answer your questions directly:
Yes, this is a valid approach.
Yes, you will run into trouble when users change the custom fields they want. (see above)
See some notes below.
Might be. I went there even before I read your 4th question. With your field => value hash, you're kind of implementing a noSQL solution anyhow, but it'll be non-trivial to implement lookups, searches, etc.
Some thoughts:
I think I would marshal the data into a db column, rather than using a db function. That way, it's pure Ruby and not dependent on the db type. See http://www.ruby-doc.org/core-1.9.3/Marshal.html. I'm doing this to cache some data in an app right now, and it's pretty slick. You may need to marshal(l) the data anyhow, if you want to wind up storing Ruby objects more complex than strings.
You'll probably get there soon anyhow, so I would plan on storing some "metadata" about the attributes while you're at it. E.g., "grape" is a String, max length 20, "rating" is an integer between 0 and 100. That way you can make your form a little prettier and do some rudimentary validation.
When you come to hate this feature, you can remember me. :-)

Id (autoincrementing integer) vs string employee ID as primary key - rails application

I'm writing my first rails app & want to get into some good habits from the start. The table in question is to be to hold employee data, one of the fields being the manager's ID. To reflect the hierarchical structure, I'm thinking of using acts_as_tree, so the parent_id would be the manager's id field (right?). If we are to use (import) data from our existing HR application - PeopleSoft - the employee ID is a string. Employee ID seems to make the most sense as a PK (coming from the PeopleSoft developer perspective, I realize I may be biased and/or not seeing all of the possibilities -- I welcome suggestions on this as well)
I know that one of the philosophies behind rails is "convention over configuration", so I'd like to use the defaults - the PK being the autoincrementing integer. Would it make sense in this case to create a "lookup table" or something in order to maintain the use/association of the ID coming from PS? There will be reports/exports going back into the PS world....
Thanks
You're correct in that the convention in Rails is to use the default auto-incrementing id. If you have a one-to-one relationship between people and employee IDs, then employee ID should just be a field (column) on your person model. Make it a key (but not a primary key) if you're going to be doing a lot of lookups using it.

Resources