У меня есть класс Product в моем проекте rails, я пытаюсь получить список методов экземпляра моего класса, которые определены в моем файле (не унаследованный метод или включенный через mixin). Вот небольшой образец моего класса:
class Product
include Mongoid::Document
include Mongoid::Paperclip
include Mongoid::Search
include Mongoid::Slug
include Mongoid::Timestamps
extend Enumerize
def product_image
image.url(:small) unless image.nil?
end
def product_school_level
self.school_levels.join ' | '
end
def product_grades
self.grades.where(degree_ids: nil).pluck(:name).uniq.join ' | '
end
end
Пробовал использовать Product.instance_methods(false)
. Однако это по-прежнему возвращает множество методов, которые мне не нужны, вот небольшой пример:
: _run_post_process_callbacks,
: aliased_fields,
: _post_process_callbacks,
: _run_image_post_process_callbacks,
: _image_post_process_callbacks,
: _validation_callbacks,
: nested_attributes ?,
: _run_touch_callbacks,
: readonly_attributes ?,
: _run_save_callbacks,
: aliased_fields ?,
: _save_callbacks,
: localized_fields ?,
: readonly_attributes,
: fields ?,
: pre_processed_defaults ?,
: _update_callbacks,
: post_processed_defaults ?,
: поля,
: _id_default
Я запустил Product.new.method(:_run_post_process_callbacks).source_location
на нескольких из этих методов, чтобы попытаться проверить, откуда они берутся. Кажется, все они исходят от active_support.
Я никогда не включал active_support в свой класс, поэтому я предполагаю, что классы в проекте rails автоматически включают методы active_supports? Как это возможно без синтаксиса наследования (<<) или без синтаксиса включения?
Как мне тогда достичь того, что я хочу делать, и избавиться от тех методов, которые мне не нужны в моем списке?
Многие (большинство? Все?) Из тех дополнительных методов, которые вы видите, создаются с использованием Module#define_method
. Если вы покопаетесь в источниках active_support
, вы увидите это. (Вы не включаете напрямую active_support
, но он втягивается одним или несколькими модулями Mongoid
.)
На самом деле это действительные методы экземпляра вашего модельного класса, поэтому они включены в instance_methods(false)
. О других методах, которые определены «традиционно» в миксинах, таких как #freeze
, сообщает instance_methods(true)
, но не instance_methods(false)
.
Я думаю, вам, возможно, придется что-то сделать, чтобы отфильтровать список на основе местоположения источника. Что-то в этом роде:
my_methods = Product.instance_methods(false).select do |m|
Product.instance_method(m).source_location.first.ends_with? '/product.rb'
end
@DavidGeismar. Да, define_method
можно использовать для определения метода во включающем классе. Вот пример того, как это можно сделать: gist.github.com/showaltb/da9e8773211f9e7b62d2a52ec2047eb2. (Это не совсем тот метод, который использует active_support
, но эффект тот же.)
Я не понимаю вашего объяснения по поводу Module #define_method: apidock.com/ruby/Module/define_method. Я проверил это, и на самом деле, когда вы используете define_method в родительском классе или в модуле, который добавляется позже, метод не возвращается
Child.instance_methods(false)