showing - Dada una clase, ver si la instancia tiene método(Ruby)
the asset "default.css" is not present in the asset pipeline. (10)
Creo que hay algo mal con method_defined?
en rieles. Puede ser inconsistente o algo así, así que si usa Rails, ¿es mejor usar algo de attribute_method?(attribute)
.
"¿La prueba para method_defined? en las clases de ActiveRecord no funciona hasta que se presente una instanciación " es una pregunta sobre la inconsistencia.
Sé en Ruby que puedo usar respond_to?
para comprobar si un objeto tiene un método determinado.
Pero, dada la clase, ¿cómo puedo verificar si la instancia tiene un método determinado?
es decir, algo como
Foo.new.respond_to?(:bar)
Pero siento que debe haber una mejor manera que crear una instancia de una instancia nueva.
En realidad, esto no funciona tanto para los objetos como para las clases.
Esto hace:
class TestClass
def methodName
end
end
Así que con la respuesta dada, esto funciona:
TestClass.method_defined? :methodName # => TRUE
Pero esto no funciona:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
Así que uso esto tanto para clases como para objetos:
Clases:
TestClass.methods.include? ''methodName'' # => TRUE
Objetos:
t = TestClass.new
t.methods.include? ''methodName'' # => TRUE
La respuesta a " Dada una clase, ver si la instancia tiene método (Ruby) " es mejor. Al parecer, Ruby tiene esto incorporado, y de alguna manera lo extrañé. Mi respuesta se deja para referencia, independientemente.
Las clases de Ruby responden a los métodos instance_methods
y public_instance_methods
. En Ruby 1.8, la primera lista todos los nombres de métodos de instancia en una matriz de cadenas, y la segunda lo restringe a métodos públicos. El segundo comportamiento es el que probablemente desearía, ya que respond_to?
También se restringe a métodos públicos por defecto.
Foo.public_instance_methods.include?(''bar'')
En Ruby 1.9, sin embargo, esos métodos devuelven matrices de símbolos.
Foo.public_instance_methods.include?(:bar)
Si planea hacer esto a menudo, es posible que desee extender el Module
para incluir un método de acceso directo. (Puede parecer extraño asignar esto a Module
lugar de Class
, pero como es allí donde viven los métodos de método de instance_methods
, es mejor mantenerse en línea con ese patrón).
class Module
def instance_respond_to?(method_name)
public_instance_methods.include?(method_name)
end
end
Si quieres admitir tanto a Ruby 1.8 como a Ruby 1.9, sería un lugar conveniente para agregar la lógica para buscar cadenas y símbolos, también.
No estoy seguro si esta es la mejor manera, pero siempre puedes hacer esto:
Foo.instance_methods.include? ''bar''
No sé por qué todo el mundo está sugiriendo que deberías usar instance_methods
e include?
cuando method_defined?
hace el trabajo.
class Test
def hello; end
end
Test.method_defined? :hello #=> true
Prueba Foo.instance_methods.include? :bar
Foo.instance_methods.include? :bar
Puedes usar method_defined?
como sigue:
String.method_defined? :upcase # => true
Mucho más fácil, portátil y eficiente que el instance_methods.include?
todos los demás parecen estar sugiriendo
Tenga en cuenta que no sabrá si una clase responde dinámicamente a algunas llamadas con method_missing
, por ejemplo, redefiniendo respond_to?
, o desde Ruby 1.9.2 definiendo respond_to_missing?
.
Si está verificando si un objeto puede responder a una serie de métodos, podría hacer algo como:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
the methods & something.methods
unirá las dos matrices en sus elementos comunes / coincidentes. something.methods incluye todos los métodos que está verificando, igualará los métodos. Por ejemplo:
[1,2] & [1,2,3,4,5]
==> [1,2]
asi que
[1,2] & [1,2,3,4,5] == [1,2]
==> true
En esta situación, querría usar símbolos, porque cuando llama a .methods, devuelve una serie de símbolos y si usó ["my", "methods"]
, devolvería falso.
klass.instance_methods.include :method_name
o "method_name"
, según la versión de Ruby, creo.
class Foo
def self.fclass_method
end
def finstance_method
end
end
foo_obj = Foo.new
foo_obj.class.methods(false)
=> [:fclass_method]
foo_obj.class.instance_methods(false)
=> [:fclass_method]
¡Espero que esto te ayude!