Caching a method that's got conditional output

69 views Asked by At

I have a method with is used to render news articles on every page. If you aren't on a care home page then it won't render specific news to that home. It's quite a heavy thing to process on every single page request. I was wondering if anyone could come up with a good way of caching it.

def articles_to_show
  @articles = @care_home ? @care_home.news_items.latest.translated.limit(4).includes(:images) : Refinery::News::Item.latest.hidden_from_main.translated.limit(4).includes(:images)
end

Here's the view template - http://pastebin.com/BAmgSZia

I've tried fragment caching it, but then I realised every now and then if it expires and the first request is that of a care home, then the news articles will be populated incorrectly.

1

There are 1 answers

2
Leszek Andrukanis On

You have ugly code already so it wouldn't be very bad to make this code a little more obfuscated ...

@articles = lambda { YOUR_HEAVY_CODE }

Then in your view you're:

- cache do
  - @articles = @articles.call
  = #rest of the partial

Thing worth mentioning is that, if you can't use any embedded and suggested way of caching, it's probably something wrong with your design.

  1. Relating your action instance variable with other instance variable probably initialized in some filter is bad design example.

  2. #articles_to_show it's bad example of REST approach, you can instead do something like:

    class Articles::CollectionController with show method

  3. Don't use ternarny operator, probably at all, it's so obfuscated. ?: syntax is proper only for very easy statements.

  4. Don't place so much to the controller, try to delegate your methods, scopes by merging them into another method - it would be cleaner