5

Mam bardzo prosty modelklienta czynne Admin wejścia do formy relacji has_and_belongs_to_many

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

który ma has_and_belongs_to_many relacji z Profile

class Profile < ActiveRecord::Base 
    attr_accessible ... 

    belongs_to :occupation 

    has_and_belongs_to_many :lifestyles 
    accepts_nested_attributes_for :lifestyles 
end 

chcę użyć ActiveAdmin edytować obiekt profilu, ale przypisz także Lifestyles do profilu. Powinien być podobny do obsługi belongs_to :occupation, ponieważ jest on automatycznie sortowany przez ActiveAdmin do skrzynki z opcjami wstępnie wypełnionymi dostępnymi zajęciami.

Próbowałem użyć metody budowania formularzy has_many, ale to tylko pokazało mi formularz do wpisania nazwy stylu życia i po złożeniu, zwróciło błąd.

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

Błąd pojawia się:

Can't mass-assign protected attributes: lifestyles_attributes 

To doskonały sposób dla mnie byłoby zbudować kilka pól wyboru, jeden dla każdego stylu życia w DB. Wybrany oznacza, że ​​styl życia jest powiązany z profilem, a niewybrany oznacza usunięcie relacji.

Mam wielkie wątpliwości, czy jest to możliwe przy użyciu ActiveAdmin i bez konieczności tworzenia bardzo złożonej logiki, aby sobie z tym poradzić. Byłbym bardzo wdzięczny, gdybyś wyraził swoją opinię i doradził mi, czy powinienem pójść tą drogą, czy inaczej podchodzić do niej inaczej.

Odpowiedz

18

Po przeprowadzeniu badań jestem gotowy odpowiedzieć na własne pytanie.

Po pierwsze, muszę podziękować @ Lichtamberg za sugerowanie poprawki. Jednak to tylko komplikuje sprawy (także pod względem bezpieczeństwa, ale nie stanowi problemu w tym przypadku) i nie pomaga mi w znalezieniu idealnego rozwiązania.

Kopiąc więcej, dowiedziałem się, że jest to bardzo często spotykany scenariusz w Railsach, a jest to wyjaśnione w Ryan Bates' screencast no #17.

Dlatego w Rails, jeśli masz has_and_belongs_to_many (krótka forma HABTM) stowarzyszenie, można łatwo ustawić identyfikatory drugiej związanego obiektu dzięki tej metodzie:

profile.lifestyle_ids = [1,2] 

I to oczywiście działa na formularzach, jeżeli Spróbuj ustawić attr_accessible dla lifestyle_ids:

class Profile < ActiveRecord::Base 
    attr_accessible :lifestyle_ids 
end 

w ActiveAdmin, ponieważ używa Formtastic, można użyć tej metody do produkcji odpowiednich polach (w tym przypadku wyboru):

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

Również mam uproszczona moja forma widok tak to teraz tylko to:

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, teraz to doskonale renderowane w widoku, ale gdy próbuję i przedstawić moje zmiany, daje mi to błąd bazy danych:

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" 

i okazało się, że jest to spowodowane faktem, że Railsy 3.2 nie jest automatycznie aktualizować sygnatury czasowe dla tabeli stowarzyszenia HABTM (bo są dodatkowe atrybuty, a Rails obsługuje tylko _id atrybutów.

Są 2 rozwiązania, aby to naprawić:

  1. Albo przekonwertować stowarzyszenie do HM: T (has_many, :through =>)
  2. lub usunąć znaczniki czasu z tabeli

jadę aby przejść na 2), ponieważ nigdy nie będę potrzebował znaczników czasu ani żadnych dodatkowych atrybutów.

Mam nadzieję, że pomoże to innym osobom mającym te same problemy.

Edycja: @cdesrosiers był najbliżej rozwiązania, ale już napisałem tę odpowiedź, zanim przeczytałem jego. W każdym razie jest to świetne. Dużo się uczę.

+1

+1 za poświęcenie czasu, aby szczegółowo odpowiedzieć na własne pytanie. – cdesrosiers

+0

Interesujące, że nie musiałem ręcznie określać 'kolekcji' (activeadmin 0.5.1, formtastic 2.2.1). Świetna odpowiedź i tak! – asymmetric

0

Dodaj

attr_accessible :lifestyles_attributes 

fe:

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

Aktywny Administrator tworzy cienką DSL (Domain-Specific Language) nad formtastic, więc najlepiej spojrzeć na formastic doc kiedy trzeba formularz dostosowywania . Znajdziesz tam, że możesz zmodyfikować relację f.input :lifestyles, :as => :check_boxes.

Mówię "może", ponieważ sam nie próbowałem tego pomocnika w konkretnym przypadku, ale te rzeczy mają tendencję do pracy po prostu automagicznie, więc wypróbuj to.

Ponadto, prawdopodobnie nie będzie musiał accepts_nested_attributes_for :lifestyles chyba rzeczywiście chcesz zmodyfikować atrybuty lifestyles z profiles, która nie sądzę, jest szczególnie przydatna w przypadku użycia substancji administratora (tylko zmodyfikować lifestyles bezpośrednio).

+0

Dobra, bardzo dobra odpowiedź. Właśnie pisałem własną odpowiedź i nie widziałem tego. W końcu to rozgryzłem, a screencast Ryana Batesa pomógł mi nauczyć się tego, o czym tu mówisz. Wiedziałem, że w Railsach jest mądrzejszy sposób: – Cristian

Powiązane problemy