Ruby on rails 用Ruby替换Ruby源文件中的函数
首先,我使用的是Ruby 2.2.0和Rails 4.2.0(因此,如果其中有任何内容对这项任务有帮助的话,我已经安装了ActiveSupport) 什么Ruby on rails 用Ruby替换Ruby源文件中的函数,ruby-on-rails,ruby,replace,Ruby On Rails,Ruby,Replace,首先,我使用的是Ruby 2.2.0和Rails 4.2.0(因此,如果其中有任何内容对这项任务有帮助的话,我已经安装了ActiveSupport) 什么 class RulesController < ApplicationController before_action :set_rule, only: [:show, :edit, :update, :destroy] # GET /rules # GET /rules.json def index @rul
class RulesController < ApplicationController
before_action :set_rule, only: [:show, :edit, :update, :destroy]
# GET /rules
# GET /rules.json
def index
@rules = Rule.all
end
# GET /rules/1
# GET /rules/1.json
def show
puts params[:rule_set_edition_id]
@description = @rule.description
@input_lines = @description.split("\\n")
@output_lines = []
for input_line in @input_lines do
if input_line != "" then
@output_lines << input_line
end
end
@rule_set_edition
end
def some_other_method
puts "FooBar"
end
# GET /rules/new
def new
@rule = Rule.new
end
# GET /rules/1/edit
def edit
end
end
我希望能够读取一个Ruby文件并获取其中声明的任何方法,然后将它们写入/覆盖到另一个可能已经声明了这些方法的Ruby文件中
我想在源文件中这样做,它是作为一种预处理器来完成的,而不是在运行时。我不是说,我想永久地编辑一个源文件
如果没有什么,那么我将阅读文件,逐行查找def
和end
语句,但我想知道这样的语句是否已经存在
为什么
部分是为了使用,部分是为了看看我是否可以,我用Ruby编写了一个脚本,它解析ArgoXML生成的XMI文件,在我的绘图中使用了一些进一步的约束,以便我的脚本知道何时使用has_many
或has_many:through
,后者是我所有habtm使用的
然后,它在shell脚本中为我的所有模型等创建Rails生成器命令,并使用awk注入任何需要手动设置的关系(如与生成器不在同一行中)
这就为大约100个表快速创建了模型和数据库条目。显然,尽管再次运行我的脚本会删除任何现有文件(或者要求我做100次我想做的事情,考虑到大部分时间都是销毁,我宁愿不要)
示例:
我很高兴有一个包含函数声明的类,或者我可以把它放在一个命名的类或模块中,这并不重要。一个文件中只有一个类
我要做的是读取文件A的内容,从文件中获取每个方法。然后我想将这些方法覆盖到文件B的源中,这样我就可以得到文件C
文件A(其方法需要插入到文件B中的文件)
以及@ChrisHeald代码中的hack_templates.rb:
require 'method_source'
include MethodSource::CodeHelpers
$implementation = open(ARGV[0])
$template = open(ARGV[1])
module Implementation
class << self
eval $implementation.read
end
end
@template_by_line = $template.each_line.to_a
(Implementation.methods - Module.new.methods).each do |method|
$implementation.rewind
# Get the source code of our implementation method
impl_source = expression_at $implementation, Implementation.method(method).source_location[1]
# Get the line that this method starts on in the template
template_line = @template_by_line.index {|line| line.match(/^\s*def #{method}/) }
if template_line
# If we found a match, replace it
# Get the source code for the template method
tmpl_source = expression_at @template_by_line, template_line + 1
# Replace it with the implemetation method
@template_by_line[template_line] = impl_source
# Remove any extra lines from the template method
tmpl_source.split(/\n/).length.times do |len|
@template_by_line.delete_at template_line + len + 1
end
else
# find the last `end` in the template array and insert the implementation source before it
last_end = @template_by_line.rindex {|line| line.match(/^\s*end/)}
@template_by_line.insert(last_end, "\n" + impl_source + "\n")
end
end
File.open($template, "w+") do |f|
f.syswrite(@template_by_line.join)
end
要求“方法\源”
包括MethodSource::CodeHelpers
$implementation=open(ARGV[0])
$template=open(ARGV[1])
模块实现
类生成器
最简单的方法就是使用自定义生成器模板
在Rails3.0及更高版本中,生成器不仅在源根目录中查找模板,还搜索其他路径中的模板。其中之一是lib/templates。因为我们想要定制Rails::Generator::HelperGenerator,所以我们只需在lib/templates/Rails/helper中创建一个名为helper.rb的模板副本即可
控制器的模板如下所示:
因此,您只需在lib/templates/rails/controller/controller.rb
中创建一个副本,并将其自定义为如下内容:
<% if namespaced? -%>
require_dependency "<%= namespaced_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= class_name %>Controller < ApplicationController
def show
puts params[:rule_set_edition_id]
@description = @rule.description
@input_lines = @description.split("\\n")
@output_lines = []
for input_line in @input_lines do
if input_line != "" then
@output_lines << input_line
end
end
@rule_set_edition
end
def some_other_method
puts "FooBar"
end
<% (actions - [:show, :some_other_method]).each do |action| -%>
def <%= action %>
end
<%= "\n" unless action == actions.last -%>
<% end -%>
end
<% end -%>
def show
super
end
还可以选择使用source\u location
来检测方法边界,对生成的模板进行后处理,但这种方法非常灵活。目前我正在为这一点进行概念验证
实际上是对模板进行黑客攻击
我们将使用method_source
gem,它使用method#source_location
查找方法的起始位置,然后对行求值,直到找到完整的表达式。一旦有了它,我们就可以用我们的实现来替换给定的方法
这相当糟糕,如果可行的话,我建议不要这样做
实现.rb
def显示
放置参数[:规则设置版本id]
@description=@rule.description
@输入线=@description.split(\\n)
@输出_行=[]
对于@input_lines do中的input_line
如果输入_行!=”“那么
@输出线编辑:ArgoXML应该读为argouml如果你想做什么,你能提供一个简单的例子吗?这可能是可行的,但我想确保我正确理解了这个问题。你能调整发电机吗?好主意。如果你决定创建这个,并将其开源,我将捐赠给你的项目。我的建议是看一看,因为它包含一个ruby解析器和运行时。我很确定这是可以做到的。目前正在制定解决方案。但是,提供自己的发电机可能要容易得多。:)谢谢,我会看看这两种方法,看看哪一种适合。实际上,对模板进行黑客攻击可能会带来好处,而不是我目前使用的Awk。
require 'method_source'
include MethodSource::CodeHelpers
$implementation = open(ARGV[0])
$template = open(ARGV[1])
module Implementation
class << self
eval $implementation.read
end
end
@template_by_line = $template.each_line.to_a
(Implementation.methods - Module.new.methods).each do |method|
$implementation.rewind
# Get the source code of our implementation method
impl_source = expression_at $implementation, Implementation.method(method).source_location[1]
# Get the line that this method starts on in the template
template_line = @template_by_line.index {|line| line.match(/^\s*def #{method}/) }
if template_line
# If we found a match, replace it
# Get the source code for the template method
tmpl_source = expression_at @template_by_line, template_line + 1
# Replace it with the implemetation method
@template_by_line[template_line] = impl_source
# Remove any extra lines from the template method
tmpl_source.split(/\n/).length.times do |len|
@template_by_line.delete_at template_line + len + 1
end
else
# find the last `end` in the template array and insert the implementation source before it
last_end = @template_by_line.rindex {|line| line.match(/^\s*end/)}
@template_by_line.insert(last_end, "\n" + impl_source + "\n")
end
end
File.open($template, "w+") do |f|
f.syswrite(@template_by_line.join)
end
<% if namespaced? -%>
require_dependency "<%= namespaced_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= class_name %>Controller < ApplicationController
def show
puts params[:rule_set_edition_id]
@description = @rule.description
@input_lines = @description.split("\\n")
@output_lines = []
for input_line in @input_lines do
if input_line != "" then
@output_lines << input_line
end
end
@rule_set_edition
end
def some_other_method
puts "FooBar"
end
<% (actions - [:show, :some_other_method]).each do |action| -%>
def <%= action %>
end
<%= "\n" unless action == actions.last -%>
<% end -%>
end
<% end -%>
def show
super
end
def show
puts params[:rule_set_edition_id]
@description = @rule.description
@input_lines = @description.split("\\n")
@output_lines = []
for input_line in @input_lines do
if input_line != "" then
@output_lines << input_line
end
end
@rule_set_edition
end
def some_other_method
puts "FooBar"
end
class RulesController < ApplicationController
before_action :set_rule, only: [:show, :edit, :update, :destroy]
# GET /rules
# GET /rules.json
def index
@rules = Rule.all
end
# GET /rules/1
# GET /rules/1.json
def show
end
# GET /rules/new
def new
@rule = Rule.new
end
# GET /rules/1/edit
def edit
end
# . . . etc
end
require 'method_source'
include MethodSource::CodeHelpers
$implementation = open("implementation.rb")
$template = open("template.rb")
module Implementation
class << self
eval $implementation.read
end
end
@template_by_line = $template.each_line.to_a
(Implementation.methods - Module.new.methods).each do |method|
$implementation.rewind
# Get the source code of our implementation method
impl_source = expression_at $implementation, Implementation.method(method).source_location[1]
# Get the line that this method starts on in the template
template_line = @template_by_line.index {|line| line.match(/^\s*def #{method}/) }
if template_line
# If we found a match, replace it
# Get the source code for the template method
tmpl_source = expression_at @template_by_line, template_line + 1
# Replace it with the implemetation method
@template_by_line[template_line] = impl_source
# Remove any extra lines from the template method
tmpl_source.split(/\n/).length.times do |len|
@template_by_line.delete_at template_line + len + 1
end
else
# find the last `end` in the template array and insert the implementation source before it
last_end = @template_by_line.rindex {|line| line.match(/^\s*end/)}
@template_by_line.insert(last_end, "\n" + impl_source + "\n")
end
end
puts @template_by_line.join
$ ruby converter.rb
class RulesController < ApplicationController
before_action :set_rule, only: [:show, :edit, :update, :destroy]
# GET /rules
# GET /rules.json
def index
@rules = Rule.all
end
# GET /rules/1
# GET /rules/1.json
def show
puts params[:rule_set_edition_id]
@description = @rule.description
@input_lines = @description.split("\\n")
@output_lines = []
for input_line in @input_lines do
if input_line != "" then
@output_lines << input_line
end
end
@rule_set_edition
end
def new
@rule = Rule.new
end
# GET /rules/1/edit
def edit
def some_other_method
puts "FooBar"
end end
# . . . etc
end