我有以下课程:
class Entity
attr_accessor :name, :internal_asn_number, :classification_id
def initialize(name = nil,int_asn_no = 0,classification_id = nil)
@name = name
@internal_asn_number = int_asn_no
@classification_id = classification_id
然后我有一个从YAML文件动态创建实体对象的方法,但是我希望字段:internal_asn_number
也是动态的,它应该从64512到65534(含)。例如,如果代码仅创建三个实体对象,则字段:internal_asn_number
应分别具有每个对象的值64512,64513和64514。
我的代码如下:
#map of yaml fields from entities yaml conf files
FIELDS = {'ENTITY_ID'.to_sym => 'entity_identification','NAME'.to_sym => 'name','CLASS_ID'.to_sym => 'classification_id'}
def load_yaml
path = /mf370/Desktop/entities_yamls/
entities = Array.new
Dir.entries(path).select {|file|
if !File.directory? path + file
if File.extname(path + file) == '.yaml'
config = YAML.load_file(path + file)
asn=*(64512..65533)
asn.each do |number|
entity = Entity.new(config[FIELDS[:ENTITY_ID]][FIELDS[:NAME]],"#{number + 1}",
config[FIELDS[:ENTITY_ID]][FIELDS[:CLASS_ID]])
entities << entity
end
end
end
}
return entities
end
这段代码在输出中给出了几个问题,实体数组只保存了多次最后一个对象,并且:asn_internal_number
的值为65533,是范围内的最后一个数字。
答案 0 :(得分:1)
避免为每个文件循环可能的asn_interal_number
值范围;相反,您可以使用另一个变量来跟踪当前asn_interal_number
并在分配下一个之前检查它;例如:
FIELDS = {'ENTITY_ID'.to_sym => 'entity_identification','NAME'.to_sym => 'name','CLASS_ID'.to_sym => 'classification_id'}
ASN_LIMIT = 65533
def load_yaml
path = "/mf370/Desktop/entities_yamls/"
entities = Array.new
current_asn = 64512
Dir.entries(path).select do |file|
if !File.directory? path + file
if File.extname(path + file) == '.yaml'
if current_asn > ASN_LIMIT
puts "Error, maximum asn numbers reached"
else
config = YAML.load_file(path + file)
Entity.new(config[FIELDS[:ENTITY_ID]][FIELDS[:NAME]],"#{current_asn}",
config[FIELDS[:ENTITY_ID]][FIELDS[:CLASS_ID]])
entities << entity
current_asn += 1
end
end
end
end
return entities
end
你会注意到的第一件事就是添加一个ASN_LIMIT
常量,用于检查是否还有asn数字。
ASN_LIMIT = 65533
添加current_asn
,跟踪分配的las asn数字(用第一个可能的值初始化):
current_asn = 64512
最后,asn
循环被另一个if
替换,如果达到ASN_LIMIT
则会输出错误,或者指定curret_asn
值:
接下来,current_asn
作为参数传递给Entity.new
(不做任何修改):
if current_asn > ASN_LIMIT
puts "Error, maximum asn numbers reached"
else
config = YAML.load_file(path + file)
Entity.new(config[FIELDS[:ENTITY_ID]][FIELDS[:NAME]],"#{current_asn}",
config[FIELDS[:ENTITY_ID]][FIELDS[:CLASS_ID]])
entities << entity
current_asn += 1
end
请注意,current_asn
一旦用于创建新的Entity
,就会在结尾处递增。
以下评论与您的问题无关,但会使您的代码更简单:
你可以改变这个
FIELDS = {'ENTITY_ID'.to_sym => 'entity_identification','NAME'.to_sym => 'name','CLASS_ID'.to_sym => 'classification_id'}
到
FIELDS = { ENTITY_ID: 'entity_identification', NAME: 'name', CLASS_ID: 'classification_id' }
得到完全相同的结果:
#=> {:ENTITY_ID=>"entity_identification", :NAME=>"name", :CLASS_ID=>"classification_id"}
在ruby中,使用[]
而不是Array.new
创建一个空数组更加惯用:
entities = []
而不是Dir.entries
使用Dir.glob
,您无需检查文件是否是目录或是否具有更正扩展名:
Dir.glob("#{path}*.yaml") do |file|
if current_asn > ASN_LIMIT
# ...
end
end
答案 1 :(得分:1)
我同意之前的回答,但我想建议像这样编写自己的类:
class Entity
ASN_MIN = 64512
ASN_MAX = 65533
attr_accessor :name, :internal_asn_number, :classification_id
def initialize(name = nil, classification_id = nil)
@name = name
@classification_id = classification_id
set_internal_asn_number
end
private
def set_internal_asn_number
@@last_free_asn ||= ASN_MIN
raise 'No more free ASN number' if @@last_free_asn > ASN_MAX
@internal_asn_number = @@last_free_asn
@@last_free_asn += 1
end
end