【问题标题】:Is it possible to read a ruby hash from one file into another and then use its values?是否可以将 ruby​​ 哈希从一个文件读入另一个文件,然后使用它的值?
【发布时间】:2020-02-05 11:07:30
【问题描述】:

背景

我有一个项目结构,其中有一个 .rb 文件,其中包含散列中的数据,这不是文件中唯一的内容:

name "vm"
description "Configuration file for the Demo VM"
default_attributes(
    custom_demo: {
        verticals: {
            fashion: true,
            automotive: false,
            fsi: false,
            custom: true
        },
        channels: {
            b2b: true,
            b2c: true
        },
        geos: [
            'us_en'
        ]
    },
    infrastructure: {
        php: {
            version: '7.3',
            port: 9000
        },
        webserver: {
            http_port: 80,
            ssl_port: 443
        },
        database: {
            user: 'magento',
            password: 'password',
            name: 'magento'
        },
        elasticsearch: {
            use: true,
            version: '6.x',
            memory: '1g',
            port: 9200,
            plugins: ['analysis-phonetic', 'analysis-icu']
        },
        mailhog: {
            use: true,
            port: 10000
        },
        webmin: {
            use: true,
            port: 20000
        },
        samba: {
            use: true,
            shares: {
                composer_credentials: true,
                image_drop: true,
                web_root: true,
                app_modules: true,
                multisite_configuration: true,
                app_design: true
            }
        }
    }

在另一个 ruby​​ 脚本中,我需要使用这个 default_attributes 哈希中的值来做其他事情。

我的问题

在另一个 ruby​​ 脚本中使用上述 ruby​​ 哈希的最佳方法是什么?

我的尝试

首先我尝试使用load() 来“加载”带有哈希的文件。由于前两行,这引发了一个问题:

name "vm"
description "Configuration file for the Demo VM"

所以,我想我应该把它读成一个字符串或一个数组并跳过前两行:

data_string = ''
data = File.readlines(File.dirname(File.expand_path(__FILE__)) + '/environments/vm.rb').drop(2).each do |line| 
  data_string += line
end
data_hash = JSON.parse(data_string)
print data_hash

这种方法做了两件我不喜欢的事情:首先,它将结果打印到屏幕上,其次,它会出错:

/opt/vagrant/embedded/lib/ruby/2.4.0/json/common.rb:156:in `parse': 751: unexpected token at 'verticals: { (JSON::ParserError)

正是在这一点上,我开始怀疑我的方法,想知道我想做的事情是否可能。为了澄清,理想情况下,在弄清楚如何在另一个脚本中解析上述文件之后,我可以使用哈希中的一些东西,比如:

default_attributes[:infrastructure][:php][:version]
# => 7.3

【问题讨论】:

    标签: ruby hash


    【解决方案1】:

    尝试直接从这个文件中读取哈希是可行的,但是混乱。我认为你应该从不同的角度来处理它。与其尝试直接从该文件中读取哈希,不如将哈希移动到自己的文件中,然后从两个位置读取它。所以:

    1. 将散列放在自己的文件中:

      # my_hash.rb
      
      MyHash = {
        # put the hash content here
      }
      
    2. 从 vm 配置文件中加载它:

      # vm_config.rb
      
      require_relative './my_hash.rb'
      name "vm"
      description "Configuration file for the Demo VM"
      default_attributes(MyHash)
      
    3. 也可以从任何其他文件加载它:

      # other_file.rb
      
      require_relative './my_hash.rb'
      puts MyHash
      # => hash will print, it has been loaded
      

    作为一个练习(不要这样做!),这是我直接从文件中读取哈希的方法:

    # other_file.rb
    
    # dummy methods:
    def name(*args); end;
    def description(*args); end
    
    # intercept the hash and assign it to a global
    def default_attributes(hash)
      $my_hash = hash
    end
    
    # require the vm config file, running the above functions:
    require_relative './vm_config.rb'
    
    puts $my_hash
    # => prints the hash
    

    【讨论】:

    • Style nitpick: MyHash 应该是 MY_HASH,因为它是一个非模块常量。
    • 可能prepend(Module.new { def default_attributes(hash); ...; end }) 存储哈希并调用super :)
    • 这是一个很好的解决方案。对我来说不幸的是,我认为它不能解决我的实际问题:我正在使用 Chef,而独立哈希实际上是一组必须加载到 Chef 节点上的环境属性。当我使用这种方法时(可以理解),我收到“无法加载此类文件”错误,因为厨师正在尝试加载我所需的哈希文件,但它从未传输到节点。我将不得不尝试解决这个问题。同时,我会接受这个答案,并感谢您为解释它所做的努力。
    • 我使用的解决方法是将建议的独立 ruby​​ 哈希转换为 json,然后使用该 json 文件基本上将 vm_config.rb 文件写出。这给了我一个文件 chef 并不依赖于我可以读入我的 Vagrant 文件以供额外使用,但仍然为 chef 提供了它需要运行的 .rb 文件。公认的解决方案对于展示此方法非常有帮助。
    猜你喜欢
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多