Обновить теги владельца через форму - PullRequest
7 голосов
/ 01 сентября 2010

Я бы хотел использовать уникальные теги владельца в своем приложении.Моя проблема в том, что когда я создаю / обновляю сообщение через форму, у меня есть только f.text_field :tag_list, который только обновляет теги для сообщения, но не имеет владельца.Если я использую f.text_field :all_tags_list, он не знает атрибут при создании / обновлении.Я мог бы добавить в свой контроллер:

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

, но тогда у меня есть дубликаты тегов, для поста и для тегов владельца.Как я могу просто работать с тегами владельца?

Ответы [ 7 ]

4 голосов
/ 01 июля 2011

Ответ, предложенный customerure (tsdbrown on SO) на https://github.com/mbleigh/acts-as-taggable-on/issues/111, работает для меня

# 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 %>
2 голосов
/ 13 сентября 2011

Я использовал наблюдателя, чтобы решить это.Что-то вроде:

в /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
1 голос
/ 29 июля 2014

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
1 голос
/ 09 июля 2013

Поздно на вечеринке, но я обнаружил, что решение guillaume06 работает хорошо, и я добавил к нему некоторые дополнительные функции:

Что это позволит: Вы сможете указать владельца тега по имени отношения между помеченной моделью и моделью владельца тега.

Как: написать модуль и включить его в свою библиотеку при инициализации (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)..
0 голосов
/ 29 июля 2015

При работе с владельцем модель taggable получает свои теги немного по-другому. Без права собственности он может получить свои теги так:

@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 действиям вашего PhotosController:

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

Это создаст две метки (одна с * 1018 и одна без 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.

0 голосов
/ 30 марта 2013

Я закончил тем, что создал виртуальный атрибут, который выполняет оператор 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 thing перед tags thing.

0 голосов
/ 01 февраля 2011

Попробуйте использовать делегирование:

class User < ActiveRecord::Base
  acts_as_taggable_on
end

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

Таким образом, когда вы сохраняете свои сообщения, он непосредственно устанавливает тег для объекта пользователя.

...