Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DRY'er Object Initialization in Ruby

Is there a more 'DRY' way to do the following in ruby?

#!/usr/bin/env ruby

class Volume
    attr_accessor :name, :size, :type, :owner, :date_created, :date_modified, :iscsi_target, :iscsi_portal

    SYSTEM = 0
    DATA = 1

    def initialize(args={:type => SYSTEM})
      @name = args[:name]
      @size = args[:size]
      @type = args[:type]
      @owner = args[:owner]
      @iscsi_target = args[:iscsi_target]
      @iscsi_portal = args[:iscsi_portal]
    end

    def inspect
      return {:name => @name,
              :size => @size,
              :type => @type,
              :owner => @owner,
              :date_created => @date_created,
              :date_modified => @date_modified,
              :iscsi_target => @iscsi_target,
              :iscsi_portal => @iscsi_portal }
    end

    def to_json
      self.inspect.to_json
    end

end

like image 962
Trevor O Avatar asked Jun 11 '09 18:06

Trevor O


People also ask

What does .NEW do in Ruby?

new is a class method, which generally creates an instance of the class (this deals with the tricky stuff like allocating memory that Ruby shields you from so you don't have to get too dirty). Then, initialize , an instance method, tells the object to set its internal state up according to the parameters requested.

What is def initialize?

verb. ini·​tial·​ize i-ˈni-shə-ˌlīz. initialized; initializing. transitive verb. : to set (something, such as a computer program counter) to a starting position, value, or configuration.

How do you initialize a class variable in Ruby?

Ruby Class VariablesClass variables begin with @@ and must be initialized before they can be used in method definitions. Referencing an uninitialized class variable produces an error. Class variables are shared among descendants of the class or module in which the class variables are defined.


2 Answers

Whenever you see a long list of things like that, usually you can roll it all up into a singular Array:

class Volume
  ATTRIBUTES = [
    :name, :size, :type, :owner, :date_created, :date_modified,
    :iscsi_target, :iscsi_portal
  ].freeze

  ATTRIBUTES.each do |attr|
    attr_accessor attr
  end

  SYSTEM = 0
  DATA = 1

  DEFAULTS = {
    :type => SYSTEM
  }.freeze

  def initialize(args = nil)
    # EDIT
    # args = args ? DEFAULTS : DEFAULTS.merge(args) # Original
    args = args ? DEFAULTS.merge(args) : DEFAULTS

    ATTRIBUTES.each do |attr|
      if (args.key?(attr))
        instance_variable_set("@#{attr}", args[attr])
      end
    end
  end

  def inspect
    ATTRIBUTES.inject({ }) do |h, attr|
      h[attr] = instance_variable_get("@#{attr}")
      h
    end
  end

  def to_json
    self.inspect.to_json
  end
end

Manipulating instance variables is pretty straightforward after that.

like image 193
tadman Avatar answered Sep 23 '22 03:09

tadman


 class Volume

  FIELDS = %w( name size type owner iscsi_target iscsi_portal date_create date_modified)
  SYSTEM = 0
  DATA = 1
  attr_accessor *FIELDS

  def initialize( args= { :type => SYSTEM } )
    args.each_pair do | key, value |
      self.send("#{key}=", value) if self.respond_to?("#{key}=")
    end
  end

  def inspect
    FIELDS.inject({}) do | hash, field |
      hash.merge( field.to_sym => self.send(field) )
    end.inspect
  end

 end
like image 27
Subba Rao Avatar answered Sep 23 '22 03:09

Subba Rao