Update owner tags via form

前端 未结 7 1823
Happy的楠姐
Happy的楠姐 2020-12-18 01:26

I would like to uniquely use owner tags in my app. My problem is that when I create / update a post via a form I only have f.text_field :tag_list which only upd

相关标签:
7条回答
  • 2020-12-18 01:48

    The answer proposed by customersure (tsdbrown on SO) on https://github.com/mbleigh/acts-as-taggable-on/issues/111 works for me

    # 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 %>
    
    0 讨论(0)
  • 2020-12-18 01:52

    the set_tag_owner before_save worked for me. But as bcb mentioned, I had to add a condition (tag_list_changed?) to prevent the tags from being deleted on update:

    def set_tag_owner
      if tag_list_changed?
        set_owner_tag_list_on(account, :tags, tag_list)
        self.tag_list = nil
      end
    end
    
    0 讨论(0)
  • 2020-12-18 01:58

    I ended up creating a virtual attribute that runs the User.tag statement:

    In my thing.rb Model:

    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
    

    The only thing you have to do is then change your views and controllers to update the tag_list to tags and make sure you set the user_id of the thing before the tags of the thing.

    0 讨论(0)
  • 2020-12-18 02:04

    When working with ownership the taggable model gets its tags a little different. Without ownership it can get its tags like so:

    @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
    

    However, both of these opperations create taggins, whose tagger_id and tagger_type are nil.

    In order to have these fields set, you have to use this method:

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

    Suppose you add this line to the create/update actions of your PhotosController:

    @user.tag(@photo, on: :tags, with: params[:photo][:tag_list])
    

    This will create two taggings (one with and one without tagger_id/_type), because params[:photo][:tag_list] is already included in photo_params. So in order to avoid that, just do not whitelist :tag_list.

    For Rails 3 - remove :tag_list from attr_accessible.

    For Rails 4 - remove :tag_list from params.require(:photo).permit(:tag_list).

    At the end your create action might look like this:

    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
    

    Also note that when tagging objects this way you cannot use the usual tag_list method to retrieve the tags of a photo, because it searches for taggings, where tagger_id IS NULL. You have to use instead

    @photo.tags_from(@user)
    

    In case your taggable object belongs_to a single user you can also user all_tags_list.

    0 讨论(0)
  • 2020-12-18 02:05

    Late to the party, but I found guillaume06's solution worked well, and I added some additional functionality to it:

    What this will enable: You will be able to specify the tag owner by the name of the relationship between the tagged model and the tag owner model.

    How: write a module and include in your lib on initialization (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
    

    Usage Instructions:

      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)..
    
    0 讨论(0)
  • 2020-12-18 02:11

    Try using delegation:

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

    So when you save your posts it sets the tag on the user object directly.

    0 讨论(0)
提交回复
热议问题