Ruby - 根据文件名创建一个类?

时间:2012-02-27 23:55:58

标签: ruby-on-rails ruby

这是我第一次制作自定义rails生成器,我希望能够根据传递给生成器的参数在模板中创建动态类,但我无法弄清楚如何以及如何正确格式化它。

   class Achievements::__FILE__ < Achievement
   end

这是我要创建的生成类,下面是生成器。同样在旁注,我是否在我的生成器中创建目录“成就”?

module Achiever
  module Generators
    class AchievementGenerator < Rails::Generators::Base
      source_root File.expand_path('../templates', __FILE__)
      argument :award, :type => :string

      def generate_achievement
        copy_file "achievement.rb", "app/models/achievement/#{file_name}.rb"
      end

      private

      def file_name
        award.underscore
      end

    end
  end
end

2 个答案:

答案 0 :(得分:2)

使用Module#const_set。它会自动包含在Object中,因此您可以执行以下操作:

<强> foo.rb

# Defining the class dynamically. Note that it doesn't currently have a name
klass = Class.new do
  attr_accessor(:args)
  def initialize(*args)
    @stuff = args
  end
end
# Getting the class name
class_name = ARGV[0].capitalize
# Assign it to a constant... dynamically. Ruby will give it a name here.
Object.const_set(class_name, klass)
# Create a new instance of it, print the class's name, and print the arguments passed to it. Note: we could just use klass.new, but this is more fun.
my_klass = const_get(class_name).new(ARGV[1..-1])
puts "Created new instance of `" << my_klass.class << "' with arguments: " << my_klass.args.join(", ")

我还没有尝试过这个代码,但它应该产生类似的东西:

$ ruby foo.rb RubyRules pancakes are better than waffles
Created new instance of `RubyRules' with arguments: pancakes, are, better, than, waffles

此外,const_set绝对的第一个参数必须以大写的字母数字字符开头(就像静态定义常量一样),或者Ruby会产生一些错误:< / p>

NameError: wrong constant name rubyRules
        --- INSERT STACKTRACE HERE ---

答案 1 :(得分:0)

我弄清楚了这个问题。我应该使用模板方法而不是copy_file方法。这允许我在模板化视图中使用erb标签,我可以在视图中调用file_name.classify,它将动态创建模型。

argument :award, :type => :string

上面设置的参数将在生成的模型中定义下面的类。

class Achievements::<%= file_name.classify %> < Achievement
end