Перечислить все методы, на которые реагирует объект?

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

У меня есть две модели,

 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. вы не сможете увидеть ‘build’ в списке, вероятно, он генерируется с помощью ‘method_missing’

2. Могу ли я в любом случае проверить реализацию method_missing для этого? Я хочу разобраться в том, как это работает

3. да, попробуйте запустить это: User.new.memberships.method_missing(:build) затем вы должны увидеть исключение, сообщающее, что был вызван защищенный метод ‘build’, после чего вы можете попытаться следовать ему. Но для этого потребуется некоторое время

4. @user.memberships.method_missing(:сборка) Исключение NoMethodError: неопределенный метод `build’ для #<Class:0x102fbf8f8>

Ответ №1:

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

Однако, похоже, что «build» — это автоматически сгенерированный метод, согласно документации. Обычно автоматически созданные методы в 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 и, и так далее, до бесконечности. Невозможно получить список всех этих возможностей.

Комментарии:

1. Не сработало. Вывод прилагается (я также пытался вызвать его в классе, а не в экземпляре, как предложила Симона) (rdb: 63) @user.memberships.class.instance_methods(true). включить?»build» false (rdb:63) @user.memberships.instance_methods(true). включить?»build» false

Ответ №2:

Пожалуйста, обратите внимание, что instance_methods возвращает массив строк или символов в зависимости от версии Ruby.

Ruby 1.8 возвращает массив строк, Ruby 1.9 — массив символов.

В 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 должен вызываться в классе, а не в экземпляре.

Комментарии:

1. Не сработало (rdb: 63) @user.memberships.instance_methods(true). включить?(:build) false (rdb:63) @user.memberships.class.instance_methods(true). включить?(:build) false

Ответ №3:

Вы могли бы попробовать:

 @user = User.first

@user.methods.grep /method_name/
  

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