Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 用Ruby替换Ruby源文件中的函数_Ruby On Rails_Ruby_Replace - Fatal编程技术网

Ruby on rails 用Ruby替换Ruby源文件中的函数

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

首先,我使用的是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
    @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