5

ho un modello molto sempliceinput di form Admin personalizzati attivi per rapporto has_and_belongs_to_many

class Lifestyle < ActiveRecord::Base 
    attr_accessible :name 
    has_and_belongs_to_many :profiles 
end 

che ha una relazione has_and_belongs_to_many con Profile

class Profile < ActiveRecord::Base 
    attr_accessible ... 

    belongs_to :occupation 

    has_and_belongs_to_many :lifestyles 
    accepts_nested_attributes_for :lifestyles 
end 

voglio usare ActiveAdmin per modificare l'oggetto profilo, ma Assegna anche stili di vita a un profilo. Dovrebbe essere simile a quello relativo allo belongs_to :occupation, in quanto viene risolto automaticamente da ActiveAdmin in una casella personale con le opzioni pre-compilate con le occupazioni disponibili.

Ho provato a utilizzare il metodo di creazione modulo has_many, ma questo mi ha permesso solo di mostrare un modulo per digitare il nome dello stile di vita e al momento dell'invio, ha restituito un errore.

f.object.lifestyles.build 
    f.has_many :lifestyles do |l| 
     l.input :name 
    end 

errore che ottengo:

Can't mass-assign protected attributes: lifestyles_attributes 

Il modo perfetto per me sarebbe quello di costruire diverse caselle, uno per ogni stile di vita nel DB. Selezionato significa che lo stile di vita è collegato al profilo e mezzi non selezionati per eliminare la relazione.

Ho grandi dubbi sul fatto che sia possibile utilizzare ActiveAdmin e senza dover creare una logica molto complessa per gestire questo problema. Lo apprezzerei molto se esprimessi la tua opinione e mi consiglierei se dovessi andare in questo modo o affrontarlo in modo diverso.

risposta

18

Dopo alcune ricerche, sono pronto a rispondere alla mia stessa domanda.

In primo luogo, devo dire grazie a @Lichtamberg per aver suggerito la correzione. Tuttavia, questo complica solo le cose (anche per quanto riguarda la sicurezza, anche se non è un problema in questo caso), e non mi aiuta a raggiungere la mia soluzione ideale.

Scavando di più, ho scoperto che questo è uno scenario molto comune in Rails e in realtà è spiegato in Ryan Bates' screencast no #17.

Pertanto, in Rails, se si dispone di un has_and_belongs_to_many (breve HABTM form) associazione, è possibile impostare facilmente gli ID degli altri oggetto associato con questo metodo:

profile.lifestyle_ids = [1,2] 

E questo funziona ovviamente per forme se che hai impostato l'attr_accessible per lifestyle_ids:

class Profile < ActiveRecord::Base 
    attr_accessible :lifestyle_ids 
end 

in ActiveAdmin, perché utilizza Formtastic, è possibile utilizzare questo metodo per l'uscita campi corretti (in questo caso caselle):

f.input :lifestyles, as: :check_boxes, collection: Lifestyle.all 

Inoltre, ho semplificato mio punto di vista forma quindi è ora semplicemente questo:

form do |f| 
    f.inputs # Include the default inputs 
    f.inputs "Lifestlyes" do # Make a panel that holds inputs for lifestyles 
     f.input :lifestyles, as: :check_boxes, collection: Lifestyle.all # Use formtastic to output my collection of checkboxes 
    end 
    f.actions # Include the default actions 
    end 

Ok, ora questo rendeva perfettamente in vista, ma se cerco di inviare i miei cambiamenti, me questo dà errore di database:

PG::Error: ERROR: null value in column "created_at" violates not-null constraint 
: INSERT INTO "lifestyles_profiles" ("profile_id", "lifestyle_id") VALUES (2, 1) RETURNING "id" 

ho scoperto che questo è dovuto al fatto che Rails 3.2 non aggiorna automaticamente i timestamp per una tabella di associazione HABTM (perché sono attributi extra, e Rails gestisce solo il _id attributi.

ci sono 2 soluzioni per risolvere questo problema:

  1. convertirsi l'associazione in una HM: t (has_many, :through =>)
  2. o rimuovere i timestamp dalla tabella

Vado andare per 2) perché non avrò mai bisogno dei timestamp o degli attributi extra.

Spero che questo aiuti altre persone che hanno gli stessi problemi.

Modifica: @cdesrosiers era più vicino alla soluzione, ma ho già scritto questa risposta prima di leggere la sua. Comunque, questo è comunque fantastico. Sto imparando molto

+1

+1 per avere il tempo di rispondere alla tua stessa domanda in dettaglio. – cdesrosiers

+0

Interessante che non ho dovuto specificare manualmente la 'collection' (activeadmin 0.5.1, formtastic 2.2.1). Ottima risposta comunque! – asymmetric

0

Aggiungere

attr_accessible :lifestyles_attributes 

fe:

class AccountsController < ApplicationController 
    attr_accessible :first_name, :last_name 
end 
2

Admin attivo crea un sottile DSL (Lingua Domain-Specific) su Formtastic, quindi è meglio guardare al formastic doc quando si ha bisogno di personalizzazione modulo . Qui, scoprirai che potresti essere in grado di utilizzare f.input :lifestyles, :as => :check_boxes per modificare una relazione has_and_belongs_to_many.

Dico "potrebbe" perché non ho provato io stesso questo helper per il tuo caso particolare, ma queste cose hanno la tendenza a lavorare solo automagicamente, quindi provalo.

Inoltre, probabilmente non sarà necessario accepts_nested_attributes_for :lifestyles a meno che non si vuole realmente modificare gli attributi di lifestyles da profiles, che non credo che è particolarmente utile quando si utilizza di amministrazione attiva (solo modificare lifestyles direttamente).

+0

Bella, ottima risposta. Stavo solo scrivendo la mia risposta e non l'ho visto. Alla fine l'ho capito, e lo screencast di Ryan Bates mi ha aiutato a imparare le cose di cui stai parlando qui. Sapevo che c'era un modo più intelligente in Rails :) – Cristian