2009-08-13 12 views
6

Mam modelu konta i modelu użytkownika:walidacji max ilość af związane obiekty

class Account < ActiveRecord::Base 
    has_many :users 
end 

class User < ActiveRecord::Base 
    belongs_to :account 
end

użytkownicy należą do konta i konta mają maksymalną użytkownika (inny dla każdego rachunku). Ale w jaki sposób mogę sprawdzić, czy to maksimum nie zostało osiągnięte podczas dodawania nowych użytkowników do konta?

Najpierw próbowałem dodać walidację na użytkownika:

class User < ActiveRecord::Base 
    belongs_to :account 
    validate :validate_max_users_have_not_been_reached 

    def validate_max_users_have_not_been_reached 
    return unless account_id_changed? # nothing to validate 
    errors.add_to_base("can not be added to this account since its user maximum have been reached") unless account.users.count < account.maximum_amount_of_users 
    end 
end

Ale to działa tylko jeśli Dodaję jednego użytkownika jednocześnie.

Jeśli dodaję wielu użytkowników za pomocą @account.update_attributes(:users_attributes => ...), po prostu przejdzie bezpośrednio, nawet jeśli jest tylko miejsce dla jeszcze jednego użytkownika.

Aktualizacja:

prostu do wyjaśnienia: Obecna metoda sprawdzania poprawności sprawdza, czy account.users.count jest mniejsza niż account.maximum_amount_of_users. Tak mówią na przykład, że account.users.count jest 9 i account.maximum_amount_of_users wynosi 10, a następnie sprawdzanie poprawności przejdzie bo 9 < 10.

Problemem jest to, że hrabia wrócił z account.users.count nie wzrośnie aż wszyscy użytkownicy zostały zapisane do bazy danych. Oznacza to, że dodawanie wielu użytkowników w tym samym czasie przejdzie sprawdzanie poprawności, ponieważ liczba użytkowników będzie taka sama aż do momentu, gdy wszyscy zostaną sprawdzeni.

W związku z tym, że askegg zwraca uwagę, czy powinienem dodać również weryfikację do modelu konta? A jak to zrobić?

Odpowiedz

16

Jeśli zadzwonisz pod numer account.users.size zamiast account.users.count, będą to również użytkownicy, którzy zostali wbudowani, ale nie zapisani w bazie danych.

JEDNAK to nie rozwiąże w pełni twojego problemu. Kiedy zadzwonisz pod numer account, użytkownik nie zwraca tego samego wystąpienia na koncie, które wskazuje @account, więc nie wie o nowych użytkownikach. Wierzę, że zostanie to "naprawione" w Rails 3, ale w międzyczasie mogę wymyślić kilka rozwiązań.

Jeśli zapisujesz konto w tym samym czasie, gdy dodajesz użytkowników (co przypuszczam, że tak, ponieważ dzwonisz pod numer update_attributes), można tam przejść do sprawdzania poprawności.

# in account.rb 
def validate_max_users_have_not_been_reached 
    errors.add_to_base("You cannot have more than #{maximum_amount_of_users} users on this account.") unless users.size < maximum_amount_of_users 
end 

Nie jestem pewien, w jaki sposób zapisywania przynależne modeli, ale jeśli nie walidacja konto nie powinny one być zapisane.

Drugim rozwiązaniem jest zresetowanie instancji user.account na siebie podczas aktualizowania atrybutów użytkownika. Możesz to zrobić w metodzie ustawiającej users_attributes.

# in account.rb 
def users_attributes=(attributes) 
    #... 
    user.account = self 
    #... 
end 

ten sposób konto użytkownika będzie wskazywać na tej samej instancji konta tak account.users.size powinien zwrócić kwotę. W takim przypadku zachowasz walidacje w modelu użytkownika.

To trudny problem, ale mam nadzieję, że dało to kilka pomysłów, jak go rozwiązać.

-2

Powodem tego jest to, że update_attributes nie przechodzi przez sprawdzanie poprawności.

Również - Twoja logika sprawdza tylko istniejącą liczbę kont w stosunku do ich maksymalnych dozwolonych. Nie ma obliczeń biorąc pod uwagę liczbę użytkowników, którzy próbują zostać dodani. Myślę, że ta logika należy bardziej do modelu konta (?).

+0

update_attributes uruchamia sprawdzanie poprawności - przynajmniej w Railsach 2.3.2. Ale problem polega na tym, że metoda sprawdzania poprawności w modelu użytkownika sprawdza, czy nie osiągnięto maksimum w porównaniu do liczby użytkowników, którzy już są na koncie. To znaczy. jeśli max == 10 i users.count == 9, to - podczas dodawania dwóch użytkowników w tym samym czasie - sprawdzanie poprawności jest wykonywane dla obu, ale za każdym razem sprawdzanie, czy 9 ​​<10. Ponieważ users.count nie zwiększy się przed użytkownicy są zapisywani w bazie danych. Ale jak można to potwierdzić na modelu konta? Czy powinienem zastąpić update_attributes itd.? –

+1

Ahh - przepraszam. Update_attribute (zanotuj brakujące "s" na końcu) pomija sprawdzanie poprawności. Mój błąd. Wygląda na to, że Ryan (który ma o wiele więcej Rubyfoo niż ja) odpowiedział na twoje pytanie. Nie wiedziałem, że metoda "rozmiaru" obejmuje niezapisane rekordy. Każdego dnia uczysz się czegoś :) – askegg