Reputation: 12224
I have a class which reads the contents of three different files into class variables upon instantiation, like so:
class Catalog
class << self
def change_file_name
standard = Standard.where(klass_name: self.to_s).first
month = Date::ABBR_MONTHNAMES[standard.version_date.month]
year = standard.version_date.year
"#{Rails.root.to_s}/#{month}_#{year}_changed_products.csv"
end
def get_changes
changes = {}
begin
IO.foreach(change_file_name) do |line|
row = CSV.parse_line(line.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '').strip, { quote_char: '"' })
version = row.pop
changes[version] ||= {}
changes[version][row[1]] = row[3]
end
rescue => bang
raise "Error opening #{change_file_name}: #{bang.message}"
end
changes
end
end
class << self; attr_accessor :changes end
@changes ||= self.get_changes
end
Now I have finally reached critical mass in terms of the size of the file that is read in when this class is instantiated. I don't think I have set up the class variables correctly either.
When this class is called (not even instantiated, just constantized
it's taking upwards of 8 seconds. And after it's been constantized, it's fine for a while. But I guess it gets cleared out of memory, and it has to be loaded again. Which takes another 8 seconds to a minute.
Ideally, it would load once when my application starts, and that would be that. Is there a way to do that? I appreciate your help as this is a particular weakness of mine. I need this data readily available. But if this doesn't work, would it be better to put this code in an initializer and load the file into constants? Thank you kindly for your help.
Upvotes: 0
Views: 60
Reputation: 426
You can use a class variable (tagged with @@) to store data at a class level.
Moreover, you can apply the singleton pattern to your Catalog (https://en.wikipedia.org/wiki/Singleton_pattern).
As you said you have a lot of data, the second option is a better one.
Upvotes: 1