Jak sprawdzić, czy model ma określoną kolumnę / atrybut?

123

Mam metodę, która musi przechodzić przez skrót i sprawdzić, czy każdy klucz istnieje w tabeli modeli, w przeciwnym razie usunie klucz / wartość.

na przykład

number_hash = { :one => "one", :two => "two" }

a tabela Number ma tylko: jedną kolumnę, więc: dwie zostaną usunięte.

Jak sprawdzić, czy model ma atrybut, czy nie?

dMix
źródło

Odpowiedzi:

205

Na zajęcia

Użyj Class.column_names.include? attr_namegdzie attr_namejest nazwą ciągu Twojego atrybutu.

W tym przypadku: Number.column_names.include? 'one'

Na przykład

Użyj record.has_attribute?(:attr_name)lub record.has_attribute?('attr_name')(Rails 3.2+) lub record.attributes.has_key? attr_name.

W tym przypadku: number.has_attribute?(:one)lub number.has_attribute?('one')lubnumber.attributes.has_key? 'one'

Andy Stewart
źródło
Aby Hash#selectnumber_hash.select { |key, value| Number.column_names.include? key }
otrzymać
28
W Railsach 3.2+, użyj, number.has_attribute?który akceptuje symbol lub ciąg
Marc-André Lafortune
Uważam, że jeśli obiekt deleguje metodę do innego obiektu, ta metoda błędnie zasugeruje istnienie kolumny. Sprawdzałem swoje modele pod kątem tych, które miały user, ale zamiast tego musiałem szukać, user_idponieważ niektóre modele delegowały użytkownika.
MattyB
Hash#has_key?jest przestarzały na korzyśćHash#key?
Charles Hamel
Co powiesz na użycie atrybutu_metoda? dla klasy:Number.attribute_method? 'one'
ouranos
13

Jeśli chcesz również sprawdzić aliasy, możesz użyć Number.method_defined? attr_namelub number.class.method_defined? attr_name.

Musiałem to zrobić dla obiektu Mongoid, który miał aliasy pól.

Nacięcie
źródło
Znalazłem ModelName.attribute_method? :attr_nameto, co zadziałało w moim przypadku
pewnym kierunku,
10

W obiekcie instancji możesz również użyć defined? instance.attributelub instance.respond_to? :attribute.
Są to bardziej ogólne rozwiązania do sprawdzania atrybutu modelu lub dowolnej metody.

Alter Lagos
źródło
3
Pamiętajcie:instance.respond_to?(:attribute) == false ; instance.attribute ; instance.respond_to?(:attribute) == true
kbrock