Does rails cache static pages and assets automatically? - ruby-on-rails

I have been reading about caching and all the resources available out there, but I am just not sure if I need to use 3rd party add-ons like Memcachier in my app. Other than the front pages (Static Pages like Homepage, About, Contact Us, Terms, Privacy) all other pages require authentication and are all dynamically created. It's a small social networking app so the show page, index page, edit page are all dynamically created. The index action is constantly going to be updated.
I want to know if Rails will automatically cache my static pages and assets such as css, javascript, images? What kind of caching should I be using?

If what you call static page are HTML files located in your public folder, they are directly served by your web server (ex: Apache), and the request don't even go through Rails
If they are files located in your app/views controller, the request goes through Rails, and it could be a good idea to implement page or fragment caching. Know that you can cache just parts of the pages, this is called fragment caching, and it's useful for dynamic pages that have static parts.
Also, you can link a cache to a record, so first time the view related to this record is displayed, the cache is generated and used for the next requests. Then when you modify this record the cache is invalidated and the process start over.
You don't need cache for your assets, they are compiles and not interpreted by Rails anymore in your production environment.
There is so many things about caching, and you can do a lot of good to your application with it (or a lot of bad is used incorrectly) and I cannot cover it all, let me give you some pointers that will teach you a lot:
http://railscasts.com/episodes/387-cache-digests
http://railscasts.com/episodes/169-dynamic-page-caching
http://railscasts.com/episodes/93-action-caching
http://railscasts.com/episodes/90-fragment-caching
http://railscasts.com/episodes/89-page-caching

Related

How to use a Rails form with a CDN?

We are interested in using a CDN (like Cloudflare) for our Rails 4 site (on Heroku), which has a form. Is it possible for the CDN to cache the form?
Each time a Rails form is rendered, it should have a unique authenticity token. So does that preclude it from being cached by a CDN? Are there any ways to make it work with a CDN?
CloudFlare caches by file extensions by default
If you're trying to cache something like yoursite.com/form, then you probably want to look at using PageRules to cache the actual page.
Note: I would recommend using caution if you use something like cache everything. You probably want to avoid having cached content intended for one user displayed to another user.

Does Rails re-compile the whole erb/haml view every time some hits it in production?

Say the view is in erb/haml, but is static (doesn't have any dynamic parts within it), does Rails recompile that view every time someone hits it, or does it cache the html after someone hits it once?
A follow up question: if I have a view with some dynamic parts, does Rails recompile only the dynamic part of the view or does it recompile the whole page?
I'm running Rails 4.
Rails evaluates view files and partials on every request. That is why html fragment caching is so valuable.
See Caching with Rails in Rails Guides.
Typically you would use Rails' cache to cache a html fragment so it does not need to be re-rendered on each request. Here's a Haml example:
- cache "key-name-for-static-content" do
.some-html
some content
See DHH's How Key-Based Cache Expiration Works for key-based caching using models.
For advanced uses, I wrote cache_rocket to help cache static content around dynamic content in partials.
Just a bit of terminology note: now compile is commonly referring to the act of turning the view template into a ruby function. Rails does this for all views:
http://guides.rubyonrails.org/action_view_overview.html#template-caching
Those functions will then output the output you want.
So I would say views are not "re-compiled" but "re-evaluated".

Performance strategy for site that is mostly static

I am taking over development on a rails 3.2 application and am looking for the best way to improve page loading time. The site itself is more of a large dynamic website than an actual web application (the site is http://korduroy.tv/, a surf lifestyle community site), and while there is a couple of small pieces that differ from user to user, most of the site is the same experience for everyone.
Page loading time is fairly slow, and from looking at the server logs, it seems to be because each page is loading so much dynamic content (for example, most pages are loading resources from 10+ models). While I hope to go through and refactor what I can, I am looking for some basic performance wins. Knowing that most of the site is the same for every user, is their a way to aggressively cache the content on the server or even serve static content that has been generated through some kind of background job?
My initial thought was to create a job that uses a static site generator, maybe something like Jekyl, and basically creates a static copy of the site, which could then be served on a cdn. My gut is telling me this is probably not the way to do it, plus there are some pages (such as the user profile page), that need to be served dynamically.
Any recommendations would be great. Disclaimer, I come from front end land and have very little knowledge of best practices when it comes to server side optimizations. Thanks!
From what you write, I believe your biggest gain will be in implementing a fragment cache using a memcache store. See http://guides.rubyonrails.org/caching_with_rails.html as the definitive guide on rails caching.
You might be able to get away with a page cache or action caches for some of the content that doesn't depend on the user (like the homepage), but unless you're serving up millions of requests a day, I'm not sure this is necessary.
I notice that while the javascript and css seems to be compiled according to the rails asset pipeline, the images are missing the sha1 hashes that allow aggressive browser caching of the resources (since you don't have to worry about the contents changing, as they get new hashes when you change the images). The key here is enabling the asset pipeline, making sure you compile your assets as part of deployment (rake assets:precompile) and using the image_tag and asset_path helpers (or image-url sass helper). Also make sure that nginx is responding with code 304 (not modified) to your browser when you're refreshing a page. This won't affect the load on the rails server (unless you have both nginx and rails running on the same server), but will reduce the average page load time.
You can look into more advanced techniques like caching your sql queries, or optimizing these, but this can lead to increased complexity making it harder to maintain your codebase. Try the view caching first, and see if that gets the load time to an acceptable level.

How do I deploy sproutcore using a CDN into an existing site?

I'm just learning about SproutCore now, seems great. But I can't find a good answer on deployment options.
I'm starting small. Just implementing a single page of a complex site with SproutCore. Right now, that page is dynamically generated and served from my django based server. I serve all of my static files (.js, .css, images, etc) off of a CDN.
The page represents one customer.
So, on that dynamic page, it knows:
What customer we should be looking at, the ID, name, etc.
Where my media should be loaded from (absolute HTTP path)
How do I get a SproutCore based app to deploy and run in an environment like this?
I imagine I can upload the built sproutcore app to my CDN. Then in my html page, somehow reference it. But how does that SproutCore app know what server to request backend data from (I'd rather not hard code it)? It can't be installed in the root of the CDN, so how does it know how to load things relative to itself? I could tell it an absolute URL to load from at run time. With some pain, I could even tell it an absolute URL to load from at build time.
No answers on this one, here's what I did...
Ended up moving to Ember.js (aka SproutCore 2). That follows a completely normal "add .js to a page and serve it normally" model and doesn't have any interesting deployment worries, so it's a no-brainer.

Rails page caching with intra-page administration

I'd love to use page caching on a Rails site I run. The information on each page is mostly constant, but the queries that need to be run to collect the information are complicated and can be slow in some cases.The only obstacle to using page caching is that the administrative interface is built into the main site so that admin operations can be performed without leaving the page of interest.
I'm using Apache+mod_rails (Passenger). Is there a way to indicate to Apache that .html files should be ignored when the current user either has a session variable or a cookie named 'admin'*? The session variable need not be evaluated by Apache for validity (since it will be evaluated by Rails in this case).
Is there a way to indicate to Apache that .html files should be ignored when the current user either has a session variable or a cookie named 'admin'*?
I believe it is not really possible. Even if it is, I guess should be very tricky.
Instead you can use Action Caching. A quote from docs:
One of the issues with page caching is
that you cannot use it for pages that
require checking code to determine
whether the user should be permitted
access.
This sounds like exactly your case.
But if you still really need Page Caching via web server, I think you better implement separate pages for admin and non-admin.
This is because of one reason. When you enable Page Caching rails doesn't process the request at all and thus there is no way to know if user is authenticated or not.
You probably can overcome this using Dynamic Page Caching. The idea is basically to add the "admin" part from the JavaScript. I don't personally like this a lot though.
One more update: quick search brought me to this article.
The idea is to cache page conditionally and plug mod_rewrite to serve admin pages.
Will work for you but is pretty dirty solution.

Resources