我想在我的应用中唯一使用所有者标签。我的问题是,当我通过表单创建/更新帖子时,我只有f.text_field :tag_list
,它只更新帖子的标签,但没有所有者。如果我使用f.text_field :all_tags_list
,则它不知道创建/更新的属性。我可以添加我的控制器:
User.find(:first).tag( @post, :with => params[:post][:tag_list], :on => :tags )
但是我有重复的标签,用于帖子和所有者标签。如何使用所有者标记?
答案 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_id
和tagger_type
为nil
。
为了设置这些字段,您必须使用此方法:
@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
。