Grails
  1. Grails
  2. GRAILS-8251

GORM dynamic get(id) method should support properties with unique = true

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 1.3.7
    • Fix Version/s: None
    • Component/s: Persistence
    • Labels:

      Description

      Most scaffolds and best practices use the convention <Domain Class>.get(id) method. This works for the GORM dynamic id, but when users want to use unique properties they are forced to create a new get method, then override all scaffolding to use this new method. It would be a great improvement to add logic that will attempt the original method, then attempt to get the instance via any unique properties found.

        Activity

        Hide
        Brad Lee added a comment -

        Here is an example:

        Consider this domain class:

        class Person {
          String name
          static constraints = {
            name(nullable:false, blank:false, unique: true)
          }
        }
        

        The get method should use this logic (not the grooviest, but you get the idea):

        get { id ->
          if( id instanceof Number ){
            return Person.findById(id.longValue())
          }else if( id instanceof String ){
            def person = Person.findByName(id)
            if( exchange == null ){
              // Attempt string coersion to number and retrieve above...
            }
            return person;
          }
          return null
        }
        
        Show
        Brad Lee added a comment - Here is an example: Consider this domain class: class Person { String name static constraints = { name(nullable: false , blank: false , unique: true ) } } The get method should use this logic (not the grooviest, but you get the idea): get { id -> if ( id instanceof Number ){ return Person.findById(id.longValue()) } else if ( id instanceof String ){ def person = Person.findByName(id) if ( exchange == null ){ // Attempt string coersion to number and retrieve above... } return person; } return null }
        Hide
        Jeff Scott Brown added a comment -

        I don't think this is a great idea.

        It looks like you have scenarios where you may be passing properties like "name" around when maybe you should be passing the primary key around (like the scaffolding does). If you can provide a simple app that demonstrates what you are trying to do, there is almost certainly a better (more simple) solution than changing the behavior of the .get() method.

        I suggest taking the question to the user mailing list and providing some more details.

        Show
        Jeff Scott Brown added a comment - I don't think this is a great idea. It looks like you have scenarios where you may be passing properties like "name" around when maybe you should be passing the primary key around (like the scaffolding does). If you can provide a simple app that demonstrates what you are trying to do, there is almost certainly a better (more simple) solution than changing the behavior of the .get() method. I suggest taking the question to the user mailing list and providing some more details.
        Hide
        Brad Lee added a comment -

        Bottom line is that REST URLs should generally not contain the immutable primary key if you have something more human readable and also unique, like user id. For example, if you have a person with unique identifier (name, userid, etc) 'bob' and his immutable primary key '1' (id in grails), then this URL:

        http://<host>/app/persons/bob

        is far preferable to this one:

        http://<host>/app/persons/1

        We know that name, userid, etc is a primary key since the GORM object defined it as such in the constraints.

        What's really interesting is that it would not be hard to retain the original functionality here - so you are merely adding to the capabilities of GORM's get method, making your user base happier - and also being far groovier in nature.

        Show
        Brad Lee added a comment - Bottom line is that REST URLs should generally not contain the immutable primary key if you have something more human readable and also unique, like user id. For example, if you have a person with unique identifier (name, userid, etc) 'bob' and his immutable primary key '1' (id in grails), then this URL: http://<host>/app/persons/bob is far preferable to this one: http://<host>/app/persons/1 We know that name, userid, etc is a primary key since the GORM object defined it as such in the constraints. What's really interesting is that it would not be hard to retain the original functionality here - so you are merely adding to the capabilities of GORM's get method, making your user base happier - and also being far groovier in nature.
        Hide
        Jeff Scott Brown added a comment -

        Brad,

        You mentioned "We know that name, userid, etc is a primary key since the GORM object defined it as such in the constraints.". In the example you provided in the original description the "name" attribute is marked as unique but that does not make it a primary key. You could have any number of properties constrained to be unique within a domain class. That doesn't make any of them a primary key.

        Depending on some details in your app this may or may not be the best thing but one thing you could do is something like this:

        grails-app/domain/Person.groovy
        class Person {
        
            String login
            String firstName
            String lastName
        
            static mapping = {
                id name: 'login', type: 'string', generator: 'assigned'
            }
        }
        

        If you did that, now you can pass the login as an argument to the get() method.

        new Person(login: 'grocher', firstName: 'Graeme', lastName: 'Rocher').save()
        new Person(login: 'jbrown', firstName: 'Jeff', lastName: 'Brown').save()
        new Person(login: 'bbeckwith', firstName: 'Burt', lastName: 'Beckwith').save()
        
        
        p = Person.get('bbeckwith')
        assert 'Burt' == p.firstName
        

        Does that help?

        Show
        Jeff Scott Brown added a comment - Brad, You mentioned "We know that name, userid, etc is a primary key since the GORM object defined it as such in the constraints.". In the example you provided in the original description the "name" attribute is marked as unique but that does not make it a primary key. You could have any number of properties constrained to be unique within a domain class. That doesn't make any of them a primary key. Depending on some details in your app this may or may not be the best thing but one thing you could do is something like this: grails-app/domain/Person.groovy class Person { String login String firstName String lastName static mapping = { id name: 'login', type: 'string', generator: 'assigned' } } If you did that, now you can pass the login as an argument to the get() method. new Person(login: 'grocher', firstName: 'Graeme', lastName: 'Rocher').save() new Person(login: 'jbrown', firstName: 'Jeff', lastName: 'Brown').save() new Person(login: 'bbeckwith', firstName: 'Burt', lastName: 'Beckwith').save() p = Person.get('bbeckwith') assert 'Burt' == p.firstName Does that help?

          People

          • Assignee:
            Jeff Scott Brown
            Reporter:
            Brad Lee
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development