I have a rather complex relation with a polymorphic through-model. In the app, there is a tag system, where users and another model can be tagged. To avoid duplicate string entries, I used a through model (TagLink) which contains the tag ID, the tagged model name and the tagged instance ID.
我与多态通模型有着相当复杂的关系。在应用程序中,有一个标记系统,可以标记用户和另一个模型。为了避免重复的字符串条目,我使用了一个直通模型(TagLink),它包含标记ID,标记的模型名称和标记的实例ID。
So I have
所以我有
User --+
|
+---> TagLink -----------> Tag
| - tagId - id
Item --+ - taggableId - text
- taggableName
(User or Item)
The linking relation is hasAndBelongsToMany
. The problem is, when I post a new tag to /items/:id/tags
or /users/:id/tags
, it is saved, but I can create as many as I want with the same text without any error.
链接关系是hasAndBelongsToMany。问题是,当我将新标签发布到/ items /:id / tags或/ users /:id / tags时,它会被保存,但我可以使用相同的文本创建任意数量的标签而不会出现任何错误。
What I would like is, upon posting to /items/:id/tags
or /users/:id/tags
, it :
我想要的是,发布到/ items /:id / tags或/ users /:id / tags后,它:
- creates a new tag entry if it does not already exists, then adds a new
TagLink
entry (this is the current behaviour, but even when the same tag already exists) - 创建一个新的标记条目(如果它尚不存在),然后添加一个新的TagLink条目(这是当前行为,但即使已经存在相同的标记)
- solely creates a
TagLink
entry when a tag already exists - 仅在标记已存在时创建TagLink条目
I thought about two solutions :
我想到了两个解决方案:
- Somehow override the create method of
Tag
to check for existence, then manually create aTagLink
entry if it exists. If not, proceed as by default. - 以某种方式覆盖Tag的create方法以检查是否存在,然后手动创建TagLink条目(如果存在)。如果没有,请默认继续。
- Expose the tag list (
/tags
) with ~all CRUD URIs, then force to use the tag ID on/{items,users}/:id/tags
. - 使用〜所有CRUD URI公开标记列表(/ tags),然后强制使用/ {items,users} /:id / tags上的标记ID。
Ideally, I would prefer the first one as it is more transparent and makes a smoother API.
理想情况下,我更喜欢第一个,因为它更透明,并使API更顺畅。
So, any leads would be welcome!
所以,任何线索都会受到欢迎!
1 个解决方案
#1
1
I ended up doing the first solution, which was pretty easy. The idea is to replace the User.create
method in a boot script which finds a tag with the same text
, and returns it if one is found.
我最终做了第一个解决方案,这非常简单。我们的想法是在引导脚本中替换User.create方法,该脚本找到具有相同文本的标记,并在找到一个标记时返回它。
module.exports = function(app) {
var Tag = app.models.Tag;
// Override Tag.create to avoid duplicates
Tag.createRaw = Tag.create;
Tag.create = function(data, token, cb) {
// Find matching tag
Tag.findOne({where: {text: data.text}}, (err, tag) => {
if (err) cb(err);
// If the tag is found, return it
else if (tag) cb(null, tag);
// Else create it
else Tag.createRaw(data, token, cb);
});
}
}
#1
1
I ended up doing the first solution, which was pretty easy. The idea is to replace the User.create
method in a boot script which finds a tag with the same text
, and returns it if one is found.
我最终做了第一个解决方案,这非常简单。我们的想法是在引导脚本中替换User.create方法,该脚本找到具有相同文本的标记,并在找到一个标记时返回它。
module.exports = function(app) {
var Tag = app.models.Tag;
// Override Tag.create to avoid duplicates
Tag.createRaw = Tag.create;
Tag.create = function(data, token, cb) {
// Find matching tag
Tag.findOne({where: {text: data.text}}, (err, tag) => {
if (err) cb(err);
// If the tag is found, return it
else if (tag) cb(null, tag);
// Else create it
else Tag.createRaw(data, token, cb);
});
}
}