Mejores prácticas de Ruby: atributos dinámicos frente a Hash para la aplicación RoR

I'm developing a model which holds configuration settings for server options. The number and type of server options change, and I need some input on the pros/cons of two ways of doing it. I'm doing this separate from the rails ActiveRecord database. All my database interactions are going to be manually with the file system.

First, having the model dynamically create attributes as needed for each server specified. (as long as this is possible... I've never done it before)

Second, creating a single Hash, which has Keys of the server options, and values of the server settings.

I think the second would be easier to implement, but I'm not sure if it is the right way to go? It seems to be cleaner to go with dynamic attributes.

Is there a rule of thumb to go with for this?

preguntado el 09 de marzo de 12 a las 14:03

2 Respuestas

Do you know about the Store functionality in Rails?

Basically you could write something like this:

class Server < ActiveRecord::Base
  store :options

You need to create a new migration as well with an options column and type text.

Now you can add and read values to the 'options' store like so:

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

You can also clean this up by adding an accessors option to the store call.

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

Now you can use ip & port as regular attributes.

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

respondido 09 mar '12, 18:03

I forgot to mention in my question... I'm trying to stay away from the Rails database for this project, so I'm not using "< ActiveRecord". All of my interactions are directly with the file system - no database persistence. Otherwise, that looks like it would be exactly what I'd need! - Josh Johnson

You should really mention you are not using anything activerecord related in your question and that you are trying to create a class that has to interact with the settings contained in files. My approach would be to create a class which accepts a file. It then reads in all the settings and stores them in a hash. This hash needs to intercept the setter ([]= I think) and store it off to the file as well as storing it in the hash. Then, as syntactic sugar you can add method_missing to the class so that when you do server_1.ip it'll check for an IP setting in the hash. - SpoBo

Made something for you.

Así es como funcionaría.

s =

s.ip # returns whats in the file.
s.ip = # overrides the new value.

I haven't written the way it interacts with the files yet so you'll have to write a proper SettingsFileManager.

If anything it should give you a good base to get started. But I wrote it primarily as a test to see what I know about ruby. Since it uses some semi-tricky stuff.

Hosted it on gitHub too with some tests.

class Settings

  attr_accessor :settings

  def initialize(file_writer)
    @file_writer = file_writer

  def read_settings_to_new_hash
    @settings = fabricate_hash

  def fabricate_hash &hash_saved_proc )

  def hash_saved_proc do |key, value|
      @file_writer.write_key(key, value)

  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]
      raise "unknown setting"


# Not implemented. This should continue the logic to interact with whatever you want.
class SettingsFileManager
  def initialize(file)
    @file = file

  # write the key and its value somewhere.
  def write_key(key, value)
    puts 'write_key', key, value

  # should return hash of keys.
  def read_keys
    puts 'read_keys'

class InterceptedHash < Hash
  def initialize(&block)
    @block = block

  def store(key, value)
    super(key, value), value)

  def []=(key, value)
    store(key, value)

respondido 13 mar '12, 21:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.