2010-09-01 5 views
7

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

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

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

+0

Я пытаюсь достичь того же. Вы с этим справились? – tsdbrown

+0

Я спросил об этом на github: http://github.com/mbleigh/acts-as-taggable-on/issues/issue/111/#issue/111 – tsdbrown

+1

Вы задумывались о наличии модели owner_tags, которая принадлежит Владелец и почта? Для этого потребуется немного больше работы, но тогда вы узнаете, кто владеет тегами, а также какой почтой они принадлежат. Вероятно, вам понадобится attr_accessor: tag_list, чтобы представления форм все еще работали, а затем выталкивали модель в модель owner_tags для создания/udpate. – Adam21e

ответ

0

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

class User < ActiveRecord::Base 
    acts_as_taggable_on 
end 

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

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

4

Ответ, предложенный customersure (tsdbrown на 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 %> 
+0

Это, похоже, не работает для меня в этом примере http://stackoverflow.com/questions/6933659/how-do-i-display-a-current-users-tags-tagged-with-acts-as- taggable-on – Simpleton

+2

Это отлично подойдет для меня. Однако обязательно поставьте условия на before_save, если только вы ДЕЙСТВИТЕЛЬНО не хотите, чтобы этот код выполнялся до КАЖДОГО сохранения (например, при сохранении вне формы). Например, если вы обновляете атрибут в другом месте вашего кода, и эти атрибуты не включают «tag_list», вы получите ожог (список тегов владельца будет установлен на нуль случайно). Я нашел это из первых рук :) – bcb

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 
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 в thing до tags в thing.

1

Late к партии, но я нашел решение 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).. 
1

set_tag_owner before_save работал для меня. Но, как упоминался БКБ, мне пришлось добавить условие (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 
+0

Пожалуйста, поделитесь своим кодом, я не нахожу, что это правильный ответ. – simeg

0

При работе с собственностью 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 

Однако оба этих opperations создать 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]) 

Это создаст два (один с одним и без tagger_id/_type), потому что params[:photo][:tag_list] уже включен в photo_params. Поэтому, чтобы этого избежать, просто не белите список :tag_list.

Для Rails 3 - удалить :tag_list из attr_accessible.

Для рельсов 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) 

В случае, если ваш taggable объект belongs_to одного пользователя вы можете также пользователь all_tags_list.

Смежные вопросы