通过表单更新所有者标签

时间:2010-09-01 14:52:32

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

我想在我的应用中唯一使用所有者标签。我的问题是,当我通过表单创建/更新帖子时,我只有f.text_field :tag_list,它只更新帖子的标签,但没有所有者。如果我使用f.text_field :all_tags_list,则它不知道创建/更新的属性。我可以添加我的控制器:

User.find(:first).tag( @post, :with => params[:post][:tag_list], :on => :tags )

但是我有重复的标签,用于帖子和所有者标签。如何使用所有者标记?

7 个答案:

答案 0 :(得分:4)

https://github.com/mbleigh/acts-as-taggable-on/issues/111上的customerure(tsdbrown on SO)提出的答案对我有用

# In a taggable model:
before_save :set_tag_owner
def set_tag_owner
    # Set the owner of some tags based on the current tag_list
    set_owner_tag_list_on(account, :tags, self.tag_list)
    # Clear the list so we don't get duplicate taggings
    self.tag_list = nil
 end

# In the view:
<%= f.text_field :tag_list, :value => @obj.all_tags_list %>

答案 1 :(得分:2)

我用一个观察者来解决这个问题。类似的东西:

在/app/models/tagging_observer.rb

class TaggingObserver < ActiveRecord::Observer
  observe ActsAsTaggableOn::Tagging

  def before_save(tagging)
    tagging.tagger = tagging.taggable.user if (tagging.taggable.respond_to?(:user) and tagging.tagger != tagging.taggable.user)
  end
end

不要忘记在application.rb

中声明您的观察者
config.active_record.observers = :tagging_observer

答案 2 :(得分:1)

晚会,但我发现guillaume06的解决方案运行良好,我添加了一些额外的功能:

这将启用:您将能够通过标记模型与标记所有者模型之间的关系名称指定标记所有者。

如何:编写一个模块并在lib中包含初始化(require 'lib/path/to/tagger'):

  module Giga::Tagger
    extend ActiveSupport::Concern
    included do
      def self.tagger owner
        before_save :set_tag_owner
        def set_tag_owner
          self.tag_types.each do |tag|
            tag_type = tag.to_s
            # Set the owner of some tags based on the current tag_list
            set_owner_tag_list_on(owner, :"#{tag_type}", self.send(:"#{tag_type.chop}_list"))
            # Clear the list so we don't get duplicate taggings
            self.send(:"#{tag_type.chop}_list=",nil)
          end
        end

      end
    end
  end

使用说明:

  Given: A model, Post, that is taggable
         A model, User, that is the tag owner
         A post is owned by the user through a relationship called :owner
  Then add to Post.rb:
         include Tagger
         acts_as_taggable_on :skills, :interests, :tags
         tagger :owner
  Make sure Post.rb already has called acts_as_taggable_on, and that User.rb has acts_as_tagger
  Note: This supports multiple tag contexts, not just tags (eg skills, interests)..

答案 3 :(得分:1)

set_tag_owner before_save为我工作。但正如bcb所提到的,我必须添加一个条件(tag_list_changed?)以防止标记在更新时被删除:

def set_tag_owner
  if tag_list_changed?
    set_owner_tag_list_on(account, :tags, tag_list)
    self.tag_list = nil
  end
end

答案 4 :(得分:0)

尝试使用委托:

class User < ActiveRecord::Base
  acts_as_taggable_on
end

class Post < ActiveRecord::Base
  delegate :tag_list, :tag_list=, :to => :user
end

因此,当您保存帖子时,它会直接在用户对象上设置标记。

答案 5 :(得分:0)

我最终创建了一个运行User.tag语句的虚拟属性:

在我的thing.rb模型中:

attr_accessible :tags
belongs_to :user
acts_as_taggable

def tags
    self.all_tags_list
end

def tags=(tags)
    user = User.find(self.user_id)
    user.tag(self, :with => tags, :on => :tags, :skip_save => true)
end

您唯一需要做的就是更改视图和控制器以将tag_list更新为tags,并确保先设置user_id的{​​{1}} thing的{​​{1}}。

答案 6 :(得分:0)

使用所有权时,可标记模型会使其标记略有不同。如果没有所有权,它可以像这样得到它的标签:

@photo.tag_list << 'a tag' # adds a tag to the existing list
@photo.tag_list = 'a tag' # sets 'a tag' to be the tag of the @post

但是,这两个操作都会创建taggins,其tagger_idtagger_typenil

为了设置这些字段,您必须使用此方法:

@user.tag(@photo, on: :tags, with: 'a tag')

假设您将此行添加到create/update的{​​{1}}操作中:

PhotosController

这将创建两个标记(一个带有@user.tag(@photo, on: :tags, with: params[:photo][:tag_list]) ,一个没有tagger_id/_type),因为params[:photo][:tag_list]中已包含photo_params。因此,为了避免这种情况,请不要将:tag_list列入白名单。

对于Rails 3 - 从:tag_list移除attr_accessible

对于Rails 4 - 从:tag_list移除params.require(:photo).permit(:tag_list)

最后,您的create操作可能如下所示:

def create
  @photo = Photo.new(photo_params) # at this point @photo will not have any tags, because :tag_list is not whitelisted
  current_user.tag(@photo, on: :tags, with: params[:photo][:tag_list])

  if @photo.save
    redirect_to @photo
  else
    render :new
  end
end

另请注意,以这种方式标记对象时,您无法使用通常的tag_list方法来检索照片的标记,因为它会搜索taggings,其中tagger_id IS NULL。你必须使用

@photo.tags_from(@user)

如果您的可标记对象belongs_to是单个用户,您也可以使用all_tags_list