acts-as-taggable-on在数据库中创建重复的行

时间:2012-09-27 22:19:13

标签: ruby-on-rails ruby acts-as-taggable-on

我正在为Rails应用程序使用act-as-taggable-on,每次我创建一个新的Photo(例如)时,我都会在'标记中获得重复的行。表

我的模型类看起来像:

class User < ActiveRecord::Base
  acts_as_tagger
  ...
end

class Photo < ActiveRecord::Base
   acts_as_taggable_on :tags
   ...
end

和我的photos_controller的创建动作

def create
  @user = current_user
  ... 
  @user.tag(@photo, :with => params[:photo][:tag_list], :on => :tags)
  ...
end

奇怪的是,我在&#39;标记中获得了重复的行。表格第一行有&#39; tagger_id&#39;和&#39; tagger_type&#39;设置为NULL,而重复行具有正确的值。

我的Gemfile看起来像这样

gem 'rails', '3.2.8'
gem 'acts-as-taggable-on', '~> 2.3.1'

之前有没有人见过这种行为?这是我的配置问题吗?

更新: 看着控制台,我可以清楚地看到正在执行的两个事务,在第一个事务中就是这样:

SQL (0.6ms)  INSERT INTO "taggings" ("context", "created_at", "tag_id", 
"taggable_id", "taggable_type", "tagger_id", "tagger_type") VALUES (?, ?, ?, ?, ?, ?, ?)
[["context", "tags"], ["created_at", Thu, 27 Sep 2012 21:49:22 UTC +00:00], ["tag_id",
 12], ["taggable_id", 10], ["taggable_type", "Photo"], 
["tagger_id", nil], ["tagger_type", nil]]

很明显tagger_id设置为null以及tagger_type。

这是一个完整的控制台输出,我将这些行分开以帮助阅读它。您将注意到两个单独的事务,在第一个事务中,插入时带有NULL值,而在第二个事务结束时,您将看到正确的事务。

开始发布&#34; / photo&#34;在2012-09-28 07:39:58 +0200的127.0.0.1 由PhotoController处理#create as HTML   参数:{&#34; utf8&#34; =&gt;&#34;✓&#34;,&#34; authenticity_token&#34; =&gt;&#34; IOmnfDpU7V7vYw3h6RXXzXPsXf / B0fcVihXhb + S8JHU =&#34;, &#34;照片&#34; =&gt; {&#34; url&#34; =&gt;&#34; www.another.com/photo.jpg",&#34; title&#34; =&gt; ;&#34;另一个&#34;,&#34; tag_list&#34; =&gt;&#34; a_tag&#34;,&#34;说明&#34; =&gt;&#34;&#34;, &#34;私人&#34; =&gt;&#34; 0&#34;},&#34;提交&#34; =&gt;&#34;添加照片&#34;} 重定向到http://www.somedomain.com:3000/users/christiangiacomi

完成302发现在414ms(ActiveRecord:20.5ms)

用户负载(0.3ms)SELECT&#34;用户&#34;。* FROM&#34;用户&#34;用户&#34;。&#34;用户名&#34; =&#39; christiangiacomi&#39;限制1   ActsAsTaggableOn :: Tag Load(0.2ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; INNER JOIN&#34;标签&#34; ON&#34;标签&#34;。&#34; id&#34; =&#34;标记&#34;。&#34; tag_id&#34;标签&#34;。&#34; taggable_id&#34; IS NULL和&#34;标记&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND(taggings.context =&#39; tags&#39; AND taggings.tagger_id IS NULL)

(0.1ms)开始交易

SQL(6.2ms)INSERT INTO&#34; photos&#34; (&#34; created_at&#34;,&#34;说明&#34;,&#34;收藏&#34;,&#34;私人&#34;,&#34;标题&#34;,&#34; updated_at&#34;,&#34; url&#34;,&#34; user_id&#34;)VALUES(?,?,?,?,?,?,?,?)[[&#34; created_at&#34 ;,星期五,2012年9月28日05:39:59 UTC +00:00],[&#34;描述&#34;,&#34;&#34;],[&#34;最爱&#34;,false ],[&#34;私人&#34;,假],[&#34;标题&#34;,&#34;另一个&#34;],[&#34; updated_at&#34;,星期五,2012年9月28日05:39:59 UTC +00:00],[&#34; url&#34;,&#34; http://www.another.com/photo.jpg"],[&#34; user_id& #34;,1]]

ActsAsTaggableOn :: Tag Load(3.2ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; WHERE(lower(name)=&#39; a_tag&#39;)   ActsAsTaggableOn ::标签存在(0.1ms)SELECT 1 AS一个FROM&#34;标签&#34;在哪里&#34;标签&#34;。&#34;名称&#34; =&#39; a_tag&#39;限制1

SQL(0.2ms)INSERT INTO&#34;标签&#34; (&#34;名称&#34;)价值观(?)[[&#34;名称&#34;,&#34; a_tag&#34;]]

ActsAsTaggableOn :: Tag Load(0.1ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; INNER JOIN&#34;标签&#34; ON&#34;标签&#34;。&#34; id&#34; =&#34;标记&#34;。&#34; tag_id&#34;标签&#34;。&#34; taggable_id&#34; = 13 AND&#34;标签&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND(taggings.context =&#39; tags&#39; AND taggings.tagger_id IS NULL)

ActsAsTaggableOn ::标记存在(0.2ms)SELECT 1 AS一个FROM&#34;标记&#34;在哪里(&#34;标签&#34;。&#34; tag_id&#34; = 16 AND&#34;标签&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND& #34;标记&#34;。&#34; taggable_id&#34; = 13 AND&#34;标记&#34;。&#34; context&#34; =&#39;标记&#39; AND&#34; taggings&#34;。&#34; tagger_id&#34; IS NULL AND&#34; taggings&#34;。&#34; tagger_type&#34; IS NULL)LIMIT 1

SQL(0.7ms)INSERT INTO&#34;标记&#34; (&#34; context&#34;,&#34; created_at&#34;,&#34; tag_id&#34;,&#34; taggable_id&#34;,&#34; taggable_type&#34;,&#34; tagger_id&#34;,&#34; tagger_type&#34;)VALUES(?,?,?,?,?,?,?)[[&#34; context&#34;,&#34; tags&#34;] ,[&#34; created_at&#34;,星期五,2012年9月28日05:39:59 UTC +00:00],[&#34; tag_id&#34;,16],[&#34; taggable_id&#34; ,13,[&#34; taggable_type&#34;,&#34; Photo&#34;],[&#34; tagger_id&#34;,nil],[&#34; tagger_type&#34;,nil]]

(4.1ms)提交事务

(0.1ms)开始交易

ActsAsTaggableOn :: Tag Load(0.2ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; WHERE(lower(name)=&#39; a_tag&#39;)

ActsAsTaggableOn :: Tag Load(0.2ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; INNER JOIN&#34;标签&#34; ON&#34;标签&#34;。&#34; id&#34; =&#34;标记&#34;。&#34; tag_id&#34;标签&#34;。&#34; taggable_id&#34; = 13 AND&#34;标签&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND(taggings.context =&#39; tags&#39; AND taggings.tagger_id IS NULL)

CACHE(0.0ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; WHERE(lower(name)=&#39; a_tag&#39;)

ActsAsTaggableOn :: Tag Load(0.2ms)SELECT&#34; tags&#34;。* FROM&#34; tags&#34; INNER JOIN&#34;标签&#34; ON&#34;标签&#34;。&#34; id&#34; =&#34;标记&#34;。&#34; tag_id&#34;标签&#34;。&#34; taggable_id&#34; = 13 AND&#34;标签&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND(taggings.context =&#39;标签&#39; AND  taggings.tagger_id = 1 AND  taggings.tagger_type =&#39;用户&#39;)

ActsAsTaggableOn ::标记存在(0.4ms)SELECT 1 AS一个FROM&#34;标记&#34;在哪里(&#34;标签&#34;。&#34; tag_id&#34; = 16 AND&#34;标签&#34;。&#34; taggable_type&#34; =&#39;照片&#39; AND& #34;标记&#34;。&#34; taggable_id&#34; = 13 AND&#34;标记&#34;。&#34; context&#34; =&#39;标记&#39; AND&#34;标签&#34;。&#34; tagger_id&#34; = 1 AND&#34;标记&#34;。&#34; tagger_type&#34; =&#39;用户&#39;)LIMIT 1

SQL(0.5ms)INSERT INTO&#34;标记&#34; (&#34; context&#34;,&#34; created_at&#34;,&#34; tag_id&#34;,&#34; taggable_id&#34;,&#34; taggable_type&#34;,&#34; tagger_id&#34;,&#34; tagger_type&#34;)VALUES(?,?,?,?,?,?,?)[[&#34; context&#34;,&#34; tags&#34;] ,[&#34; created_at&#34;,星期五,2012年9月28日05:39:59 UTC +00:00],[&#34; tag_id&#34;,16],[&#34; taggable_id&#34; ,13,[&#34; taggable_type&#34;,&#34; Photo&#34;],[&#34; tagger_id&#34;,1],[&#34; tagger_type&#34;,&#34 ;用户&#34;]]

(2.4ms)提交事务

2 个答案:

答案 0 :(得分:2)

我知道这个问题现在好五年了,但这仍然发生在带有acts-as-taggable 4.0的Rails 5.1中,我只是想表明如何解决这个问题。

这是一个非常简单的修复方法,在你的控制器强大的参数中你只需要添加tag_list: []而不是:tag_list,如下所示:

def photo_params
  params.require(:photo).permit(:title, tag_list: [])
end

这会阻止在数据库中创建重复和空白Taggings,您可以使用form_for而不是form_tag

<%= form_for @photo do |f| %>
  <%= f.text_field :title %>
  <%= f.text_field :tag_list %>
  <%= f.submit %>
<% end %>

答案 1 :(得分:1)

好的,这真的很奇怪,但我已经想出了如何避免这个问题。

我做的第一件事是创建一个尖峰解决方案来测试acts_as_taggable_on,这似乎有效。它由两个模型类组成,就是它......当我通过rails控制台进行测试时它就起作用了。

所以我添加了一个像我在rails应用程序中的表单并再次测试它......

我的表格是这样的:

   <div>
      <%= form_for @photo, :html => { :class => "dialog" } do |f| %>

      ...

      <%= f.label :title%>
      <%= f.text_field :title, :class => "wide" %>

      <%= f.label 'Tags' %>
      <%= f.text_field :tag_list, :value => @tags %>

      ...

      <%= f.submit button_text(@photo), :class => "btn btn-large btn-primary" %>
      <%= f.submit "Cancel", :class => "btn btn-large"  %>
   </div>

当我实现这个并测试它时,我得到了一个'无法批量分配:tag_list'

我读到了Rails 3.2.3中关于质量分配的变化,并决定不妥协安全性。

所以我添加到我的Photo模型类

 attr_accessible :tag_list

这解决了错误但是当我测试它时我发现现在出现的重复行!所以现在这个bug是可以重现的!!

我通过更改表单解决了这个问题,因此我没有将表单绑定到Photo模型对象。

像这样:

<div>
   <%= form_tag({:controller => "photos", :action => "create"}, :method => "post", :class => "dialog") do %>

   ...

   <%= label_tag :title, 'Title'%>
   <%= text_field_tag :title, nil, :class => "wide" %>

   <%= label_tag :tag_list, 'Tags'%>
   <%= text_field_tag :tag_list, nil, :class => "wide" %>

   ...

   <%= submit_tag('Add', :class => "btn btn-large btn-primary") %>
   <%= submit_tag("Cancel", :class => "btn btn-large")  %>
</div>

我还删除了attr_accessible:tag_list并修改了控制器以接受表单中的不同值。

@photo = current_user.photos.build(:title => params[:title],
                                   ...
                                   )
@user.tag(@photo, :with => params[:tag_list], :on => :tags)

这解决了这个问题!

我现在将试着确切了解为什么会发生这种情况! :)