I have a situation, where I want to add many classes as instance variables of another class, plus perform some action on each class. The purpose is to have an 'app' with many 'views', to represent PageObjects
.For instance:
class App
attr_reader :login_view, :list_view, :create_view
def initialize
action([LoginView,ListView,CreateView])
@login_view = LoginView.new
@list_view = ListView.new
@create_view = Create_view.new
end
end
# App.new.login_view => [LoginView]
I came up with a solution which works:
module ClassToVar
def create_instances_for(views)
Array(views).each { |clazz| create_instance_for(clazz) }
end
private
def create_instance_for(clazz)
class_name = to_camel_case(clazz)
variable_name = '@' + class_name
instance_variable_set(variable_name, clazz.new)
self.class.class_eval { attr_reader class_name.to_sym }
end
# *This could be done useing ActiveSupport, but I preferred to add it here*
def to_camel_case(class_name)
demodulize(class_name).gsub(/::/, '/')
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
.gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-", "_").downcase
end
def demodulize(class_name)
class_name.to_s.split('::').last
end
end
# class App include ClassToVar
# def initialize
# create_instances_for([ListView, LoginView, CreateView])
# end
#
I think there has to be a different way to solve it: Either a simpler way, or a different design, so I don't need to take this approach.
Any advice?
to_snake_case
. I won't edit it, so the original code is there. As I commented, I did not want to require active support. \$\endgroup\$