私は何かが欠けていると確信していますが、Bookshelf APIは執拗に混乱します。これが私がやろうとしていることです:
Radio
という名前のアプリケーション割り当ての文字列主キーと、この例の目的のために、_example1
_および_example2
_という名前の2つのフィールドを持つserial
というモデルがあります。モデル定義でカスタムIDを_idAttribute: 'serial'
_で指定しました。そして特にこの例では:
example1
_および_example2
_を設定します。example1
_を設定し、_example2
_を変更せずにそのままにします。したがって、Bookshelfモデルには、クラス(つまり「静的」)メソッド(「info」には「serial」、「example1」、「example2」のフィールドがあります)として、次のようなものがあります。
_insertOrUpdate: function (info) {
return new Radio({'serial':info.serial}).fetch().then(function (model) {
if (model) {
model.set('example1', info.example1);
return model.save({}, {
method: 'update',
patch: true
})
} else {
return new Radio({
serial: info.serial,
example1: info.example1,
example2: info.example2
}).save({}, {
method: 'insert'
})
}
}).then(function (model) {
console.log("SUCCESS");
}).catch(function (err) {
console.log("ERROR", err);
});
}
_
呼び出し例:
_Radio.insertOrUpdate({
serial: ...,
example1: ...,
example2: ...
})
_
ここで実行している問題は、「挿入」ケースが機能しているのに、「更新」ケースが失敗して次のようになることです。
_ERROR { Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where `serial` = '123223'' at line 1
_
これは、生成されたクエリにset
句が欠落しているKnexデバッグがオンになっている場合に明らかです。
_update `radios` set where `serial` = ?
_
今、私は fetch
と save
のBookshelfドキュメントに焦点を当てており、間違った方向に向かっているかどうか疑問に思っています。
私は間違ったAPIを使用していることを知っていますが、それを理解することができません。私が気付いた奇妙なことのいくつかは、それを半動作状態にするためだけに実行する必要がありました。
save
の最初のパラメータがわかりません。 saveがModel
のstaticメソッドだった場合、それはだろう意味がありますが、そうではありません。これはインスタンスメソッドであり、Model
コンストラクターに属性を渡すことができます(たとえば、new X(a:1).save({a:2})
はどういう意味ですか?)。また、保存前にset
で属性を設定できます。だから私はこれを理解できません。オプションを指定するには、プレースホルダーとして_{}
_を渡す必要がありました。
これは forge
ですが、Model
コンストラクターに属性を既に渡すことができるため、その目的が何であるかはわかりません(作成者がX.forge({a:1})
とnew X({a:1})
...?)。
Bookshelfの癖のため、保存するメソッドを明示的に指定する必要があることがわかりました。Bookshelfはメソッドの選択をisNew()
に基づいていますが、isNew()
は常にtrue
であり、IDを渡すとモデルコンストラクタに追加します。これは、アプリケーションが割り当てたIDの場合に行う必要があります。したがって、アプリケーションが割り当てたIDの場合、Bookshelfはalwaysが「挿入」を実行しますalwaysがモデルを「新しい」と考えるためです。したがって、メソッドを強制的に「更新」する必要があります...これは、私のBookshelfの混乱に追加されます。
とにかく、どうすればこれを正しく行うことができますか?この挿入と更新を機能させるにはどうすればよいですか?
さらに重要なことに、これはどこに文書化されているのでしょうか?誠実に私はそれがどこかに明確に文書化されていると仮定します、そして今私は木の森を見ることができないだけなので、私はこれを理解する必要があるので、ドキュメントは直接的な回答以上のものです。私は実際の開発ではなく、本棚にたくさんの時間を費やしてきました。
それは興味深いもので、何が起こっているのかを理解するのに少し時間がかかりました。
ご存知のように、patch
オプションに関するsave()
method documentation は、
保存する引数で指定された属性のみを保存します。
したがって、コードを次のように変更するだけです
_if (model) {
model.set('example1', info.example1);
return model.save();
}
_
set
属性が保存されます。
[〜#〜] but [〜#〜][〜#〜] but [〜#〜][〜#〜] but [〜#〜][〜#〜] but [〜#〜]
[〜#〜] all [〜#〜]属性はupdate
ステートメントに含まれ、id
!
これはORMの一般的な動作であり、その理由は、あるトランザクションからデータを取得して別のトランザクションから保存している場合(悪い、悪い習慣です!)、データが他のクライアントによって変更された可能性があります。そのため、属性の一部のみを保存すると、矛盾した状態になる可能性があります。
しかし、patch
属性の存在そのものがこの概念に違反しています。したがって、本棚は次の方法で改善できます。
patch
オプションを廃止するだけです。 (私はそれを好むかもしれません)patch
オプションも廃止される可能性があります。patch
セマンティクスをsave()
で提供されるものだけではなく、変更された属性に関連付けることです。ただし、このような変更により、残念ながら一部のユースケースが機能しなくなる可能性があります。数回の推測の後、私はそれを機能させたように見えますが、これが正しいかどうか、または推測せずにこれをどのように判断できたかはわかりません。
基本的には、「更新」ケースを次のように変更することで機能させることができました。
save
で設定するのではなく、最初のパラメーターとしてset
に渡します。以下の最終的なソリューションにつながります。
insertOrUpdate: function (info) {
return new Radio({'serial':info.serial}).fetch().then(function (model) {
if (model) {
// pass params to save instead of set()
var params = { 'example1' : info.example1 }
return model.save(params, {
method: 'update',
patch: true
})
} else {
return new Radio({
serial: info.serial,
example1: info.example1,
example2: info.example2
}).save({}, {
method: 'insert'
})
}
}).then(function (model) {
console.log("SUCCESS");
}).catch(function (err) {
console.log("ERROR", err);
});
}
forge
がどのように/ここに収まるのか、または「挿入」の場合のsave
の最初のパラメーターとの取り引きがどうあるべきかはまだわかりません。
さらに重要なことに、私はset
が何のためにあるのかを完全に確信していません。 ORMフレームワークの主な利点の1つは想定のようなものを透明にすることです(つまり、「保存」が正しく機能する一方で、モデルを考えずに、使用せずに使用できます。あなたが「保存」した時点で何が変更されたかについての知識-私すべき事前に未知の任意のコードset
の事柄を知ることができ、何が変更されたかを知らなくてもそれを保存できる、しかしそれは私にはできないように見えます)、それで私が本棚から実際にここで何を得たかはわかりません。より良いアプローチがあるはずです。