2010-09-01 13 views
7

Desidero utilizzare in modo univoco i tag proprietario nella mia app. Il mio problema è che quando creo/aggiorno un post tramite un modulo ho solo f.text_field :tag_list che aggiorna solo i tag per il post ma non ha alcun proprietario. Se utilizzo f.text_field :all_tags_list, non conosco l'attributo su create/update. Potrei aggiungere nel mio controller:Aggiorna tag proprietario tramite il modulo

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

ma poi ho tag duplicati, per post e per i tag del proprietario. Come posso lavorare con i tag del proprietario?

+0

Sto cercando di ottenere la stessa cosa. Sei arrivato da qualche parte con questo? – tsdbrown

+0

Ho chiesto informazioni su questo su github: http://github.com/mbleigh/acts-as-taggable-on/issues/issue/111/#issue/111 – tsdbrown

+1

Hai mai pensato di avere un modello owner_tags che appartiene a Proprietario e posta? Richiederebbe un po 'più di legwork, ma poi saprai a chi appartengono i tag e in quale post appartengono. Probabilmente dovresti avere attr_accessor: tag_list in modo che le viste del modulo funzionino ancora e poi ottenere il modello per dividerle nel modello owner_tags su create/udpate. – Adam21e

risposta

0

Provare a utilizzare la delega:

class User < ActiveRecord::Base 
    acts_as_taggable_on 
end 

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

Quindi, quando si salva i tuoi messaggi imposta il tag sul direttamente l'oggetto utente.

4

La risposta proposta da customersure (tsdbrown su SO) su https://github.com/mbleigh/acts-as-taggable-on/issues/111 opere per 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

Questo non sembra funzionare per me in questo esempio http://stackoverflow.com/questions/6933659/how-do-i-display-a-current-users-tags-tagged-with-acts-as- taggable-on – Simpleton

+2

Questo ha funzionato alla grande per me. Tuttavia, assicurati di mettere le condizioni su before_save a meno che tu non voglia VERAMENTE che questo codice venga eseguito prima di OGNI salvataggio (ad esempio, salva al di fuori del modulo). Ad esempio se aggiorni un attributo altrove nel tuo codice e quegli attributi non includono "tag_list", verrai bruciato (l'elenco dei tag del proprietario verrà impostato su zero per errore). Ho trovato questo fuori prima mano :) – bcb

2

ho usato un osservatore per risolvere questo. Qualcosa di simile:

in /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 

Non dimenticare di dichiarare il vostro osservatore application.rb

config.active_record.observers = :tagging_observer 
0

ho finito per creare un attributo virtuale che corre il User.tag dichiarazione:

Nel mio thing.rb Modello:

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 

L'unica cosa che dovete fare è quindi cambiare le vostre opinioni e controller per aggiornare il tag_list a tags e assicurarsi di impostare la user_id del thing prima della tags del thing.

1

in ritardo alla festa, ma ho trovato la soluzione di guillaume06 ha funzionato bene, e ho aggiunto alcune funzionalità aggiuntive ad esso:

Ciò permetterà: Sarete in grado di specificare il proprietario etichetta con il nome del rapporto tra il modello con tag e il modello proprietario del tag.

Come: scrivere un modulo e includere nel vostro lib su inizializzazione (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 

Istruzioni d'uso:

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

il before_save set_tag_owner lavorato per me. Ma, come accennato BCB, ho dovuto aggiungere una condizione (tag_list_changed?) Per evitare che i tag vengano eliminati aggiornata:

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

Si prega di condividere il codice, non trovo che questa sia una risposta valida. – simeg

0

Quando si lavora con la proprietà il modello oggetto di tag ottiene i relativi tag un po 'diverso.Senza la proprietà si può ottenere i propri tag in questo modo:

@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 

Tuttavia, entrambi questi opperations creano taggins, la cui tagger_id e tagger_type sono nil.

Per avere questi campi impostati, è necessario utilizzare questo metodo:

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

Supponiamo si aggiunge questa linea ai create/update azioni del vostro PhotosController:

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

Questo creerà due taggings (uno con e uno senza tagger_id/_type), perché params[:photo][:tag_list] è già incluso in photo_params. Quindi, per evitare ciò, non aggiungere la whitelist allo :tag_list.

Per Rails 3 - rimuovere :tag_list da attr_accessible.

Per Rails 4 - rimuovere :tag_list da params.require(:photo).permit(:tag_list).

Alla fine la vostra azione create potrebbe assomigliare a questo:

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 

Si noti inoltre che quando la codifica degli oggetti in questo modo non è possibile utilizzare il solito metodo tag_list per recuperare i tag di una foto, perché cerca di taggings , dove tagger_id IS NULL. Devi usare invece

@photo.tags_from(@user) 

Nel caso in cui l'oggetto oggetto di tag belongs_to un singolo utente è anche possibile utente all_tags_list.

Problemi correlati