Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class static instance initializers (i.e. factory methods) in Ruby

I have a class that I want to put factory methods on to spit out a new instance based on one of two construction methods: either it can be constructed from data in memory, or data stored in a file.

What I would like to do is to encapsulate the logic of how the construction is performed inside the class, so I would like to have static class methods that are set up like this:

class MyAppModel
    def initialize
        #Absolutely nothing here - instances are not constructed externally with MyAppModel.new
    end

    def self.construct_from_some_other_object otherObject
        inst = MyAppModel.new
        inst.instance_variable_set("@some_non_published_var", otherObject.foo)
        return inst
    end

    def self.construct_from_file file
        inst = MyAppModel.new
        inst.instance_variable_set("@some_non_published_var", get_it_from_file(file))
        return inst
    end
end

Is there no way to set @some_private_var on an instance of a class from the class itself without resorting to metaprogramming (instance_variable_set)? It seems like this pattern is not so esoteric as to require meta-poking variables into instances. I really don't intend to allow any class outside of MyAppModel to have access to some_published_var, so I don't want to use e.g. attr_accessor - it just feels like I'm missing something...

like image 702
Matt Avatar asked Feb 09 '11 21:02

Matt


1 Answers

Maybe using a constructor is the better way to achieve what you want, just make it protected if you don't want to create instances from the "outside"

class MyAppModel
  class << self
    # ensure that your constructor can't be called from the outside
    protected :new

    def construct_from_some_other_object(other_object)
      new(other_object.foo)
    end

    def construct_from_file(file)
      new(get_it_from_file(file))
    end
  end

  def initialize(my_var)
    @my_var = my_var
  end
end
like image 188
Holin Avatar answered Oct 03 '22 02:10

Holin