CultivateLabs / storytime

Storytime is a Rails 4+ CMS and blogging engine, with a core focus on content. It is built and maintained by @cultivatelabs
MIT License
752 stars 81 forks source link

Snippets for a single page should all be loaded through a single query #58

Open bcroesch opened 9 years ago

bcroesch commented 9 years ago

Chris Morris commented on http://www.flyoverworks.com/2014/11/29/re-thinking-cms-backed-pages-with-storytime-s-text-snippets:

I took the liberty of looking up the snippet method from Storytime. Depending on how much you're using this, you're potentially hitting your database any number of times to load the page content.

  def snippet(name)
    snippet = Storytime::Snippet.find_by(name: name)
    snippet.nil? ? "" : snippet.content.html_safe
  end

In the past, I have added an attribute to such a Snippet model containing an identifier for which page particular content belongs so that I can add scopes to the Snippet model to pull all the Snippets for a given page. So, now you can do:

@landing_page_snippets = Snippet.landing_page

Then I would put something like the following in the controller:

@landing_page_snippets.each_with_index { |record, value| instance_variable_set("@#{record.key}", value) }

This will generate instance variables equal to each record's key attribute which would be set like "header-text", "sub-header-text", "explaination-copy", etc. Now, in the view you can refer to the individual snippets like:

@landing_page_snippets[@header-text].content
@landing_page_snippets[@sub-header-text].content
@landing_page_snippets[@explaination-copy].content

This is because @header-text will be instantiated as a Fixnum equal to the position of the record in the ActiveRecord::Relation thereby allowing you to pull them all at once with one query instead of an n+1 affair and refer to them individually in the view template markup.

bcroesch commented 9 years ago

Would be nice to pull all snippets for a page in one query. To do that, we probably need a join table between pages and snippets. Then we'd also need to do a multi-select on the snippet creation page to indicate which pages the snippet will appear on.