2

我有一个 RoR 应用程序,允许用户标记他们收藏中的项目。我使用 tag-it.js Jquery 插件并使用 Ajax 调用来添加和删除 ItemsController 中的标签。我的问题是每个标签都添加了两次,因此当我执行@item.tags.each 时,所有标签都会显示两次。

物品控制器:

  def add_tag 
    @collection = current_user.collections.find(params[:collection_id])    
    @item = @collection.items.find(params[:id])
    @item.tag_list.add(params[:tag])   
    current_user.tag(@item, :with => @item.tag_list.to_s, :on => :tags)          
    @item.save   

    render nothing: true 
  end 

  def remove_tag 
    @item = current_user.items.find_by_id(params[:id])       
    @item.tag_list.remove(params[:tag]) 
    current_user.tag(@item, :with => @item.tag_list.to_s, :on => :tags)          
    @item.save 

    render nothing: true 
  end 

使用 Tag-it.js 处理 AJAX 标记的 Javascript:

$('#item_tags').tagit({
      onTagAdded: function(event, tag) {          
       var add_url = $('#item_tags').attr("data-add-url");              
        $.ajax({
          url: add_url,                      
          data: {tag: tag.text().substring(0, tag.text().length-1)},                                   
        })             
      }, 
      onTagRemoved: function(event, tag) {
        var remove_url = $('#item_tags').attr("data-remove-url"); 
        $.ajax({
          url: remove_url,  
          type: 'DELETE',                        
          data: {tag: tag.text().substring(0, tag.text().length-1)},                                  
        })
      },
      tagSource: function(search, showChoices) {
        var autocomplete_url = $('#item_tags').attr("data-auctocomplete-url");             
        $.ajax({
          url: autocomplete_url,        
          data: {term: search.term},                              
          success: function(choices) {
            showChoices(choices);
          }
        })           
      }
});

用户添加/删除标签的 item#_form 视图:

<ul id='item_tags' class='tagit' data-remove-url="<%= remove_tag_collection_item_path %>" data-add-url="<%= add_tag_collection_item_path %>" data-auctocomplete-url="/collections/<%=@collection.id %>/items/autocomplete_tag_name"> 
      <% @item.tags.each do |tag| %>   
        <li><%= tag.name %></li>            
      <% end %>                   
</ul>

我必须注意,有必要拥有标签所有权(由 current_user),以便 Jquery 自动完成仅基于当前用户的先前标签而不是所有用户完成。我认为问题在于我必须将标签添加到 tag_list 中,然后将 tag_list 添加到用户项目标记中。我找不到解决这个问题的方法,因为 current_user.tag() 方法似乎在调用 current_user.tag() 时覆盖了以前的项目标签,所以我必须将新标签添加到以前的标签以保留它们。

此外,当我提交 item#_form 时,我需要以某种方式让 update 方法忽略 tags 属性,因为它试图将它们保存到 item 但它们已经通过 AJAX 调用保存,所以我收到此错误:

ActiveRecord::AssociationTypeMismatch in ItemsController#update
ActsAsTaggableOn::Tag(#82082080) expected, got String(#72294010)

提前致谢。

PS。以下是我如何在 ItemsController 中自动完成工作:

def get_autocomplete_items(parameters)
    tags = current_user.owned_tags.named_like(parameters[:term])   
end
4

3 回答 3

0

你是对的:

我认为问题在于我必须将标签添加到 tag_list 中,然后将 tag_list 添加到用户项目标记中。我找不到解决这个问题的方法,因为 current_user.tag() 方法似乎在调用 current_user.tag() 时覆盖了以前的项目标签,所以我必须将新标签添加到以前的标签以保留它们。

.tag方法使用给定列表覆盖现有标签。因此,如果您想添加新标签,您似乎需要将新标签附加到现有标签,然后传入该新列表。但是,.tag_list.add实际上也会创建标签。

所以,当你这样做时:

  @item.tag_list.add(params[:tag])   
  current_user.tag(@item, :with => @item.tag_list.to_s, :on => :tags)          

您确实添加了两次新标签。

当我这样做时:

tag_list = profile.tag_list // oops!
tag_list.add(tags)
self.tag(profile, with: tag_list, on: :tags)

我正在创建对 tag_list 的引用,然后在其上调用 add。我们需要做的是:

tag_list = profile.tags.map(&:name)

为我们正在标记的对象创建一个标记名称数组。然后我们就可以在列表的副本上调用 add 了,没问题!不再有重复的标签。

我很高兴遇到您的问题,因为它使我得到了对我有用的答案。但是,如果图书馆提供了一种很好的方法,我会更加高兴。仅仅通过阅读文档,我无法找到一个好方法。

于 2014-01-24T11:54:38.053 回答
0

你做得很好,但是,只是一个小错误。

这里tag_list得到重复的标签,一个有所有者,另一个没有所有者

您的线路正在添加没有所有者@item.tag_list.add(params[:tag])的标签

并且行正在添加与所有者current_user.tag(@item, :with => @item.tag_list.to_s, :on => :tags)相同的标签

后来,当您保存对象时,由于tag_list其行为是对对象的未拥有标签的引用,因此两者都被保存

以下代码应该可以正常工作。

  def add_tag 
    @collection = current_user.collections.find(params[:collection_id])    
    @item = @collection.items.find(params[:id])
    tag_list = @item.all_tag_list.dup # Reference to original tag_list avoided
    # Also instead of "tag_list", use "all_tag_list" method, as "tag_list" only return tags without owner
    # Link(go to last line og Tag Ownership topic) : "https://github.com/mbleigh/acts-as-taggable-on#tag-ownership"
    tag_list.add(params[:tag])   
    current_user.tag(@item, :with => tag_list.to_s, :on => :tags)          
    @item.save   

    render nothing: true 
  end 

  def remove_tag 
    @item = current_user.items.find_by_id(params[:id])
    tag_list = @item.all_tag_list.dup # Reference to original tag_list avoided      
    tag_list.remove(params[:tag]) 
    current_user.tag(@item, :with => tag_list.to_s, :on => :tags)          
    @item.save 

    render nothing: true 
  end 

改良版

def add_owned_tag 
    @some_item = Item.find(params[:id])
    owned_tag_list = @some_item.all_tag_list - @some_item.tag_list
    owned_tag_list += [(params[:tag])]
    @tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
    @some_item.save   
end

def stringify(tag_list)
    tag_list.inject('') { |memo, tag| memo += (tag + ',') }[0..-1]
end

def remove_owned_tag 
    @some_item = Item.find(params[:id])
    owned_tag_list = @some_item.all_tag_list - @some_item.tag_list
    owned_tag_list -= [(params[:tag])]
    @tag_owner.tag(@some_item, :with => stringify(owned_tag_list), :on => :tags)
    @some_item.save   
end
于 2015-11-19T07:07:32.323 回答
-1

注意页面加载时触发的 onTagAdded 事件。在此处查看事件示例http://aehlke.github.com/tag-it/examples.html

//-------------------------------
// Tag events
//-------------------------------
var eventTags = $('#eventTags');
eventTags.tagit({
     availableTags: sampleTags,
     onTagRemoved: function(evt, tag) {
        console.log(evt);
        alert('This tag is being removed: ' + eventTags.tagit('tagLabel', tag));
    },
    onTagClicked: function(evt, tag) {
        console.log(tag);
        alert('This tag was clicked: ' + eventTags.tagit('tagLabel', tag));
    }
 }).tagit('option', 'onTagAdded', function(evt, tag) {
    // Add this callbackafter we initialize the widget,
    // so that onTagAdded doesn't get called on page load.
    alert('This tag is being added: ' + eventTags.tagit('tagLabel', tag));
 });
于 2012-07-01T22:46:42.847 回答