Ruby最佳实践 - 动态属性与Hash for RoR应用程序

时间:2012-03-09 14:45:29

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

我正在开发一个包含服务器选项配置设置的模型。服务器选项的数量和类型发生了变化,我需要对两种方法的优缺点进行一些输入。 我这是从rails ActiveRecord数据库中分离出来的。我的所有数据库交互都将通过文件系统手动完成。

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

其次,创建一个Hash,它具有服务器选项的键和服务器设置的值。

我认为第二种更容易实现,但我不确定它是否是正确的方法?使用动态属性似乎更清晰。

这是否有经验法则?

2 个答案:

答案 0 :(得分:4)

您知道Rails中的商店功能吗?

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

基本上你可以这样写:

class Server < ActiveRecord::Base
  store :options
end

您还需要创建一个新的迁移以及选项列和文本类型。

现在您可以像这样添加和读取'options'商店的值:

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

您还可以通过向商店调用添加访问者选项来清理它。

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

现在你可以使用ip&amp; port作为常规属性。

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

答案 1 :(得分:1)

为你做点什么。

以下是它的工作方式。

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。

如果有的话,它应该为你提供一个良好的入门基础。但我写它主要是为了看看我对红宝石的了解。因为它使用了一些半棘手的东西。

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