Reputation: 433
I have some string inputs, which I want to validate whether it's a valid Ruby Symbol literal. If it is, then convert it to a Symbol. Otherwise return the passed string.
Example,
def parse_symbol(str)
... # Validate and convert to Symbol
# Return Symbol if valid Symbol literal
# Otherwise return str
end
input1 = ':foo_bar' #=> Valid Symbol
parse_symbol(input1) #=> :foo_bar
input2 = ':"foo bar"' #=> Valid Symbol
parse_symbol(input2) #=> :"foo bar"
input3 = ':foo bar' #=> Invalid
parse_symbol(input3) #=> :foo bar
input4 = '::"foo_bar"' #=> Invalid
parse_symbol(input4) #=> ::"foo_bar"
... # all other possible valid and invalid symbol literal goes here
str.to_sym # Transforms every string into Symbol form
Edit
Is eval
an expensive tool to use here?
eval(str).is_a?(Symbol) rescue str
Upvotes: 1
Views: 196
Reputation: 458
def parse_symbol(str)
result = str.scan /^\:(((@@|@|\$)?[a-zA-Z_]+[a-zA-Z0-9_]*[!\?]?)|(\$([:.><\?!\$\\\/'"@`~\+\;]|\-\w))|(\$[0-9]+)|(<|>|\[\])|"(.*)"|'(.*)')$/
return str unless !result.empty?
result[0].drop(1).each do |part|
return part.to_sym unless part.nil?
end
end
Upvotes: 0
Reputation: 17528
I'd recommend using a real parser for this.
require 'parser/current'
require 'minitest/autorun'
def parse_symbol(str)
ast = Parser::CurrentRuby.parse(str)
if ast.type == :sym
ast.children[0]
else
str
end
rescue Parser::SyntaxError
str
end
class TestAnswer < Minitest::Test
def test_1
assert_equal :foo_bar, parse_symbol(':foo_bar')
end
def test_2
assert_equal :"foo bar", parse_symbol(':"foo bar"')
end
def test_3
assert_equal ":foo bar", parse_symbol(':foo bar')
end
def test_4
assert_equal '::"foo_bar"', parse_symbol('::"foo_bar"')
end
end
Upvotes: 3
Reputation: 127
Using a regular expression like this.
def parse_symbol(str)
if str ~= /:([^:\s]+||"[^:]+")/
return str.to_sym
else
return str
end
end
Is
eval
an expensive tool to use here?
It might not be that expensive, but it can be dangerous depending on where this input is coming from.
Upvotes: -1