Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails - Caching Variables

I have these two variables being set in the controller. How do I cache these so they don't communicate with the database each time, only the first time.

@tablenutrients = Nutrient.find(:all)
@columnnutrients = @tablenutrients.collect {|x| x.nutrient}
like image 539
San Backups Avatar asked Oct 04 '12 00:10

San Backups


3 Answers

what @djlumley said.

In general, you can also configure and use ActiveSupport::Cache::Store to explicitly store your own custom variables. You could then get/set cached values, for example, like this:

@tablenutrients = Rails.cache.fetch("tablenutrients") do 
  Nutrient.find(:all)
end
like image 140
pje Avatar answered Nov 10 '22 00:11

pje


If your database is setup correctly, it should be caching your data by default. If you're using MySQL or postgresql you can change the amoutn of RAM the cache uses to ensure you're getting a high cache hit rate.

Beyond simple database caching, using something like Dalli to connect to memcached should make improving performance fairly easy.

Rails should take advantage of memcached to cache all your active record queries in memcached provided it's setup correctly. The Rails guide on caching together with the Dalli documentation should help you get started based on the version of Rails you're running.

like image 41
djlumley Avatar answered Nov 09 '22 23:11

djlumley


Rails has a few built in caching options for you, two of which would likely work for you, depending on what you're doing with the query result:

Fragment Caching

If you were using this as a collection for a select box an often used form I would go with this option. This would allow you to cache not only the database result, but the actual HTML section of the page . This is done simply by throwing a <%= cache do %> around the section, like so:

<html>
   ...
   <body>
     ...
     <div class='content'>
       ...
       <%= cache do %>
         <%= select "nutrient", "nutrient", Nutrient.all.collect(&:nutrient) } %>
       <% end %>

Rail.cache

You could also write a method to talk directly to the built in cache store, by dropping a method in your ApplicationController and then have it run on a before_filter callback like so:

application_controller.rb

class ApplicationController < ActionController::Base
  before_filter :retrieve_nutrients

  def retrieve_nutrients
    @nutrients = Rails.cache.fetch("nutrients") do
      Nutrient.all.collect(&:nutrient)
    end
  end
end

In both cases in a production environment you're going to want to setup either Memcached or Redis to act as a caching layer (they sit behind Rails.cache and are a snap to implement). I would checkout Rails Guides for a deeper look at it.

like image 42
jonkgrimes Avatar answered Nov 09 '22 22:11

jonkgrimes