将字符串转换为现有的类实例

时间:2012-10-23 15:55:19

标签: ruby

给定一个类实例和一个字符串,如何将字符串转换为引用实例?

class Room
  def enter
    puts "Welcome!"
  end
end

# Rooms are predefined
lounge = Room.new
kitchen = Room.new
study = Room.new

puts "Which room would you like to go to?"
print "> "
room = gets.strip

# User types "lounge"

room.enter # => undefined method `enter' for "lounge":String (NoMethodError)

我理解为什么我得到NoM​​ethodError,但我无法弄清楚如何转换room字符串以引用名为lounge的Room的现有实例。

5 个答案:

答案 0 :(得分:1)

或许试图按照房间来映射房间?

class Room

  def enter
    puts "Welcome!"
  end
end

# Rooms are predefined
rooms = %w[lounge kitchen study].inject({}) { |f,c| f.update c => Room.new }

puts "Which room would you like to go to?"
print "> "
if room = rooms[gets.strip]
  room.enter
end

甚至更简单:

class Room

  def initialize room_type
    @room_type = room_type
  end

  def enter
    return puts 'Unsupported room type' unless %w[
      lounge kitchen study
    ].include?(@room_type)
    puts "Welcome to #{@room_type}!"
  end

end

puts "Which room would you like to go to?"
print "> "
room = Room.new(gets.strip)
room.enter

答案 1 :(得分:1)

room_name = gets.strip.capitalize
room = Kernel.const_get(room_name)
room.enter

如果您require "active_support/all"(部分Rails)可以执行此操作:

room = gets.strip.camelize.constantize
room.new.enter

修改

正如田人指出的那样,require "active_support/core_ext/string/inflections"会更有效率。

答案 2 :(得分:1)

class Room
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def enter
    puts "Welcome to #{@name}!"
  end
end

# Rooms are predefined
rooms = ["lounge", "kitchen", "study"].map(&Room.method(:new))

puts "Which room would you like to go to?"
print "> "
name = gets.strip

# Just an example (not using find to avoid nil.enter)
p rooms.select{ |room| room.name == name }.map(&:enter)

答案 3 :(得分:0)

您可以使用eval方法动态执行一段ruby脚本。在这种情况下,eval(room)会为您提供房间实例。

然而,这是非常危险的方法,因为它允许最终用户执行代码。为了防止代码执行,您最好验证它是定义的房间变量之一:

eval(room).enter if local_variables.include?(room.to_sym)

答案 4 :(得分:0)

我最终在散列中将每个Room对象存储为初始化时的类变量。这允许您通过哈希引用每个实例:

class Room
  @@rooms = {}

  def initialize(name)
    @@rooms.store name, self
  end

  def rooms
    @@rooms
  end

  def enter
    puts "Welcome!"
  end
end

# Rooms are predefined
lounge = Room.new('lounge')
kitchen = Room.new('kitchen')
study = Room.new('study')

puts "Which room would you like to go to?"
print "> "
new_room = gets.strip

lounge.rooms[new_room].enter if lounge.rooms.has_key? new_room