【问题标题】:Ruby String to Class NameRuby 字符串到类名
【发布时间】:2011-07-15 04:52:42
【问题描述】:

我正在尝试创建一个从ActiveRecord::Base 继承的新类,该类需要从字符串动态生成

"general_systems".camelize.singularize = Class.new < ActiveRecord::Base

但是我不断收到错误:

undefined method `singularize=' for "GeneralSystems":String

我也试过constantize这个字符串

>> foo = "general_systems".camelize.singularize
=> "GeneralSystem"
>> foo.constantize
NameError: uninitialized constant GeneralSystem
    from /var/lib/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/inflector/methods.rb:124:in `block in constantize'
    from /var/lib/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/inflector/methods.rb:123:in `each'
    from /var/lib/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/inflector/methods.rb:123:in `constantize'
    from /var/lib/gems/1.9.1/gems/activesupport-3.0.5/lib/active_support/core_ext/string/inflections.rb:43:in `constantize'
    from (irb):4
    from /usr/bin/irb:12:in `<main>'
>> foo.constantize = Class.new
NoMethodError: undefined method `constantize=' for "GeneralSystem":String
    from (irb):5
    from /usr/bin/irb:12:in `<main>'

任何帮助将不胜感激。

【问题讨论】:

  • 你不想调用一个不存在的方法 "general_systems".camelize.singularize=(Class.new)。你到底想做什么?
  • 根据您的一位 cmets 对某人的回答判断,您已经用他们的解决方案解决了问题。也许你现在可以选择一个答案?

标签: ruby metaprogramming


【解决方案1】:

如果您使用的是 Rails,它提供了一个名为 #constantize 的方法,它可以工作:

irb(main):017:0> Object.const_get 'House::Owns'
NameError: wrong constant name House::Owns

'House::Owns'.constantize
=> House::Owns

【讨论】:

  • 我得到:1.9.3p392 :019 &gt; 'House::Owns'.constantize NoMethodError: undefined method constantize' for "House::Owns":String from (irb):19 from /Users/ryan/.rvm/rubies/ruby-1.9.3-p392/ bin/irb:16:in
    '`
  • #constantize 是 Rails 方法。 api.rubyonrails.org/classes/ActiveSupport/…
【解决方案2】:

这样的?

>> Object.const_set("general_systems".classify, Class.new)
=> GeneralSystem
>> GeneralSystem.new
=> #<GeneralSystem:0x105b0f738>

【讨论】:

  • 这是一个积极支持的成语
【解决方案3】:
klazz = Class.new(ActiveRecord::Base) do
  def do_something_fun(param1)
    param1.have_fun!
  end
end

klazz_name = "general_systems".singularize.classify
Object.const_set(klazz_name, klazz)

【讨论】:

    【解决方案4】:

    查看“The Book Of Ruby”中的这个示例,包含在 Ruby 1.9 安装程序中。

    puts("What shall we call this class?> ")
    className = gets.strip().capitalize()
    Object.const_set(className,Class.new)
    puts("I'll give it a method called > 'myname'" ) 
    className = Object.const_get(className)
    className::module_eval{
      define_method(:myname){ 
        puts("The name of my class is '#{self.class}'" ) 
     } }
     x = className.new x.myname
    

    【讨论】:

      【解决方案5】:

      给定:

      class Banana
      end
      

      您可以通过以下方式获取纯 Ruby 中的类:

      Object.const_get 'Banana'
      => Banana
      

      或者如果您使用的是 Rails:

      'Banana'.constantize
      => Banana
      

      【讨论】:

        【解决方案6】:

        如果你的字符串包含命名空间,你可以使用:

        require 'rubygems'
        require 'active_support/inflector'
        parent=String # using String to get a self contained example
        # require 'active_record'   # uncomment for ActiveRecord::Base as parent class
        # parent=ActiveRecord::Base # uncomment for ActiveRecord::Base as parent class
        namespace = 'A::B::general_systems'.split('::') 
        class_name = namespace.pop 
        namespace = namespace.inject(Object) do |mod, name|
          if mod.constants.collect{|sym| sym.to_s}.include? name.classify
            mod.const_get name.classify
          else
            mod.const_set name.classify, Module.new
          end
        end
        
        klass = if namespace.constants.include? class_name.classify
          namespace.const_get class_name.classify
        else
          namespace.const_set class_name.classify, Class.new(parent)
        end
        
        object = klass.allocate # allocate new object of klass
        object.send :initialize # initialize object
        object.class
        object.class.superclass
        

        【讨论】:

          【解决方案7】:

          试试

          >> "general_systems".classify
          => "GeneralSystem"
          

          【讨论】:

          • 谢谢大家,我最终得到了:
            Object.const_set(loader.classify, Class.new(ActiveRecord::Base)) db_loader = Object.const_get(loader.classify ) db_loader.create(input_system) 
            而且效果很好。
          • @Telmo:为了将来参考,请使用反引号而不是&lt;pre&gt;&lt;code&gt;
          猜你喜欢
          • 2023-03-30
          • 1970-01-01
          • 1970-01-01
          • 2013-11-29
          • 2017-10-22
          • 1970-01-01
          • 2021-01-08
          • 2012-10-13
          • 1970-01-01
          相关资源
          最近更新 更多