是否可以为包含任何包含模型的 Ruby class 渲染 "source code"?
Is it possible to render the "source code" for a Ruby class that includes any included models?
说,我有以下 Ruby:
module Nameable
def name
"John"
end
end
class User
include Nameable
def email
"john@example.com"
end
end
有没有办法显示、打印或查看整个 "User" 的 "expanded source code"?我不确定这个术语是什么,但是 "expanded source code" 我的意思是 Ruby 中的代码(所以不是 AST),其中包含的部分包括:
class User
def name
"John"
end
def email
"john@example.com"
end
end
当解决方案还可以显示继承行为的代码时加分。
您可以使用 method_source gem.
require 'method_source'
def flatten_source_code(klass)
excluded_parents = [Kernel, Object, BasicObject]
type = klass.instance_of?(Module) ? "module" : "class"
puts "#{type} #{klass}"
(klass.ancestors-excluded_parents).reverse.each do |ancestor|
ancestor.instance_methods(false).each do |method_name|
method = ancestor.instance_method(method_name)
script, line = method.source_location
if script then
puts
puts " # #{script} (line #{line})"
puts method.source
else
puts
puts " # def #{method_name}"
puts " # end"
end
end
end
puts "end"
end
module Nameable
def name
"John"
end
end
class User
include Nameable
def email
"john@example.com"
end
end
flatten_source_code(User)
puts
flatten_source_code(Nameable)
#=>
# class User
#
# # flatten_source_code.rb (line 27)
# def name
# "John"
# end
#
# # flatten_source_code.rb (line 34)
# def email
# "john@example.com"
# end
# end
# module Nameable
#
# # flatten_source_code.rb (line 27)
# def name
# "John"
# end
# end
对于更复杂的情况,它不会完美地工作,但它可以为您的示例工作。
纯属娱乐,有:
module Nameable
def name
"John"
end
def email
"included john@example.com"
end
end
module AnotherModule
def email
"prepended john@example.com"
end
end
class User
include Nameable
prepend AnotherModule
def email
"john@example.com"
end
end
flatten_source_code(User)
puts "u = User.new"
puts "puts u.name"
puts "puts u.email"
正在启动 ruby flatten_source_code.rb | ruby
returns :
John
prepended john@example.com
所以显示的 Ruby 代码是有效的并且遵循继承顺序。
不过,它会多次定义相同的方法。
您可以保留 |method_name,method_source|
的哈希值。如果一个方法覆盖旧方法并调用 super
,您可以将旧方法定义为私有方法 old_method_name_from_Module_blabla
并相应地替换 super
。
说,我有以下 Ruby:
module Nameable
def name
"John"
end
end
class User
include Nameable
def email
"john@example.com"
end
end
有没有办法显示、打印或查看整个 "User" 的 "expanded source code"?我不确定这个术语是什么,但是 "expanded source code" 我的意思是 Ruby 中的代码(所以不是 AST),其中包含的部分包括:
class User
def name
"John"
end
def email
"john@example.com"
end
end
当解决方案还可以显示继承行为的代码时加分。
您可以使用 method_source gem.
require 'method_source'
def flatten_source_code(klass)
excluded_parents = [Kernel, Object, BasicObject]
type = klass.instance_of?(Module) ? "module" : "class"
puts "#{type} #{klass}"
(klass.ancestors-excluded_parents).reverse.each do |ancestor|
ancestor.instance_methods(false).each do |method_name|
method = ancestor.instance_method(method_name)
script, line = method.source_location
if script then
puts
puts " # #{script} (line #{line})"
puts method.source
else
puts
puts " # def #{method_name}"
puts " # end"
end
end
end
puts "end"
end
module Nameable
def name
"John"
end
end
class User
include Nameable
def email
"john@example.com"
end
end
flatten_source_code(User)
puts
flatten_source_code(Nameable)
#=>
# class User
#
# # flatten_source_code.rb (line 27)
# def name
# "John"
# end
#
# # flatten_source_code.rb (line 34)
# def email
# "john@example.com"
# end
# end
# module Nameable
#
# # flatten_source_code.rb (line 27)
# def name
# "John"
# end
# end
对于更复杂的情况,它不会完美地工作,但它可以为您的示例工作。
纯属娱乐,有:
module Nameable
def name
"John"
end
def email
"included john@example.com"
end
end
module AnotherModule
def email
"prepended john@example.com"
end
end
class User
include Nameable
prepend AnotherModule
def email
"john@example.com"
end
end
flatten_source_code(User)
puts "u = User.new"
puts "puts u.name"
puts "puts u.email"
正在启动 ruby flatten_source_code.rb | ruby
returns :
John
prepended john@example.com
所以显示的 Ruby 代码是有效的并且遵循继承顺序。 不过,它会多次定义相同的方法。
您可以保留 |method_name,method_source|
的哈希值。如果一个方法覆盖旧方法并调用 super
,您可以将旧方法定义为私有方法 old_method_name_from_Module_blabla
并相应地替换 super
。