2012-12-03 14 views
6

Sto cercando un modo per modificare/aggiungere parole chiave correlate a un articolo, in linea in Activeadmin.Modifica relazioni molti a molti in Activeadmin

Ho definito un semplice molti-a-molti setup:

class Area < ActiveRecord::Base 
    has_many :area_keywords 
    has_many :keywords, :through => :area_keywords 
    accepts_nested_attributes_for :keywords, :reject_if => :all_blank, :allow_destroy => true 
end 

class AreaKeyword < ActiveRecord::Base 
    belongs_to :area 
    belongs_to :keyword 
end 

class Keyword < ActiveRecord::Base 
    has_many :area_keywords 
    has_many :areas, :through => :area_keywords 
end 

vorrei aggiungere e modificare le parole chiave in forma en zona, quindi ha installato questo Aciveadmin:

ActiveAdmin.register Area do 
    form do |f| 
    f.inputs "Area details" do 
     f.input :title 
     f.input :description 
    end 
    f.has_many :keywords do |k| 
     if k.object.nil? 
     k.input :word, :label => 'Keyword' 
     else 
     k.input :word, :label => k.object.word 
     k.input :_destroy, :as => :boolean, :label => "delete" 
     end 
    end 
    end 
end 

Funziona come previsto.

Ma se aggiungo la stessa parola chiave a due aree diverse, la parola chiave verrà creata due volte.

Quando si inserisce una nuova parola chiave (nel modulo Area), vorrei creare automaticamente una relazione con una parola chiave esistente o creare una nuova parola chiave, se non esiste. Quale sarebbe il modo migliore per farlo?

risposta

4

Questa è una risposta piuttosto tarda :) ma in realtà ho riscontrato un problema simile in uno dei miei progetti ... Ho dovuto aggiungere parole chiave/tag a due modelli diversi, ma potevano condividerli. All'inizio facevo proprio come te, e stavo creando un record ogni volta che "aggiungi" una parola chiave/tag ad un modello.

Un modo migliore per gestirlo è utilizzare un sistema di codifica. E ho realizzato un sistema piuttosto pulito dalla combinazione di due veramente buoni gemme: 'atti-come-oggetto di tag-on' (https://github.com/mbleigh/acts-as-taggable-on) e 'Select2-rails' (https://github.com/argerim/select2-rails)

Nel mio progetto, io in realtà ha fatto qualcosa di simile a te e ha creato un modello solo per avere un elenco di tutte le parole chiave appropriate che volevo. Ma 'act-as-taggable-on' non richiede necessariamente un elenco di parole chiave accettate ... quindi puoi crearle al volo e gestirà automaticamente duplicati, conteggi ecc.

'select2-rails 'consente solo di avere una bella interfaccia per aggiungere e rimuovere le parole chiave in un campo, invece di utilizzare le caselle di controllo, selezionare opzioni o un input di testo in cui si dovrebbe separare manualmente la stringa con virgole o eventuali separatori.

Se qualcuno ha bisogno di maggiori dettagli su come ho implementato tutto, sarei più che felice di fornire più codice .. ma la documentazione per entrambi è abbastanza semplice!

EDIT: Beh, ho una sensazione un po 'di codice sarebbe effettivamente essere utile :)

bundle install sia gioiello nella tua Gemfile

gem 'acts-as-taggable-on' 
gem 'select2-rails' 

nel modello Area, si potrebbe aggiungere quanto segue e fare qualcosa come

class Area < ActiveRecord::Base 
    # .. your code 

    attr_accessible :area_keyword_list 

    acts_as_taggable_on :area_keywords 
end 

E nel file ActiveAdmin

ActiveAdmin.register Area do 

    form do |f| 
     f.inputs do 
     # .. whatever fields you have 
     f.input :area_keyword_list, 
      :as => :select, 
      :multiple => :true, 
      :collection => # here either a list of accepted keyword..or just left open, 
      :input_html => { :class => "multiple-select" } 
     end 
    end 
end 

e JS per select2 è abbastanza semplice ...

$(".multiple-select").select2(); 

Voilà!

+0

Soluzione molto bella.Grazie per la condivisione! Ho usato entrambe le gemme dopo aver postato questa domanda, ma ha senso usarle insieme in questo modo. –

+0

buona soluzione, ma voglio che alcune opzioni di default dovrebbero essere selezionate. Diciamo che durante l'aggiornamento voglio che i miei attuali figli debbano essere selezionati di default. Come posso farlo con select2. –

+0

l'ho fatto con: selected => IDS –