我希望能够加载整个应用程序,以便我可以找到给定类的后代.
例如,给定我定义了以下类:
# app/models/foo_class.rb
class FooClass < MySpecialBaseClass
# pasta code
end
Run Code Online (Sandbox Code Playgroud)
它不会被发现:
irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass }
=> []
Run Code Online (Sandbox Code Playgroud)
直到我调用const:
irb> FooClass
Run Code Online (Sandbox Code Playgroud)
然后它返回:
irb> ObjectSpace.each_object.select { |obj| obj.is_a?(Class) && obj <= MySpecialBaseClass }
=> [FooClass]
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?
如果我有4个具有以下层次结构的类:
class MainClass < ActiveRecord::Base
...
end
class SubClassA < MainClass
...
end
class SubClassB < MainClass
...
end
class SubClassC < MainClass
...
end
Run Code Online (Sandbox Code Playgroud)
如何在不经过并创建其他每个类的实例的情况下获取MainClass的子类列表?
在一个新的IRB会议中,我可以进去说
irb(main)> MainClass.descendants
=> []
Run Code Online (Sandbox Code Playgroud)
但是,如果我经历并创建每个子类的实例,我将看到以下内容
irb(main)> SubClassA.new
=> #<SubClassA ...>
irb(main)> SubClassB.new
=> #<SubClassB ...>
irb(main)> SubClassC.new
=> #<SubClassC ...>
irb(main)> MainClass.descendants
=> [SubClassA(...), SubClassB(...), SubClassC(...)]
Run Code Online (Sandbox Code Playgroud)
我基本上是在寻找一种方法来提供所有子类的方法,以便将来当我想添加SubClassD,SubClassE等时,我不必担心每个人都会在代码中实例化,然后用户才能看到它们.
当我在本地进入 rails 控制台时,我需要能够从控制器中看到所有类的后代。我有这个Api::BaseController,我所有的 Api 控制器都继承自。我遇到的问题是,当我跳入 rails 控制台以检查后代中的 Api 控制器时,它一直是空的,直到我调用它们。这可能与开发中的类如何不急切加载有关,并且它们不在本地缓存。
sample_app$ rails c
Loading development environment (Rails 4.2.0)
2.1.5 :001 > Api::BaseController.descendants
=> []
2.1.5 :002 > Api::V1::FoosController
=> Api::V1::FoosController
2.1.5 :003 > Api::BaseController.descendants
=> [Api::V1::FoosController]
Run Code Online (Sandbox Code Playgroud)
从这个例子中,你可以看到当我Api::BaseController第一次调用后代时,它是一个空数组。在调用其中一个控制器之后,该类将被加载并显示为后代。在这种情况下,V1 以及 V2、V3 等中可能有任意数量的控制器......
作为一个愚蠢的丑陋的黑客,我可以做到
Dir.glob("#{Rails.root.join('app', 'controllers', 'api', 'v1')}/**/*.rb").each(&method(:require_dependency))
Run Code Online (Sandbox Code Playgroud)
但我不想每次进入控制台时都必须写。我也在研究一个 gem,绝对不想把这种代码放在我的 gem 中。
另一种选择是在开发中缓存类,但这本身会导致巨大的问题。谁有想法?
编辑
另一种选择是调用Rails.application.eager_load!. 如果我只能在我的 API 文件夹中指定控制器,这个选项就可以正常工作。这样我就不必急切加载整个应用程序,而只需加载我需要的一小部分控制器。
这个问题类似于/关于另一个堆栈溢出问题,关于在Ruby中查找类的所有后代.一个很好的问题,我正在寻找的信息 - 除了我下载到rails控制台时:
irb(main):001:0> ActiveSupport::DescendantsTracker.descendants(Object)
=>[]
irb(main):002:0> ObjectSpace.each_object(Class).select { |klass| klass < Object }
=> [IRB::Notifier::AbstractNotifier, IRB::Notifier::ErrUnrecognizedLevel, ...]
Run Code Online (Sandbox Code Playgroud)
那么,为什么ActiveSupport :: DescendantsTracker不返回Object的后代?实施中有什么不同?DescendantsTracker的文档表明:
该模块提供了一个内部实现来跟踪后代,这比通过ObjectSpace迭代更快.
快点?好吧,它必须更快地返回任何东西(对吧?),但它应该返回所提供类的后代.
可能重复:
在Ruby中查找类的所有后代
所以,让我们说我们有:
class LivingBeing
class Animal
end
class Bacteria
end
class Virus
end
end
class Fungi < LivingBeing
end
Run Code Online (Sandbox Code Playgroud)
如何检查子类LivingBeing有哪些?我知道我们有Klass.ancestors什么方法可以看到与祖先相反的方法?
我正在测试rspec,factory_girl和capybara.该项目使用devise,我有以下方法登录规范:
def login_admin
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in FactoryGirl.create(:admin)
end
end
def login_user
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user)
end
end
Run Code Online (Sandbox Code Playgroud)
然后我在companies_controller_spec上执行测试:
require 'spec_helper'
describe CompaniesController, :type => :controller do
let(:valid_attributes) { { "email" => Faker::Internet.email } }
login_admin
describe "GET show" do
it "assigns the requested company as @company" do
company = FactoryGirl.create(:company)
get :show, {:id => company.to_param}
expect(assigns(:company)).to eq(company)
end
end
describe "GET edit" do
it "assigns the requested company as @company" do
company = FactoryGirl.create(:company) …Run Code Online (Sandbox Code Playgroud) 我的目标是:
class MyBeautifulRubyClass
#some code goes here
end
puts MyBeautifulRubyClass.subclasses #returns 0
class SlightlyUglierClass < MyBeautifulRubyClass
end
puts MyBeautifulRubyClass.subclasses #returns 1
Run Code Online (Sandbox Code Playgroud)
理想情况下甚至是地狱
puts MyBeautifulRubyClass.getSubclasses #returns [SlightlyUglierClass] in class object form
Run Code Online (Sandbox Code Playgroud)
我相信这是可能的,只是不确定如何!
有没有办法获取所有已定义的类的列表.我正在寻找这样的代码:
Class.instances.each do |klass|
puts klass.name
end
Run Code Online (Sandbox Code Playgroud)
如果没有办法做到这一点.可以定义一个A类,使其后代在其中注册?例如,以这种方式:
class A
...
end
class B < A
end
class C < B
end
A.descendants # => [B, C]
Run Code Online (Sandbox Code Playgroud) 我想调用一个名为my_format_number如下的函数:
num = 5.5
formated_num = num.my_format_number
Run Code Online (Sandbox Code Playgroud)
我怎样才能在 Ruby 中做到这一点?这些类型的函数的名称是什么?
如何获得定义方法的类?
我已经找到了如何查找后代和ansestors的方法:查找Ruby中一个类的所有后代
但这并不一定会让我得到定义类(实际上是最后一个定义类)。
我已经找到了如何获取调用类: Ruby Inheritance Get Caller Class Name
但我要相反。我想如何获得定义类。
我也试过了Module.nesting。在这种情况下,这就是我想要的,但是我担心,在我没有最终控制权的更大的代码库中,这将是不一致的并且不可接受的。
puts RUBY_VERSION
# Test class vs super.
class Super
def test_func
puts "#{self.class}, #{ __method__}"
end
end
class Child < Super
def test_func2
self.test_func
end
end
Child.new.test_func
Run Code Online (Sandbox Code Playgroud)
我曾希望:
1.8.7
超级,test_func
但是得到了:
1.8.7
孩子,test_func