在 ruby 中覆盖冻结变量的方法有哪些?

What are the ways to override a frozen variable in ruby?

这是一个 selenium-webdriver commands.rb 文件,我想在其中编辑 upload_fileCOMMANDS 变量从 [:post、'session/:session_id/se/file'][:post , 'session/:session_id/file']。我想将这个 class 扩展到我的一个,并使这个更改永久化,这样即使我 捆绑安装 它,这个更改也不应该消失。

module Selenium
  module WebDriver
    module Remote
      module W3C
        class Bridge
          COMMANDS = {
            upload_file: [:post, 'session/:session_id/se/file']
          }.freeze

        end
      end
    end
  end
end

您只需将常量分配给新值即可解决解冻问题:

Selenium::WebDriver::Remote::W3C::Bridge.const_set(:COMMANDS, {
 upload_file: [:post, 'session/:session_id/file']
}.freeze)

您会收到警告,但它会起作用。

如果你真的想解冻,我必须向你指出另一个关于该主题的问题:


回复评论

最简单的方法是使用 ActiveSupport 中的 ActiveSupport Hash#deep_dup。如果这是一个 non-rails 项目,您可以添加 activesupport gem 和 require 'active_support/all':

my_commands = Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS.deep_dup

# Here we can change one key only, or do any other manipulation:
my_commands[:upload_file] = [:post, 'session/:session_id/file']
Selenium::WebDriver::Remote::W3C::Bridge.const_set(:COMMANDS, my_commands)

您也可以在没有 ActiveSupport 的情况下执行此操作,但是您需要更加注意如何克隆对象,因为 deep_dup 不可用,像这样的方法可以代替:

my_commands = Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS.clone.transform_values(&:clone)

然后 运行 与上一个示例相同的内容。

要理解这一点,请阅读 Ruby 中对象的“浅”与“深”副本之间的区别,或者“克隆”与“deep_dup”之间的区别。如果您不熟悉,另请参阅我在该片段中使用的 Hash#transform_values