How to use a Rails form with a CDN? - ruby-on-rails

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.

Related

Does rails cache static pages and assets automatically?

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

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.

Pulling CSS assets (like background images) from the database in a Rails app?

I'm wondering if there's a way to store CSS asset paths, like background images, in the database so that they're customizable without accessing or rewriting the code. I've looked at some template engines, like liquid, but think they're a overkill for what I want to do. I only want a tiny bit of customization in my views between various deployments of the same app codebase, not anything for various users.
I've not looked much at Rails 3.1, but from what I understand the CSS assets are compiled and aren't static any longer, so -- does that mean I can write something like that into my CSS in rails 3.1 that pulls from the database? I usually deploy to Heroku and aren't sure if they're supporting 3.1 yet.
Anyone have any better strategies or ideas?
Storing binary files like images in the database can quickly become cumbersome. There was a time when we were storing user uploads like PDF's and such in the DB but it became unmanageable. We quickly moved it all over to S3 and made Paperclip store and retrieve the files there (encrypting the files before saving them to S3, and sending them over SSL since the files were potentially sensitive) and it made things much saner.
I'd say best bet for you is to use S3. Since
On heroku you have a limited
database size (depending on your
plan) and could quickly run out if
you're storing binaries there.
You can't dynamically save new files
to the filesystem on heroku, and
S3 is cheap as hell (and free for
most casual use) to store and
retrieve files.
EDIT based on your comment:
Ok I mis-understood the question. Either store the image path in the database or have the image stored with such a path & naming convention that the code itself can figure out where to get the image (which is what paperclip does). Both ways are acceptable. NOTE that SASS is not truly dynamic, you can't pull paths from the database and make the sass change on-the-fly. I've run into a similar situation and the solution was to make the CSS point to a background-image that was in fact a route in the application. In our instance we were able to change the image displayed based on the subdomain or domain of the incoming user, but you could just as easily display that image based on a session cookie that gets set before the views are rendered.
While SASS is compiled, after it's been generated it is static. The syntax, and 'dynamic' nature of it are just to make writing CSS easier.
What about using something like S3(Paperclip) + a "css assets" table/model?
That way in an "admin" page you can pull all of the possible CSS assets, allow someone to select a new one or even upload a new image to s3. This means you wouldn't have to actually rewrite any code just have an admin portal where they can select possible images.

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.

How do I cache subdomain-specific views in Rails?

Our Rails app has some views that get heavy traffic but don't change too often (weekly at the most). I want to cache these views but we use subdomains to specify user accounts.
I've seen a few different blog posts on how to cache views based on subdomains. Just wondering what the preferred method is.
Also, one of the pages we need to cache is XML output. I don't know if that matters at all.
You just need to inject the things that change into your cache_key value when you cache. This may require using action caching instead of page caching. It sounds like you would need to inject the user id or the subdomain id when you're generating the cache_key for your content.

Resources