2014-10-28 29 views
5

Czy istnieje sposób uniknięcia automatycznego zapisywania obiektu podczas przypisywania atrybutów kolekcji (metoda collection_singular_ids = ids)?Railsy 3 nie mogą wykonywać sprawdzania poprawności dla persytowanego obiektu podczas użycia metody collection_singular_ids = ids

Na przykład Mam następujący model Test i pakiet, pakiet ma wiele testów. Użytkownik może zbudować pakiet pakietów z liczbą testów.

No problem na walidację gdy obiekt jest nowy pakiet.

1.9.2 :001> package = Package.new(:name => "sample", :cost => 3.3, :test_ids => [1,2,3,4]) 
=> #<Package id: nil, name: "sample", cost: 3.3> 
1.9.2 :002> package.test_ids 
=> [1, 2, 3, 4] 
1.9.2 :003> package.save 
=> false 
1.9.2 :004> package.save! 
ActiveRecord::RecordInvalid: Validation failed: This package should have at most three tests 
1.9.2: 005> package.test_ids = [1,2] 
=> [1, 2] 
1.9.2 :005> package.save! 
=> true 

Ale nie mogłem trafić at_most_3_tests metodę z utrzymywały pakiet obiektu.

Dołącz rekord tabeli jest tworzony bezpośrednio przy przypisywaniu IDS testowych

1.9.2: 006> package 
=> #<Package id: 1, name: "sample", cost: 3.3> 
1.9.2: 007> package.test_ids 
=> [1,2] 
1.9.2: 007> package.test_ids = [1,2,3,4,5] 
=> [1,2,3,4,5] 
1.9.2: 008> package.test_ids 
=> [1,2,3,4,5] 

wymóg klient jest interfejs rozwijanej wyboru wielu testów w postaci pakietu a także wykorzystywane select2 jquery plugin do listy rozwijanej. Kod Rhmtl wygląda

<%= form_for @package do |f| %> 
    <%= f.text_field :name %> 
    <div> <label>Select Tests</label> </div> 
    <div> 
    <%= f.select "test_ids", options_for_select(@tests, f.object.test_ids), {}, { "data-validate" => true, :multiple => true} %> 
    </div> 

Proszę mi pomóc rozwiązać ten problem.

Odpowiedz

5

dla numeru granicznej stowarzyszenia

Można użyć następujących walidacji jako następujące zamiast metodę:

has_many :tests, :length => { :maximum => 3 } 

Do korzystania z wielu wybierz

mam ten problem wcześniej i rozwiązałem go, używając następującego kodu:

<%= f.select(:test_ids, options_from_collection_for_select(@tests, :id, :name, @promotion.test_ids), {}, {multiple: true, "data-validate" => true}) => 

Myślę, że options_from_collection_for_select, przeczytaj kategorie post przykład z tego link może ci pomóc.

walidacji

użyłem validates_associated, jak następuje:

validates_associated :tests 

Aby dostać stare atrybuty utrwalonej obiektu

Można użyć reload aktywnego rekordu jako następujące:

1.9.2: 006> package 
=> #<Package id: 1, name: "sample", cost: 3.3> 
1.9.2: 007> package.test_ids 
=> [1,2] 
1.9.2: 007> package.test_ids = [1,2,3,4,5] 
=> [1,2,3,4,5] 
1.9.2: 007> package.reload 
=> #<Package id: 1, name: "sample", cost: 3.3> 
1.9.2: 008> package.test_ids 
=> [1,2] 

Albo można sprawdzić poprawności obiektu pakietu, jeśli jest fałszywe przeładowanie go:

unless package.valid? 
    package.reload 
end 
+0

Nie mogę połączyć się z pakietem. ponieważ każdorazowe przypisanie tablicy identyfikatorów powoduje automatyczne zapisanie akcji. Na przykład package.test_ids = [1,2,3,4,5] –

+0

@ManivannanJeganathan Aktualizuję moją odpowiedź, aby użyć tej walidacji 'has_many: tests,: length => {: maximum => 3}' –

+0

Moja walidacja nie jest tylko na podstawie długości. Podałem tylko przykładowy kod. parametry [: pakiet] powinny zawsze mieć parametry test_ids, takie jak {: cost => 3.4,: test_ids => [1,2,3,4,5]}. Po prostu muszę zastosować metodę sprawdzania poprawności w modelu pakietu i formie renderowania, jeśli nie przejdzie sprawdzania poprawności. Potrafię użyć metody sprawdzania poprawności za pomocą odpowiedzi, nazywając '' 'validates_associated: package''' w modelu PackageTest. Ale jeśli sprawdzanie poprawności nie powiedzie się w związku z sprawdzaniem poprawności test_ids, zgłaszany wyjątek zamiast zwracania wartości true lub false. Kod ex "' 'if @ pakiet.update_attributes parametry [: pakiet] inny render" formularz "' '' –

3

Jeśli ręczne przypisanie test_ids w kontrolerze, polecam aktualizację całego obiektu z zagnieżdżonych atrybutów zamiast.Zakłada się, że params[:package][:test_ids] jest ustawiona na twoją listę identyfikatorów testowych (której odpowiedź Mohameda pomoże). Więc akcja kontroler będzie wyglądać mniej więcej tak:

def update 
    package = Package.find(params[:id]) 
    package.update_attributes params[:package] 
end 

ten zaktualizuje wszystko naraz w transakcji/bazy danych ActiveRecord. Oznacza to, że jeśli walidacja nie powiedzie się, wszystkie zmiany zostaną wycofane, więc nie ma znaczenia, że ​​testy zostały zapisane. Więcej informacji to here.

Polecam również dzwoniąc pod numer tests.size zamiast test_ids.count, ponieważ zamiennik będzie generował lepsze zapytanie (lub nie musi w ogóle korzystać z bazy danych).

+0

Fine.But problem z wywołaniem update_attributes z parametrem test_ids, spowoduje zgłoszenie wyjątku zamiast zwracania wartości true lub false, jeśli sprawdzanie poprawności nie powiedzie się w związku z sprawdzaniem poprawności test_ids (metoda at_most_3_tests). Jakieś sugestie? Przykładowy kod: if pakiet.update_attributes parametry [: pakiet] –

+0

Użyłem ** validates_associated: package ** w PackageTest model –

+0

validates_associated nie powinien domyślnie podnosić wyjątku. Jaki błąd dostałeś? – Ari