Доменный объект, ссылающийся на справочную таблицу в Grails GORM - PullRequest
2 голосов
/ 24 октября 2010

У меня есть объект домена с именем User:

class User{
  String username;
  String firstName;
  String lastName;
  Zipcode zip;
}

У меня также есть объект Zip Code:

class Zipcode {
  String zip;
  String city;
  String state;
  Float lat;
  Float long;
}

Таблица почтовых индексов никогда не должна изменяться, так как она содержит статические справочные данные, предварительно заполненные

Пользователь принадлежит одному почтовому индексу. Пользователь вводит почтовый индекс как часть создания пользователя.

Как мне моделировать отношения объектов домена? Я хотел бы убедиться, что GORM не пытается обновить почтовые индексы. Я хотел бы убедиться, что пользователь вводит только действительные номера почтового индекса. (Которые находятся в таблице почтовых индексов) Как мне настроить ограничения для объекта User? В контроллере я делаю следующее:

def userInstance = new User(params) // where params are form values

Как установить правильный почтовый индекс на объекте?

Ответы [ 3 ]

4 голосов
/ 25 октября 2010

Вы бы не позволили бы GORM управлять свойством zip (и запретить GORM делать это на втором этапе).

Это то, что подход mfloryan тоже говорит; однако, его подход не разделяет интересы, а правильно ( разделение интересов парадигма): в паттерне MVC (Model-View-Controller) задача контроллеров не состоит в том, чтобы " модель »модель данных, но это задача уровня доступа к данным (который - в случае GORM - сами классы домена).

Таким образом, класс User будет реализован так:

class User {
    String userName
    String firstName
    String lastName
    String zip

    ZipCode retrieveZipCode() {
        ZipCode.findByZip(zip)
    }

static constraints = {
    zip nullable: false, blank: false, matches: /^\d{5}/,
    /* not tested at my machine: */
    validator: {
        if(!retrieveZipCode(it)) {
            return false
        }
    }
}
}

Обратите внимание на метод retrieveZipCode(). Он не называется getZipCode(), так как в противном случае Hibernate выдает исключение о «отсутствующем методе установки». Вы также можете поэкспериментировать с добавлением свойства zipCode, метода getZipCode() (который ничего не делает или, наоборот, выдает исключение) и добавлением свойства zipCode к определению transinients. - Все это (в любой комбинации) будет не работать.

Также обратите внимание на определение constraints: оно совпадает, когда zip состоит ровно из пяти цифр. (Я полагаю, что это формат почтовых индексов в США.) Следует также убедиться, что база данных содержит запись для почтового индекса пользователя (синтаксис не проверен).

Я немного изменил класс ZipCode (частично, чтобы избежать ошибки компиляции):

class ZipCode {
    String zip;
    String city;
    String state;
    Float latitude;
    Float longitude;
}

И, наконец, интеграция тест:

class UserTests extends GroovyTestCase {
    def testUserCreation() {
        User user = new User(
            userName: "foo", firstName: "bar", 
            lastName: "baz", zip: "12345")
        assert user.validate()
        assert user.retrieveZipCode()
        user.save()
    }
}

Спасибо

1 голос
/ 24 октября 2010

Это звучит как проблема пользовательского интерфейса. Выполните поиск Zipcode объекта в контроллере и установите объект, расположенный на пользователя. В противном случае я не вижу, как Zipcode мог быть изменен при создании пользователя.

save = {
  params.zip.id = Zipcode.findByZip(params.zip)
  def userInstance = new User(params)
}

или

save = {
  def userInstance = new User(params)
  userInstance.zip = Zipcode.findByZip(params.zip) 
}

Вы должны включить некоторую логику проверки (если почтовый индекс неправильный), а также рассмотреть возможность переименования params.zip в params.userProvidedZip или что-то в этом роде.

0 голосов
/ 24 октября 2010

использовать обратный вызов события домена

   transient beforeUpdate = { 
      // check to make sure that the zip code value remains the same
      // and is never changed... 
   } 
...