2

私は、ユーザーがコレクション内のアイテムにタグを付けることができるRoRアプリを持っています。tag-it.js Jqueryプラグインを使用し、Ajax呼び出しを使用してItemsControllerのタグを追加および削除します。私の問題は、各タグが2回追加されるため、@ item.tags.eachを実行すると、すべてのタグが2回表示されることです。

ItemsController:

  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>

Jqueryのオートコンプリートがすべてのユーザーではなく現在のユーザーの以前のタグに基づいてのみ完了するように、(current_userによる)タグの所有権が必要であることに注意する必要があります。問題は、タグをtag_listに追加してから、tag_listをユーザーアイテムのタグ付けに追加する必要があることだと思います。current_user.tag()が呼び出されたときにcurrent_user.tag()メソッドが前のアイテムタグを上書きしているように見えるため、これを回避する方法を見つけることができません。そのため、前のタグに新しいタグを追加して保存する必要があります。

さらに、item#_formを送信するとき、更新メソッドがタグ属性を無視するようにする必要があります。これは、タグをアイテムに保存しようとしているのに、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)          

確かに、新しいタグを 2 回追加していました。

そして、私がこれをしていたとき:

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 に答える
-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 に答える