2011-08-18 9 views
6

Jeśli mam modelu ActiveRecord następującoRuby ocena klasy, validates_inclusion_of z dynamicznymi danymi

class Foo < ActiveRecord::Base 
    validates_inclusion_of :value, :in => self.allowed_types 

    def self.allowed_types 
    # some code that returns an enumerable 
    end 
end 

to nie działa, ponieważ metoda allowed_types nie zostało zdefiniowane w momencie, w którym walidacja jest uwzględniany. Wszystkie poprawki, o których myślę, że w zasadzie wszystkie dotyczą obracania definicji metody powyżej sprawdzania poprawności, tak aby była dostępna w razie potrzeby.

Rozumiem, że może to być raczej pytanie o styl kodowania niż cokolwiek (chcę, aby wszystkie moje walidacje znajdowały się u góry modelu i metod na dole), ale uważam, że powinno to być jakieś rozwiązanie tego problemu, prawdopodobnie z leniwą oceną początkowego obciążenia modelu?

jest tym, co chcę zrobić, nawet jeśli jest to możliwe? Czy powinienem właśnie definiować metodę powyżej sprawdzania poprawności lub czy istnieje lepsze rozwiązanie sprawdzania poprawności w celu osiągnięcia tego, czego chcę.

+0

@eightbitraptor ... spróbuj ': w => Foo.allowed_types' zamiast': w => self.allowed_types' ... beacause myślę 'self' będzie odwołanie do obiektu 'Foo' zamiast' Foo' – rubyprince

Odpowiedz

10

Powinieneś być w stanie użyć składni lambda do tego celu. Może tak:

class Foo < ActiveRecord::Base 
    validates_inclusion_of :value, :in => lambda { |foo| foo.allowed_types } 

    def allowed_types 
    # some code that returns an enumerable 
    end 
end 

ten sposób będzie oceniać blok lambda na każdym walidacji i przekazać instancję Foo do bloku. Następnie zwróci wartość z dozwolonych_typów w tej instancji, aby można było ją dynamicznie sprawdzać.

Należy również zauważyć, że usunąłem self. z deklaracji metody allowed_types, ponieważ utworzyłoby to metodę klasy zamiast metody instancji, która jest właśnie tutaj.

+0

Dziękuję, to było dokładnie to, co próbowałem z tym zrobić, po prostu nie zdawałem sobie sprawy, że przekazanie obiektu do lambda sprawi, że obiekt zostanie zatwierdzony. – eightbitraptor

+0

Chciałbym móc głosować dwa razy. – patrickmcgraw

+1

Możesz użyć ': in => lambda (&: allowed_types) dla jeszcze bardziej zwartej składni. – radiospiel

0

Opcja: w metodzie validates_inclusion_of wydaje się nie akceptować lambda lub Proc. Oto inne podejście:

validates_each :product_id do |record, attrib, value| 
    begin 
    Product.find(value) 
    rescue ActiveRecord::ActiveRecordError 
    record.errors.add attrib, 'must be selected from list.' 
    end 
end 
Powiązane problemy