8

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...

1 Answer 1

11

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
Sign up to request clarification or add additional context in comments.

2 Comments

This is very nice and idiomatic.
Thanks, I think this is much cleaner than what I was doing - it still involves passing a bunch of stuff to the constructor, but since it's protected anyway, that's no big deal - and far better than instance_variable_set.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.