2010-10-14 3 views
22

Вот что я хотел бы сделать:Как добавить ограничения на наследуемых свойств в области Grails подклассу

class A { 
    String string 
    static constraints = { 
    string(maxSize:100) 
    } 
} 

class B extends A { 
    static constraints = { 
    string(url:true) 
    } 
} 

Так класс А должен иметь некоторые ограничения и B должны иметь то же самое плюс дополнительные ограничений на одно и то же свойство.

Я не мог заставить это работать, хотя и могу представить, что он столкнулся с концепцией «Таблица за иерархию».

Итак, я попытался обойти эту проблему, представив объект Command с ограничениями класса B, которые могут быть проверены в конструкторе класса B. Однако кажется, что объекты Command могут использоваться только в контроллерах (граф говорит, что там для него нет метода .validate().

Так что мой вопрос: что является самым элегантным способом решения этой проблемы с использованием ограничений Grails (не повторное выполнение проверки вручную)? Может быть ...

  • Переключившись на концепцию Table-per-Sub-Class?
  • Создание объекта Command в классе Domain каким-то образом?
  • Любой другой способ?

Edit: Было бы хорошо для меня, чтобы определить все ограничения в дочерних классах, повторяя ограничения родительского класса или даже не имеющие ограничения в родительском классе вообще. Но решение должно работать для нескольких дочерних классов (с разными ограничениями) одного и того же родительского класса.

+0

Я не уверен, что каждое ограничение будет работать таким образом, так как по умолчанию наследуются классы отображаются в одной таблице БД. Итак, если у вас есть класс C с ненулевыми, уникальными ограничениями на C.c, он наложит ограничение таблицы DB на всю таблицу A - и поле c будет там для всех классов и будет null для чего-либо, кроме экземпляров C. –

+0

Да, именно поэтому я привнес в игру Table-per-Sub-Class. –

ответ

5

Как это было в 2.x:

Как ограничений является закрытие выполняется некоторыми ConstraintsBuilder, я бы попробовать вызвать его из B, как

class B extends A { 
    static constraints = { 
    url(unique: true) 
    A.constraints.delegate = delegate # thanks Artefacto 
    A.constraints() 
    } 
} 
+1

Закрыть. Вы должны сначала перенести делегат 'A.constraints':' A.constraints.delegate = delegate'. Но спасибо, что указал мне в правильном направлении. – Artefacto

+2

@Artefacto - Вы могли бы опубликовать ответ, который работает, или отредактировать этот ответ, чтобы заставить его работать? Я знаю других, у которых был этот вопрос. Благодаря! – cdeszaq

+0

Я пробовал его с grails 2.0.4 (с консолью grails), и он не работает, он выдает ошибку в фазе, где A.contraints не имеет свойства делегата – jneira

1

В принципе я не вижу, как это может быть сделано.

Дизайн мудрого класса домена фактически отображает структуру таблицы базы данных. Ограничения будут фактически создавать ограничения DB. Таким образом, вы пытаетесь создать несколько объектов, которые будут создавать различные ограничения в одной таблице.

Я думаю, что лучшим подходом было бы создание одного объекта домена, который имеет простейшее подмножество ограничений, а затем использовать разные объекты команд для точной настройки точных ограничений, которые вы хотите передать в домен.

Вы также можете использовать валидатор: в ограничениях для тонкой настройки различных ограничений для разных типов объектов (что-то вроде столбца типов в домене и на основе разных типов выполняет другую проверку).

-1

Вам нужно переопределить ограничения суперкласса, потому что это статические clojure (статические свойства и статические методы не наследуются дочерними классами), поэтому он не отображается GORM.

Cheers.

7

Вы можете использовать

class B extends A { 
     static constraints = { 
      importFrom A 
      //B stuff 
     } 
    } 

как состояний в http://grails.org/doc/latest/ref/Constraints/Usage.html

+0

вы попробовали это? это сработало? –

+0

Я пробовал его на Grails 2.5.1 и отлично работает, спасибо! – Santee