Ruby - Создание класса на основе имени файла? - PullRequest
2 голосов
/ 28 февраля 2012

Я впервые делаю собственный генератор рельсов, и я хочу иметь возможность создавать динамический класс в шаблоне на основе аргумента, переданного генератору, но я не могу понять, как и правильно его отформатировать.

   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 ]

2 голосов
/ 28 февраля 2012

Использовать Модуль # 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 выдаст ошибку, похожую на следующую:

NameError: wrong constant name rubyRules
        --- INSERT STACKTRACE HERE ---
0 голосов
/ 28 февраля 2012

Я выяснил проблему с этим вопросом. Вместо метода copy_file я должен использовать метод шаблона. Затем это позволяет мне использовать теги erb внутри шаблонного представления, и я могу вызвать file_name.classify внутри представлений, и это будет динамически создавать модель.

argument :award, :type => :string

То, что здесь указано выше в качестве аргумента, будет определять класс ниже в сгенерированной модели.

class Achievements::<%= file_name.classify %> < Achievement
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...