【问题标题】:Ruby Best Practice - Dynamic Attributes vs Hash for RoR applicationRuby 最佳实践 - RoR 应用程序的动态属性与哈希
【发布时间】:2012-03-09 14:45:29
【问题描述】:

我正在开发一个模型,其中包含服务器选项的配置设置。服务器选项的数量和类型发生了变化,我需要一些关于两种方式的优缺点的输入。 我正在与 rails ActiveRecord 数据库分开执行此操作。我所有的数据库交互都将通过文件系统手动进行。

首先,让模型根据需要为每个指定的服务器动态创建属性。 (只要这是可能的......我以前从未做过)

其次,创建单个哈希,其中包含服务器选项的键和服务器设置的值。

我认为第二种方法会更容易实施,但我不确定这是否是正确的方法?使用动态属性似乎更干净。

这方面有经验法则吗?

【问题讨论】:

    标签: ruby-on-rails ruby set dynamic-attributes


    【解决方案1】:

    你知道 Rails 中的 Store 功能吗?

    http://api.rubyonrails.org/classes/ActiveRecord/Store.html

    基本上你可以这样写:

    class Server < ActiveRecord::Base
      store :options
    end
    

    您还需要使用选项列创建新迁移并键入文本。

    现在您可以像这样向“选项”存储添加和读取值:

    server_instance.options[:ip] = '10.0.1.7'
    server_instance.options[:ip] # returns the IP.
    

    您还可以通过在 store 调用中添加访问器选项来清除它。

    class Server < ActiveRecord::Base
      store :options, accessors: [ :ip, :port ]
    end
    

    现在您可以将 ip 和端口用作常规属性。

    server_instance.ip = '10.0.1.7'
    server_instance.ip # returns the IP.
    

    【讨论】:

    • 我忘了在我的问题中提到......我试图远离这个项目的 Rails 数据库,所以我没有使用“
    • 您确实应该提到您没有在问题中使用任何与 activerecord 相关的内容,并且您正在尝试创建一个必须与文件中包含的设置进行交互的类。我的方法是创建一个接受文件的类。然后它读取所有设置并将它们存储在哈希中。这个散列需要拦截设置器([]= 我认为)并将其存储到文件中,并将其存储在散列中。然后,作为语法糖,您可以将 method_missing 添加到类中,这样当您执行 server_1.ip 时,它会检查哈希中的 IP 设置。
    【解决方案2】:

    为你做了点什么。

    这是它的工作原理。

    s = Settings.new(SettingsFileManager.new(some_file))
    
    s.ip # returns whats in the file.
    s.ip = 10.0.0.1 # overrides the new value.
    

    我还没有写出它与文件交互的方式,所以你必须写一个合适的 SettingsFileManager。

    如果有的话,它应该为您提供良好的入门基础。但我写它主要是为了测试我对 ruby​​ 的了解。因为它使用了一些半棘手的东西。

    通过一些测试也将其托管在github

    class Settings
    
      attr_accessor :settings
    
      def initialize(file_writer)
        @file_writer = file_writer
        read_settings_to_new_hash
      end
    
      def read_settings_to_new_hash
        @settings = fabricate_hash
        @settings.replace(@file_writer.read_keys)
      end
    
      def fabricate_hash
        InterceptedHash.new( &hash_saved_proc )
      end
    
      def hash_saved_proc
        Proc.new do |key, value|
          @file_writer.write_key(key, value)
        end
      end
    
      def method_missing(m, *args, &block)
        if @settings.has_key?(m) || args[0]
          if args[0]
            @settings[m.to_s.sub("=","").to_sym] = args[0]
          else
            @settings[m]
          end
        else
          raise "unknown setting"
        end
      end
    
    end
    
    # Not implemented. This should continue the logic to interact with whatever you want.
    class SettingsFileManager
      def initialize(file)
        @file = file
      end
    
      # write the key and its value somewhere.
      def write_key(key, value)
        puts 'write_key', key, value
      end
    
      # should return hash of keys.
      def read_keys
        puts 'read_keys'
        Hash.new
      end
    end
    
    class InterceptedHash < Hash
      def initialize(&block)
        super
        @block = block
      end
    
      def store(key, value)
        super(key, value)
        @block.call(key, value)
      end
    
      def []=(key, value)
        store(key, value)
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2013-12-09
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多