acts-as-taggable-on gem 不清除标签的奇怪行为
Weird behaviors on acts-as-taggable-on gem of not clearing taggings
我有一个名为 Recipe 的模型,它使用了被报告的 acts-as-taggable-on gem to add taggings to the recipes. The weird behavior is when I edit and update the recipe via the controller, the recipe taggings are added instead of updating to proper taggings. There was a similar Github issue,但没有任何人回复。我的 acts-as-taggable-on gem 版本是 3.2.6.
例如,我的食谱有三个标签:fruit
、fruit
和 vegetables
。 fruit
标签不相关,所以我在 f.tag_list
输入字段中删除了这两个 fruit
标签,只包含 vegetables
.
Processing by Users::RecipesController#update as JS
Parameters: {"utf8"=>"✓", "recipe"=>{"image_ids"=>"46746", "cover_image_id"=>"46746",
"name"=>"Cauliflower", "description"=>"this is the description", "preparation_time_hr"=>"0",
"preparation_time_min"=>"50", "servings"=>"4",
"category_ids"=>"", "cuisine_ids"=>"", "tag_list"=>"vegetables", "ingredients"=>....}
users/recipes_controller.rb
def update
if @recipe.update_attributes(recipe_params)
if params[:publish_recipe] && params[:publish_recipe] == "true"
update_status!(:publish!)
end
redirect_to user_recipes_url
else
respond_to do |format|
format.html{ render "edit" }
format.js { render partial: "shared/flash_message", locals: { flash_type: "error", flash_message: "#{@recipe.errors.full_messages.to_sentence}" } }
end
end
end
recipe_params
包括 tag_list
作为允许的参数。
def recipe_params
params.required(:recipe).permit(:name, :category_ids, :cuisine_ids, :tag_list, :preparation_time_hr,
:cover_image_id, :preparation_time_min, :servings, :description, :image_ids, :commentable,
ingredients_attributes: [:id, :name, :_destroy],
instructions_attributes: [:id, :text, :_destroy, image_attributes: [:id, :picture, :_destroy]]
) rescue {}
end
但最终旧标签没有被删除,新标签已添加到列表中:fruit
、fruit
、vegetables
、vegetables
。
另一件奇怪的事情是,当我试图查看食谱的 tag_list 时,它是一个空数组。尝试在 rails 控制台中编辑 tag_list
,它添加了另一个标记,但是当我编辑 r.reload
时,tag_list
它仍然是一个空数组。现在菜谱和标签的关系是这样的:
r = Recipe.find(20980)
[56] pry(main)> r.tag_list
ActsAsTaggableOn::Tag Load (14.9ms) SELECT `tags`.* FROM `tags` INNER JOIN `taggings` ON `tags`.`id` = `taggings`.`tag_id` WHERE `taggings`.`taggable_id` = 20980 AND `taggings`.`taggable_type` = 'Recipe' AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)
=> []
[57] pry(main)> r.tags
=> [#<ActsAsTaggableOn::Tag id: 2, name: "fruit", taggings_count: 1138, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:47:20", updated_at: "2015-07-25 15:47:53">,
#<ActsAsTaggableOn::Tag id: 2, name: "fruit", taggings_count: 1138, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:47:20", updated_at: "2015-07-25 15:47:53">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">]
[58] pry(main)> r.taggings
ActsAsTaggableOn::Tagging Load (35.8ms) SELECT `taggings`.* FROM `taggings` WHERE `taggings`.`taggable_id` = 20980 AND `taggings`.`taggable_type` = 'Recipe'
=> [#<ActsAsTaggableOn::Tagging id: 20408, tag_id: 2, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 03:56:13">,
#<ActsAsTaggableOn::Tagging id: 20409, tag_id: 2, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 03:56:14">,
#<ActsAsTaggableOn::Tagging id: 20410, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:01:36">,
#<ActsAsTaggableOn::Tagging id: 20411, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:47:38">,
#<ActsAsTaggableOn::Tagging id: 20412, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:53:38">]
tag_list
数据库查询也很奇怪,为什么查询包含这个taggings.tagger_id IS NULL
?
我对这个 gem 还是个新手,知道如何使用 gem 方法正确更新标签吗?我希望我可以避免使用我自己的代码更新标签以避免进一步的问题。注意我的Recipe模型是paper_trailgem版本的,希望与这个问题无关。
由于网上没有解决办法,而且我只在Recipe上使用这个taggable,所以我现在手动调用一个方法来在模型保存后重新更新标签。
def update_tags(tag_list)
self.taggings.destroy_all
list = tag_list.split(",")
list.each do |t|
tag = Tag.find_or_create_by(name: t)
self.taggings.create(tag_id: tag.id, context: "tags")
end
return self.taggings
end
我仍然认为这个问题有更好的解决方案,我愿意接受替代方案作为最佳答案。
我在 act-as-taggable-on 文档中看不到任何关于当 tags_list
作为参数进入 update_attributes
方法时会发生什么的内容,但在你的情况下似乎添加标签而不删除现有标签。我确实在文档中注意到 tag_list 可以分配给 =
来替换现有标签:
You can also add and remove tags by direct assignment. Note this will remove existing tags so use it with attention.
@user.tag_list = "awesome, slick, hefty"
@user.save
所以你可以在你的更新方法中做到这一点
def update
if @recipe.update_attributes(recipe_params)
@recipe.tag_list = recipe_params["tag_list"]
@recipe.save
...
else
...
end
end
我有一个名为 Recipe 的模型,它使用了被报告的 acts-as-taggable-on gem to add taggings to the recipes. The weird behavior is when I edit and update the recipe via the controller, the recipe taggings are added instead of updating to proper taggings. There was a similar Github issue,但没有任何人回复。我的 acts-as-taggable-on gem 版本是 3.2.6.
例如,我的食谱有三个标签:fruit
、fruit
和 vegetables
。 fruit
标签不相关,所以我在 f.tag_list
输入字段中删除了这两个 fruit
标签,只包含 vegetables
.
Processing by Users::RecipesController#update as JS
Parameters: {"utf8"=>"✓", "recipe"=>{"image_ids"=>"46746", "cover_image_id"=>"46746",
"name"=>"Cauliflower", "description"=>"this is the description", "preparation_time_hr"=>"0",
"preparation_time_min"=>"50", "servings"=>"4",
"category_ids"=>"", "cuisine_ids"=>"", "tag_list"=>"vegetables", "ingredients"=>....}
users/recipes_controller.rb
def update
if @recipe.update_attributes(recipe_params)
if params[:publish_recipe] && params[:publish_recipe] == "true"
update_status!(:publish!)
end
redirect_to user_recipes_url
else
respond_to do |format|
format.html{ render "edit" }
format.js { render partial: "shared/flash_message", locals: { flash_type: "error", flash_message: "#{@recipe.errors.full_messages.to_sentence}" } }
end
end
end
recipe_params
包括 tag_list
作为允许的参数。
def recipe_params
params.required(:recipe).permit(:name, :category_ids, :cuisine_ids, :tag_list, :preparation_time_hr,
:cover_image_id, :preparation_time_min, :servings, :description, :image_ids, :commentable,
ingredients_attributes: [:id, :name, :_destroy],
instructions_attributes: [:id, :text, :_destroy, image_attributes: [:id, :picture, :_destroy]]
) rescue {}
end
但最终旧标签没有被删除,新标签已添加到列表中:fruit
、fruit
、vegetables
、vegetables
。
另一件奇怪的事情是,当我试图查看食谱的 tag_list 时,它是一个空数组。尝试在 rails 控制台中编辑 tag_list
,它添加了另一个标记,但是当我编辑 r.reload
时,tag_list
它仍然是一个空数组。现在菜谱和标签的关系是这样的:
r = Recipe.find(20980)
[56] pry(main)> r.tag_list
ActsAsTaggableOn::Tag Load (14.9ms) SELECT `tags`.* FROM `tags` INNER JOIN `taggings` ON `tags`.`id` = `taggings`.`tag_id` WHERE `taggings`.`taggable_id` = 20980 AND `taggings`.`taggable_type` = 'Recipe' AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)
=> []
[57] pry(main)> r.tags
=> [#<ActsAsTaggableOn::Tag id: 2, name: "fruit", taggings_count: 1138, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:47:20", updated_at: "2015-07-25 15:47:53">,
#<ActsAsTaggableOn::Tag id: 2, name: "fruit", taggings_count: 1138, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:47:20", updated_at: "2015-07-25 15:47:53">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">,
#<ActsAsTaggableOn::Tag id: 531, name: "vegetables", taggings_count: 21, tagger_id: nil, tagger_type: nil, created_at: "2015-07-25 15:56:15", updated_at: "2015-07-25 15:56:16">]
[58] pry(main)> r.taggings
ActsAsTaggableOn::Tagging Load (35.8ms) SELECT `taggings`.* FROM `taggings` WHERE `taggings`.`taggable_id` = 20980 AND `taggings`.`taggable_type` = 'Recipe'
=> [#<ActsAsTaggableOn::Tagging id: 20408, tag_id: 2, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 03:56:13">,
#<ActsAsTaggableOn::Tagging id: 20409, tag_id: 2, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 03:56:14">,
#<ActsAsTaggableOn::Tagging id: 20410, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:01:36">,
#<ActsAsTaggableOn::Tagging id: 20411, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:47:38">,
#<ActsAsTaggableOn::Tagging id: 20412, tag_id: 531, taggable_id: 20980, taggable_type: "Recipe", tagger_id: 200422, tagger_type: "User", context: "tags", created_at: "2015-08-21 04:53:38">]
tag_list
数据库查询也很奇怪,为什么查询包含这个taggings.tagger_id IS NULL
?
我对这个 gem 还是个新手,知道如何使用 gem 方法正确更新标签吗?我希望我可以避免使用我自己的代码更新标签以避免进一步的问题。注意我的Recipe模型是paper_trailgem版本的,希望与这个问题无关。
由于网上没有解决办法,而且我只在Recipe上使用这个taggable,所以我现在手动调用一个方法来在模型保存后重新更新标签。
def update_tags(tag_list)
self.taggings.destroy_all
list = tag_list.split(",")
list.each do |t|
tag = Tag.find_or_create_by(name: t)
self.taggings.create(tag_id: tag.id, context: "tags")
end
return self.taggings
end
我仍然认为这个问题有更好的解决方案,我愿意接受替代方案作为最佳答案。
我在 act-as-taggable-on 文档中看不到任何关于当 tags_list
作为参数进入 update_attributes
方法时会发生什么的内容,但在你的情况下似乎添加标签而不删除现有标签。我确实在文档中注意到 tag_list 可以分配给 =
来替换现有标签:
You can also add and remove tags by direct assignment. Note this will remove existing tags so use it with attention.
@user.tag_list = "awesome, slick, hefty" @user.save
所以你可以在你的更新方法中做到这一点
def update
if @recipe.update_attributes(recipe_params)
@recipe.tag_list = recipe_params["tag_list"]
@recipe.save
...
else
...
end
end