Como listar todos os métodos de um objeto em Ruby?

113

Como faço para listar todos os métodos aos quais um determinado objeto tem acesso?

Eu tenho um @current_userobjeto, definido no controlador do aplicativo:

def current_user
  @current_user ||= User.find(session[:user_id]) if session[:user_id]
end

E quero ver quais métodos eu tenho disponíveis para mim no arquivo de visualização. Especificamente, quero ver quais métodos uma :has_manyassociação oferece. (Eu sei o que :has_many devo fornecer, mas quero verificar isso.)

Dirk
fonte
Para esclarecer, você deseja que os métodos possam ser chamados @current_user?
Andrew Marshall
@Dirk, bem-vindo ao stackoverflow! Lembre-se de "verificar" a resposta que melhor responde à sua pergunta. Também vote positivamente em qualquer resposta, a qualquer pergunta, que você considere útil / útil.
Larry K

Respostas:

211

O seguinte irá listar os métodos que a classe User possui que a classe Object base não possui ...

>> User.methods - Object.methods
=> ["field_types", "maximum", "create!", "active_connections", "to_dropdown",
    "content_columns", "su_pw?", "default_timezone", "encode_quoted_value", 
    "reloadable?", "update", "reset_sequence_name", "default_timezone=", 
    "validate_find_options", "find_on_conditions_without_deprecation", 
    "validates_size_of", "execute_simple_calculation", "attr_protected", 
    "reflections", "table_name_prefix", ...

Observe que methodsé um método para Classes e para instâncias de Class.

Aqui estão os métodos que minha classe de usuário possui que não estão na classe base ActiveRecord:

>> User.methods - ActiveRecord::Base.methods
=> ["field_types", "su_pw?", "set_login_attr", "create_user_and_conf_user", 
    "original_table_name", "field_type", "authenticate", "set_default_order",
    "id_name?", "id_name_column", "original_locking_column", "default_order",
    "subclass_associations",  ... 
# I ran the statements in the console.

Observe que os métodos criados como resultado dos (muitos) relacionamentos has_many definidos na classe User não estão nos resultados da methodschamada.

Adicionado Observe que: has_many não adiciona métodos diretamente. Em vez disso, o mecanismo ActiveRecord usa o Ruby method_missinge as responds_totécnicas para lidar com chamadas de método em tempo real. Como resultado, os métodos não são listados no methodsresultado do método.

Larry K
fonte
2
Embora isso possa não estar completo, pois alguns métodos são criados apenas quando method_missing é chamado (por exemplo, localizadores dinâmicos)
Frederick Cheung
se eu tentar responders_to? Recebo um erro de método ausente. Estou executando isso dentro de application.html.erb
Dirk
@Dirk - talvez o método não esteja presente ... Eu sugiro que você arquive uma nova pergunta onde você mostre quais são suas definições de classe AR e então pergunte sobre os métodos específicos que você acha: has_many deve fornecer. Você também tem a correspondência: belongs_to? As regras de capitalização e pluralização do Rails para AR levaram muitos ao erro ...
Larry K
@Larry. Obrigado - posso obter uma lista com .to_yaml. Tem a seguinte aparência: --- -: sketches -: sketch_ids -: sketches = -: sketch_ids = -: before_add_for_sketches -: before_add_for_sketches? <muitos omitidos> ........ como faço para acessar esses métodos? (apontando-me a documentação apreciada também :)
Dirk
A documentação para: has_many mostra muitos dos métodos que são adicionados. Outros são novos para versões posteriores do Rails. Estes incluem o "before_add_for" etc. Eles são "Callbacks da Associação" - veja aquela parte deste documento
Larry K
9

Módulo # instance_methods

Retorna uma matriz contendo os nomes dos métodos de instância públicos e protegidos no receptor. Para um módulo, esses são os métodos públicos e protegidos; para uma classe, eles são os métodos de instância (não singleton). Sem nenhum argumento ou com um argumento falso, os métodos de instância em mod são retornados, caso contrário, os métodos em mod e as superclasses de mod são retornados.

module A
  def method1()  end
end
class B
  def method2()  end
end
class C < B
  def method3()  end
end

A.instance_methods                #=> [:method1]
B.instance_methods(false)         #=> [:method2]
C.instance_methods(false)         #=> [:method3]
C.instance_methods(true).length   #=> 43
Clyfe
fonte
6

Ou apenas User.methods(false)para retornar apenas os métodos definidos nessa classe.

Ruto Collins
fonte
4

Você pode fazer

current_user.methods

Para uma melhor lista

puts "\n\current_user.methods : "+ current_user.methods.sort.join("\n").to_s+"\n\n"
Andreas Lyngstad
fonte
3

Que tal um desses?

object.methods.sort
Class.methods.sort
Michael Frederick
fonte
1

Suponha que o usuário has_many posts:

u = User.first
u.posts.methods
u.posts.methods - Object.methods
Marek Příhoda
fonte
1

Para expor a resposta de @clyfe. Você pode obter uma lista de seus métodos de instância usando o seguinte código (supondo que você tenha uma classe de objeto chamada "Parser"):

Parser.new.methods - Object.new.methods
Jared Menard
fonte
1

Se você está procurando uma lista de métodos que respondem por uma instância (no seu caso @current_user). De acordo com os métodos de documentação ruby

Retorna uma lista dos nomes dos métodos públicos e protegidos de obj. Isso incluirá todos os métodos acessíveis nos ancestrais do obj. Se o parâmetro opcional for falso, ele retorna uma matriz de métodos singleton públicos e protegidos de obj, a matriz não incluirá métodos em módulos incluídos em obj.

@current_user.methods
@current_user.methods(false) #only public and protected singleton methods and also array will not include methods in modules included in @current_user class or parent of it.

Como alternativa, você também pode verificar se um método pode ser chamado em um objeto ou não.

@current_user.respond_to?:your_method_name

Se você não quiser os métodos da classe pai, apenas subtraia os métodos da classe pai.

@current_user.methods - @current_user.class.superclass.new.methods #methods that are available to @current_user instance.
Mukesh Kumar Gupta
fonte