I am developing a script that selects sub-components based on multiple Layers.
See a piece of code below:
@complist[]
ents.each do | bl_entity |
if bl_entity.is_a? (Sketchup::ComponentInstance)
subcomp = bl_entity.definition.entities.grep(Sketchup::ComponentInstance)
subcomp_onlayer = subcomp.find_all {|comp|
comp.layer.name == ("Layer1" || "Layer2" || "Layer3")
}
subcomp_onlayer.each {|compo|
@complist << compo.definition.name
}
end
end
This works but I have to pre-program all the Layers that the script must run.
I want to save the layer names as described above in a text file for the user to adjust.
The script must read the layer names from the text file and the text file is stored in the parameter (@qlayerlist)
Eval of an external file is indeed not secure - it could be modified to contain malicious code. Why not save the list as either one layer name per line or comma-delimited or some other plain text alternative, then open the file, read its lines, and load the strings into your list of layers?
I would store the data in something like JSON - then serialize between Hash and a JSON string. Then have your extension/script process the JSON data and use that to transform your model.
This statement does not do what you think. ("Layer1" || "Layer2" || "Layer3") is a logical expression that will always evaluate as true because the 1st subexpression "Layer1" will evaluate as true.
(In Ruby ALL objects evaluate as true except the nil and false objects. This means even 0, an empty string and an empty array evaluate as true when tested because they are still valid objects.)
So, the whole statement will always be false because layer.name always returns a String that will never be equivalent to true. In effect your conditional expression for the find_all is: false, and nothing will ever be found, always returning an empty array as subcomp_onlayer.
You can use a regular expression …
# Define a regular expression outside loops ...
one_of_target_layers = /(Layer1|Layer2|Layer3)/i
ents.each do | bl_entity |
if bl_entity.is_a?(Sketchup::ComponentInstance)
subcomp = bl_entity.definition.entities.grep(Sketchup::ComponentInstance)
subcomp_onlayer = subcomp.find_all { |comp|
comp.layer.name =~ one_of_target_layers
}
subcomp_onlayer.each { |compo|
@complist << compo.definition.name
}
end
end
If you don’t understand regular expressions (they are complex,) …
then you can use an array of layer names for comparison instead …
# Define an array of layer names outside loops ...
target_layers = ["Layer1","Layer2","Layer3"]
ents.each do | bl_entity |
if bl_entity.is_a?(Sketchup::ComponentInstance)
subcomp = bl_entity.definition.entities.grep(Sketchup::ComponentInstance)
subcomp_onlayer = subcomp.find_all { |comp|
target_layers.any? {|ln| ln == comp.layer.name }
}
subcomp_onlayer.each { |compo|
@complist << compo.definition.name
}
end
end