私の最終目標は、次のようなドメイン クラスを持つことです。
- プロパティを考慮して生成される
equals
およびhashCode
メソッド@EqualsAndHashCode
hasMany
- ドメイン クラスのプロパティの
unique
制約では、プロパティがhasMany
考慮されます - ドメイン クラスのインスタンスは、そのプロパティの 1 つが既存のインスタンスと異なる限り、一意であると見なされます。
@James Kleeh と @dmahapatro のおかげで、私は近いと思いますが、ポイント 2 と 3 が問題を引き起こしています。
testFooWithMockedBar
要件をテストする最初の試みは、FooTests.groovy
ファイルの単体テストでした。Bar.get()
そのテストで使用しようとしていますが、機能していません。への呼び出しもうまくいかなかったと思いmockForConstraintsTests
ます。
私は次のテストでこの問題を修正しtestFooWithoutMockedBar
たと確信していますが、次に説明するように、テストが私が思っていることを行っているかどうかはわかりません。
合格した後testFooWithoutMockedBar
、アプリを開発モードで実行して、期待どおりに機能するかどうかを確認しました。残念ながら、ファイルbars
内の行の属性が原因で、Grails がデータベース内にテーブルを作成できません。これが私が得るエラーです:prop1(unique: ['prop2', 'prop3', 'bars'])
Foo.groovy
foo
| Error 2013-08-20 16:17:52,249 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - Unsuccessful: create table foo (id bigint not null auto_increment, version bigint not null, prop1 varchar(255) not null, prop2 varchar(255) not null, prop3 varchar(255) not null, primary key (id), unique (foo_bars_id, prop3, prop2, prop1)) ENGINE=InnoDB
| Error 2013-08-20 16:17:52,250 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - Key column 'foo_bars_id' doesn't exist in table
| Error 2013-08-20 16:17:52,309 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - Unsuccessful: alter table foo_bar add index FKD76E651A96EEE146 (foo_bars_id), add constraint FKD76E651A96EEE146 foreign key (foo_bars_id) references foo (id)
| Error 2013-08-20 16:17:52,310 [localhost-startStop-1] ERROR hbm2ddl.SchemaExport - Can't create table 'foobar.#sql-474_8c' (errno: 150)
これを修正するためのグルーヴィーな方法があるかどうかはわかりません。それを修正するために私が考えることができる唯一の方法は、カスタムバリデーターを使用することですFoo.groovy
:
class Foo {
...
boolean isUnique
static transients = ['isUnique']
static constraints = {
isUnique(
validator: { val, obj ->
def rslt = true
for(foo in Foo.getAll()) {
if (foo == obj) {
rslt = false
break
}
}
return rslt
}
)
bars(nullable: false)
}
私がやりたいことをするためのより良い方法はありますか?
フーグルービー
package foobar
@groovy.transform.EqualsAndHashCode
class Foo {
String prop1
String prop2
String prop3
Set<Bar> bars
static hasMany = [bars: Bar]
static constraints = {
prop1(unique: ['prop2', 'prop3', 'bars']) // The 'bars' in this line is preventing Grails from creating the foo table in the database.
bars(nullable: false)
}
}
Bar.groovy
package foobar
@groovy.transform.EqualsAndHashCode
class Bar {
String prop1
}
FooTests.groovy
package foobar
import grails.test.mixin.*
import org.junit.*
@TestFor(Foo)
@Mock(Bar)
class FooTests {
void testFooWithMockedBar() {
// Create existing instances to validate against
mockForConstraintsTests(Bar, [
new Bar(prop1: "a"),
new Bar(prop1: "b"),
new Bar(prop1: "c"),
new Bar(prop1: "d")
]
)
mockForConstraintsTests(Foo, [
new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(1), Bar.get(2)])
]
)
// Validation should fail if all properties are null
def foo = new Foo()
assert !foo.validate()
assert "nullable" == foo.errors["prop1"]
assert "nullable" == foo.errors["prop2"]
assert "nullable" == foo.errors["prop3"]
assert "nullable" == foo.errors["bars"]
// Test unique constraints
foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(1), Bar.get(2)])
assert !foo.validate()
assert "unique" == foo.errors["prop1"]
// Validation should pass with all unique, not null properties
foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(3), Bar.get(4)])
assert foo.validate()
// Test equals and hashCode
assert foo == new Foo(prop1: "a", prop2: "b", prop3: "c", bars: [Bar.get(3), Bar.get(4)])
}
void testFooWithoutMockedBar() {
// Create existing instances to validate against
def bars1 = [new Bar(prop1: "a"), new Bar(prop1: "b")]
def bars2 = [new Bar(prop1: "c"), new Bar(prop1: "d")]
mockForConstraintsTests(Foo, [
new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)
]
)
// Validation should fail if all properties are null
def foo = new Foo()
assert !foo.validate()
assert "nullable" == foo.errors["prop1"]
assert "nullable" == foo.errors["prop2"]
assert "nullable" == foo.errors["prop3"]
assert "nullable" == foo.errors["bars"]
// Test unique constraints
foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)
assert !foo.validate()
assert "unique" == foo.errors["prop1"]
// Validation should pass
foo = new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars2)
assert foo.validate()
// Test equals and hashCode
assert foo != new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars1)
assert foo == new Foo(prop1: "a", prop2: "b", prop3: "c", bars: bars2)
}
}