【问题标题】:Is there a way in Ruby/Rails to execute code that is in a string?Ruby/Rails 中有没有办法执行字符串中的代码?
【发布时间】:2010-11-14 09:42:42
【问题描述】:

所以我有一个包含不同代码示例的数据库(阅读 sn-ps)。 代码示例由用户创建。 Rails 中有没有办法执行它?

例如,我的数据库中有以下代码(id=123):

return @var.reverse

有没有办法让我执行它?比如:

@var = 'Hello'
@result = exec(CodeSample.find(123))

所以结果是'olleH'

【问题讨论】:

    标签: ruby-on-rails ruby scripting


    【解决方案1】:

    你可以使用eval:

    code = '@var.reverse'
    @var = 'Hello'
    @result = eval(code)  # => "olleH"
    

    但是这样做要非常小心;您正在授予该代码对系统的完全访问权限。试试eval('exit()') 看看会发生什么。

    【讨论】:

    • 像魔术一样工作。是的,我知道这是一个安全/可用性问题。但这是一个仅供内部使用的原型,我也希望有一个插件可以做类似的功能,但带有“沙盒”,这意味着让我只公开某些 ruby​​ 函数,或者更好的是只公开某个类的一组方法。我想这是一个单独的讨论;-)
    【解决方案2】:

    对于eval 的答案(这是正确的),我要补充:给你一份 Pickaxe Book 的副本(Programming RubyProgramming Ruby 1.9,取决于你的 Ruby 版本)并阅读名为 “将 Ruby 锁定在保险箱中。” 这一章全部是关于 Ruby 的安全级别和受污染的对象,本章开头正是你的用例以及为什么你需要对此保持偏执.

    【讨论】:

    【解决方案3】:

    如果您的用例非常有限或限制用例,您还可以使用另一种方法。

    我不得不使用这种方法来允许用户动态指定相对时间,例如3.months.ago

    我使用正则表达式来清理用户的输入,就像这样

    PERMITTED_OPERATIONS = /^\{\%([1-9]\.(day|year|month|hour|minute)(s\.|\.)ago|Time\.now)\%\}$/
    def permit?(operation)
      return !PERMITTED_OPERATIONS.match(operation.to_s).nil?
    end
    

    您也可以扩展正则表达式以允许 from_now 或为允许的操作创建一个正则表达式数组并对其进行循环。

    欢迎任何采用这种方法的 cmets。

    【讨论】:

    • 我修改了你的,以满足我的需要:^[1-9]{1,2}\.(day|year|month|hour|minute)(s\.|\.)ago$我很确定你想逃避你的月经?
    • @Sam 是的,你是 100% 正确的。句号应该被转义。我已经更新了答案。很好发现。
    猜你喜欢
    • 1970-01-01
    • 2019-12-03
    • 2013-08-12
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多