除了`eval`,是否有任何功能可以从字符串中获取数组值?

时间:2019-02-13 13:15:32

标签: ruby-on-rails ruby

我有一个字符串params,其值为"1""['1','2','3','4']"。通过使用eval方法,可以获得结果1[1,2,3,4],但是我需要结果[1][1,2,3,4]

params[:city_id] = eval(params[:city_id])

scope :city, -> (params) { params[:city_id].present? ? where(city_id: (params[:city_id].is_a?(String) ? eval(params[:city_id]) : params[:city_id])) : all }

在这里,我不希望评估。

scope :city, -> (params) { params[:city_id].present? ? where(city_id: params[:city_id]) : all }

params[:city_id] #should be array values e.g [1] or [1,2,3,4] instead of string

2 个答案:

答案 0 :(得分:2)

您的字符串看起来非常接近JSON,因此您可能最安全的做法是将字符串解析为JSON。实际上:

JSON.parse("1") => 1
JSON.parse('["1","2","3","4"]') => ["1","2","3","4"]

现在您的数组使用单引号。所以我建议您这样做:

Array(JSON.parse(string.gsub("'", '"'))).map(&:to_i)

因此,将双引号替换为双引号,解析为JSON,确保将其包装在数组中并将数组中可能的字符串转换为整数。

答案 1 :(得分:1)

我对我首选的方法发表了评论:按原样完成参数设置是不寻常的,而理想的方法是解决此问题。使用eval绝对是不行的-这样做有很多安全方面的考虑(例如,假设有人将"City.delete_all"提交为参数)。

作为解决您眼前问题的一种方法,您可以使用正则表达式来扫描数字:

str = "['1','2','3','4']"
str.scan(/\d+/)
# => ["1", "2", "3"]

str = '1'
str.scan(/\d+/)
# => ["1"]

# In your case:

params[:city_id].scan(/\d+/)

用非常简单的术语来说,它会在给定的字符串中查找其中的任何数字。这是一个简单的Regex101,上面有结果/说明:https://regex101.com/r/41yw9C/1

Rails应该注意转换后续查询(where(city_id: params[:city_id]))中的字段,尽管如果您明确想要整数数组,则可以附加以下内容(感谢@SergioTulentsev):

params[:city_id].scan(/\d+/).map(&:to_i)

# or in a single loop, though slightly less readable:
[].tap { |result| str.scan(/\d+/) { |match| result << match.to_i } }

# => [1, 2, 3, 4]

希望这很有用,请让我知道您的生活状况或有任何疑问。