Skip to content

Instantly share code, notes, and snippets.

@fj
Created May 7, 2012 18:41
Show Gist options
  • Save fj/2629588 to your computer and use it in GitHub Desktop.
Save fj/2629588 to your computer and use it in GitHub Desktop.
Dynamic CSS in Rails 3.2

You operate a terrible clone of about.me called my.name. The entire purpose of the site is to show a user's name with some limited styling customization.

You allow users to configure a small number of parameters -- say, background color, font size, and some other properties -- and you store this information with each user.

When a request is made for my.name/123, you look up the user with id 123 and show that name in the middle of the page. The customized styling associated with each user is in the form of a CSS file that looks like styles.css?user_id=123. The CSS served is the same for any page; only the values for a few of the fields will be different for a given user_id.

You're using Rails 3.2 and Compass, so you want styles.css to actually be a dynamic file that generates an asset in the pipeline and which can be easily cached (so that you're not constantly recomputing styles.css?user_id=... for a given user).

What do you do?

@btaitelb
Copy link

btaitelb commented May 7, 2012

One idea would be to have app/views/styles/user.scss.erb along with a StylesController that serves up that file.

I would suggest avoiding app/assets, since the default is to evaluate the erb during assets:precompile, so you'd need to have some special configuration and routes to serve up a file from there at runtime (which would only confuse devs who understand the pipeline).

@fj
Copy link
Author

fj commented May 7, 2012

@phillipkoebbe: I'm not sure I like the "it's really a file" approach because that's not portable (you can no longer just deploy and have it work, since you'd also need to remember the files, and you definitely don't want those in source control) and it requires you to consider a special case ("has the file been generated yet?"). But it's definitely expedient! Thanks for the suggestion.

@btaitelb: The controller approach seems like the way to go and is the one I'm most strongly considering. It nevertheless feels like a bit of a hack to me because now I have CSS that lives under styles instead of, e.g., public/assets/... or what have you.

@deathbob
Copy link

deathbob commented May 7, 2012

Yeah, done something similar in the past and did exactly what btaitelb suggests.

In our case the same app was serving multiple domains so we were switching stuff out on domain, not user, but same idea. HTML on the page was the same, the css was different and generated by request. In our case it was easy to cache since anybody who visited that domain name got the same css.

If I was switching on user instead of domain I think maybe I'd pull the css in with javascript or, if you didn't want the page to look wonky for .1 seconds, i guess actually include it inline :)

Altho if you switch on user maybe should change name of file instead of using query string, to ease caching?

@phillipkoebbe
Copy link

@fj Having external files to worry about is a pain. Been there, done that, don't want the book. In this case, however, since they are dynamically generated to begin with, I'd just make it part of the deployment process by creating a rake task and calling it from Capistrano.

I'm not sure how significant the special case is. You already have the special case of "Does this user have any customizations to consider?", so slight changes in the perspective of how you approach the special case might be negligible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment