#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’ в списке. Скорее всего, эти методы генерируются динамически