0

1対多の関連付けのデータバインディングを処理するGrailsの機能を利用しようとしています。リレーションシップに正常に割り当てることはできますが、単一の要素またはすべての要素を削除しても機能しません。

これが私のモデルがどのように見えるかの例です:

class Location {
    Float latitude
    Float longitude
}

class Route {
    Location start
    Location stop

    static belongsTo: [courier: Courier]
}

class Courier {
    String name
    static hasMany = [pickups: Location]
}

class ScheduledCourier extends Courier {
    static hasMany = [routes: Route]

    static mapping = {
        routes(cascade: 'all-delete-orphan')
    }
}

Webサイトを介して新しいScheduledCourierオブジェクトを作成する場合、次のようにマークアップで自動的にバインドするルートのリストを渡すことができます。

<input type="hidden" name="routes[0].latitude" value="5" />
<input type="hidden" name="routes[0].longitude" value="5" />
<input type="hidden" name="routes[1].latitude" value="10" />
<input type="hidden" name="routes[1].longitude" value="10" />

これは私のコントローラーでうまく機能します:

class CourierController {
    // Very simplistic save
    def saveScheduled = {
        def courier = new ScheduledCourier(params)
        courier.save()
    }

    // Very simplistic update
    def update = {
        def courier = Courier.get(params.id)
        courier.properties = params
        courier.save()
    }
}

代わりに次のマークアップを使用すると、デバッガーをステップスルーして、routesプロパティが[]になり、オブジェクトは正常に保存されますが、レコードはデータベースから削除されないことがわかります。

<input type="hidden" name="routes" value="" />

さらに、次のようなマークアップを送信した場合:

<input type="hidden" name="routes[0].latitude" value="5" />
<input type="hidden" name="routes[0].longitude" value="5" />

courier.routesは、1つのオブジェクトのみを含むように更新されません。

誰かがこの行動を見たことがありますか?

これはGrails1.3.7です...少なくとも今のところは。

この動作を再現する統合テストを作成しました。

public void testCourierSave() {
    def l1 = new Location(latitude: 5, longitude: 5).save(flush: true)
    def l2 = new Location(latitude: 10, longitude: 10).save(flush: true)

    def params = ["name": "Courier", "pickups[0].id": l1.id, "pickups[1].id": l2.id,
        "routes[0].start.id": l1.id, "routes[0].stop.id": l2.id,
        "routes[1].start.id": l2.id, "routes[1].stop.id": l1.id]

    def c1 = new ScheduledCourier(params).save(flush: true)

    assertEquals(2, c1.routes.size())

    params = [routes: ""]
    c1.properties = params
    c1.save(flush: true)
    c1.refresh()    // Since the Routes aren't deleted, this reloads them

    assertEquals(0, c1.routes.size())    // Fails

    assertEquals([], Route.findAllByCourier(c1))    // Fails if previous assert is removed
}
4

1 に答える 1

1

次のことが起こっているのだろうか:

フレームワークを渡すとき、params [routes:""]それは単なる空の文字列であるため、フレームワークはそれを無視します。

同様に<input type="hidden" name="routes[0].latitude" value="5" />、おそらくコレクション内の0番目のルートエントリを更新するだけですが、他のエントリは削除されません。これは、0番目のルートの緯度の値は5である必要があるということだけであり、これが現在の唯一のルートであるということではないためです。コレクション。

routes.clear()必要な効果を得るには、パラメータをバインドする前にを追加する必要があります。

モデルの状態がデータベースに永続化されるタイミングを制御するには、Grailsで使用可能なSpringトランザクション性を使用できます。これにより、後続の処理が失敗した場合に、オブジェクトの元の状態に戻すことができます。例えば:

Courier.withTransaction {status ->

  // Load the courier

  //clear the existing routes

  // bind the new properties

  // perform extra processing

  //if the object is invalid, roll back the changes
  status.setRollbackOnly()

}
于 2012-07-23T06:34:36.520 に答える