Список всех методов, которые объект отвечает_to?

У меня две модели,

User 
Membership

Оба имеют следующее отношение друг к другу

user has_many :memberships

Я пытался выяснить, где находится метод сборки, и как я могу получить его в списке методов для экземпляра. Вот вывод отладчика, который показывает мою delima

(rdb:63) @user.memberships.respond_to?"build"
true

В то время как следующее возвращает false, не должно ли оно возвращать true??

(rdb:63) @user.memberships.instance_methods.include?"build"
false

Ответы

Ответ 1

Одно дело, что instance_methods принимает необязательный логический параметр, указывающий, хотите ли вы видеть методы предков-экземпляров. В вашем случае я думаю, что вы хотите instance_methods(true).

Однако, похоже, что "сборка" - это автогенерированный метод, согласно документации. Как правило, автогенерируемые методы в ActiveRecord реализуются путем переопределения method_missing и обработки вызовов "методами", которые фактически не существуют. responds_to также переопределяется, поэтому класс укажет, что он отвечает на правильные вызовы. Однако, поскольку эти "методы" на самом деле не определены, они не будут отображаться в списке instance_methods.

Поскольку список команд, которые класс может respond_to использовать method_missing, по существу бесконечен, я уверен, что нет способа получить список. Например, модель ActiveRecord, которая имеет атрибуты a, b, c и d, будет автоматически отвечать на вызовы, такие как find_by_a_and_b и find_by_a_b_and_c и find_by_b_and_d и т.д., До бесконечности. Невозможно получить список всех этих возможностей.

Ответ 2

Обратите внимание, что instance_methods возвращает массив String или Symbol в зависимости от версии Ruby.

Ruby 1.8 возвращает массив строк, Ruby 1.9 - Array of Symbol.

В Ruby 1.8

"".respond_to?(:upcase)
# => true 
"".class.instance_methods.include?("upcase")
# => false
"".class.instance_methods.include?(:upcase)
# => false

В Ruby 1.9

"".respond_to?(:upcase)
# => true 
"".class.instance_methods.include?("upcase")
# => false
"".class.instance_methods.include?(:upcase)
# => true

Кроме того, instance_methods должен быть вызван в классе, а не в экземпляре.

Ответ 3

Вы можете попробовать:

@user = User.first

@user.methods.grep /method_name/

Однако я не думаю, что вы увидите "build" или "create" в списке. Скорее всего, эти методы генерируются динамически