Reputation: 801
I'm new to Ruby on Rails (just started using it a few days ago). I'm making a simple web frontend to display various system information, including S.M.A.R.T information. I've made this little class:
class SmartValues
attr_reader :data
KEYS = [:id, :name, :flag, :value, :worst, :thresh, :type, :updated, :failed, :raw]
def initialize(devices)
@data = Hash[devices.map {|dev| [dev, SmartValues.getValues(dev)]}]
end
def self.getValues(device)
lines = `sudo /usr/sbin/smartctl -A #{device}`.split("\n")[7..-1].collect! { |line| line.split }
return lines.map { |line| Hash[KEYS.zip line] }
end
end
It works fine, except that it's included into my controller like this:
class HomeController < ApplicationController
def index
@smart = SmartValues.new(["/dev/sda", "/dev/sdb", "/dev/sdc", "/dev/sdd", "/dev/sde", "/dev/sdf"]).data
end
end
So it must be that the smartctl binary is executed multiple times for each request of the page. I would like to add some kind of caching, so that the information is updated periodically, but not on every request. What's the right RoR-ish way of doing it?
Upvotes: 0
Views: 335
Reputation: 115511
def self.lines(device)
Rails.cache.fetch("#{device}_lines", :namespace => "smart_values", :expires_in => 15.minutes) do
`sudo /usr/sbin/smartctl -A #{device}`.split("\n")[7..-1].collect! { |line| line.split }
end
end
def self.getValues(device)
lines(device).map { |line| Hash[KEYS.zip line] }
end
Upvotes: 3