I have a "virtual scratchpad" Rails app that has pages (analogous to a piece of scratch paper), and each page has_many :notes (analogous to the notes that you'd write on that paper).

I want to count the total pages and notes created over the lifetime of the app. I know all the advice about "never delete data" but in this case the app is literally designed to work like scratch paper. As a result, if a page hasn't been touched/updated in 30 days, the app automatically destroys it (like throwing away scratch paper).

For fun I'd like to track the total lifetime number of pages created, and the total lifetime notes created. Since my app, be design, will destroy data when it expires, I can't simply do Page.count and Note.count in order to get these stats. I need instead to increment a counter for each, and have that counter persisted forever.

My question this: my first inclination for how to implement this is to simply create a stats table with a column for each stat (e.g. lifetime_page_count, lifetime_note_count, etc.), and have that table contain only a single row since I will only have one set of statistics. It seems a little silly to create a table just to contain a single row, but is this considered okay for this kind of use? Is there a better model/pattern I should think about? My database is pretty simple as it is (literally just two tables - pages and notes), but that doesn't mean I want to be sloppy about the implementation just because I can.

share|improve this question
Let's see (and I do not know rails) ... if it has to be saved in the table, then these stats will not belong to either of the two tables that you created - that would be a waste of space and would violate some norm. If it belongs to some other table, then it depends on the number of stats. If you have a few of them, then a single row table makes sense. If you have more than 20, then you might want to grow the table down, not to the right, so then have a table that contains (stat_id, stat_mnemonic, stat_description, stat_type, stat_value) or split this table up. What about dynamic view instead? – Leonid May 27 '12 at 15:48

1 Answer

I wound up going with multiple rows, and a generic "stats" table. Based my design off a simplified version of acts_as_statistic

Each row is a single statistic. The table has the following columns:

  • group
  • name
  • value

So, a row in this might be [group: 'totals', name: 'pages', value: '212']

I then have a few convenience methods:

Stat.get_stat("totals", "pages")   => returns the associated record from the database
Stat.get_value("totals", "pages")  => returns the value in that Stat's value column
Stat.increment("totals", "pages")  => increments the value in the specified Stat

This has the advantage that I can add future stats anytime I want without a schema change. Since we're dealing with a few stats at a time (and this is a pretty low-traffic site), the load on the app/DB as measured in real-time is negligible.

share|improve this answer
+1 for anticipating the a change. – Leonid May 28 '12 at 2:47

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.