# Statistics table via a trigger

**URL:** <https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916>\
**Category:** Rails\
**Created:** [October 1, 2008, 6:13am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916 "2008-10-01T06:13:57Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 1, 2008, 6:13am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/1 "2008-10-01T06:13:57Z")

</div>

I’m trying to implement something similar to a historical price chart,  
where I save the prices when they change to a “stats” table.

I’d like to take the current value and save it to a statistics model  
before it gets updated with the new value.

Is there a way to do it with a trigger or should I just save the value  
in two different models?

Something like this:

@book = Book.find(params[:id])  
@stats = Stat.new()

puts @book.price #=\> $10.00

@stats.book\_id = @book.id  
@stats.price = @book.price

@book.price = $20.00

@book.save()  
@stats.save()

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 1, 2008, 4:06pm UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/2 "2008-10-01T16:06:26Z")

</div>

On Tue, Sep 30, 2008 at 9:13 PM, Anthony E.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Something like this:  
> @book.price = $20.00
> 
> @book.save()  
> @stats.save()

Anthony,

Is Book the only model that you’ll be doing this for? …or are there  
other models that will use this historical log of prices?

There’s a few options here. One, you could add method to be called by  
after\_save to check the price previously stored with the new one… if  
they are different… add a new entry to the historical log.

Another option is to not store prices in the Book model and only in  
another table called something like BookPrice.

book has\_many book\_prices

Then you can scope book\_prices for current to do something like:

book.book\_prices.current.price # =\> get the current price

book.book\_prices.each { |book\_price| … } # =\> iterate through all  
book prices

Anyhow, there’s a few options to throw your way. Good luck!

Cheers,  
Robby

–  
Robby R.  
Chief Evangelist, Partner

PLANET ARGON, LLC  
design // development // hosting

> **[Planet Argon](https://www.planetargon.com/)**
>
> Planet Argon is a Ruby on Rails development agency specializing in maintenance and support for existing Rails apps. Based in Portland, OR, Planet Argon has been a member of the Rails community since 2004.

[http://www.robbyonrails.com/](http://www.robbyonrails.com/)  
aim: planetargon

+1 503 445 2457  
+1 877 55 ARGON [toll free]  
+1 815 642 4068 [fax]

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 2, 2008, 12:30am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/3 "2008-10-02T00:30:32Z")

</div>

Book having many :prices does make sense. That way you get to keep  
the history of the price of the book. Of course, the latest price in  
the association is the current price.

Ramon T.

On Thu, Oct 2, 2008 at 2:05 AM, Anthony E.

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 2, 2008, 1:01am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/4 "2008-10-02T01:01:28Z")

</div>

Ramon T. wrote:

> Book having many :prices does make sense. That way you get to keep  
> the history of the price of the book. Of course, the latest price in  
> the association is the current price.
> 
> Ramon T.

The problem with that is to get the current price (most uses cases) I  
have to scan the entire ‘prices’ table.

I’d rather do it in such a way that it only saves the current price,  
year, edition, etc. to a “stats” whenever the book is updated (without  
any explicit association).

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 1, 2008, 8:05pm UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/5 "2008-10-01T20:05:44Z")

</div>

Robby R. wrote:

> On Tue, Sep 30, 2008 at 9:13 PM, Anthony E.  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > Something like this:  
> > @book.price = $20.00
> > 
> > @book.save()  
> > @stats.save()
> 
> Anthony,
> 
> Is Book the only model that you’ll be doing this for? …or are there  
> other models that will use this historical log of prices?
> 
> There’s a few options here. One, you could add method to be called by  
> after\_save to check the price previously stored with the new one… if  
> they are different… add a new entry to the historical log.
> 
> Another option is to not store prices in the Book model and only in  
> another table called something like BookPrice.
> 
> book has\_many book\_prices
> 
> Then you can scope book\_prices for current to do something like:
> 
> book.book\_prices.current.price # =\> get the current price
> 
> book.book\_prices.each { |book\_price| … } # =\> iterate through all  
> book prices
> 
> Anyhow, there’s a few options to throw your way. Good luck!
> 
> Cheers,  
> Robby

Thanks Robby.

I will be doing this for one model for now, perhaps others down the  
road.

The “Book” model has numeric attributes that I want to save into a  
“statistics” table so I can draw a line-graph over time from it.

Other attributes would be archived as well.

Its sounds to be a before\_update would give me access to the current  
price. And I don’t want to keep the current price in a stats table  
because that table will eventually grow and slow down the regular query.

## book

id  
title  
price  
edition  
year

## stats

id  
book\_id  
price  
edition  
year  
created\_at  
updated\_at

Ideally sans-rails the stats table would be populated with a trigger  
when the book table is updated.

There book will definitely “has\_many :stats” but I don’t really want  
that association to be queried every time I get a regular book object,  
only when I build the stats page.

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 2, 2008, 1:20am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/6 "2008-10-02T01:20:16Z")

</div>

On Wed, Oct 1, 2008 at 4:01 PM, Anthony E.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> have to scan the entire ‘prices’ table.

_sniff_ I smell premature optimization. 😉

Seriously, with database indexes… this is doubtful to be an issue.  
If it’s ever an issue you can cache the current price in the book  
model, but really… I wouldn’t be concerned about that for a while.

> I’d rather do it in such a way that it only saves the current price,  
> year, edition, etc. to a “stats” whenever the book is updated (without  
> any explicit association).

This is the case either way. Just not convinced you need to cache this  
in the Book model from the get-go, which is what you’re leaning  
toward.

Cheers,  
Robby

–  
Robby R.  
Chief Evangelist, Partner

PLANET ARGON, LLC  
design // development // hosting

> **[Planet Argon](https://www.planetargon.com/)**
>
> Planet Argon is a Ruby on Rails development agency specializing in maintenance and support for existing Rails apps. Based in Portland, OR, Planet Argon has been a member of the Rails community since 2004.

[http://www.robbyonrails.com/](http://www.robbyonrails.com/)  
aim: planetargon

+1 503 445 2457  
+1 877 55 ARGON [toll free]  
+1 815 642 4068 [fax]

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 3, 2008, 11:28am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/7 "2008-10-03T11:28:00Z")

</div>

Anthony E. wrote:

> Robby R. wrote:
> 
> > On Wed, Oct 1, 2008 at 4:01 PM, Anthony E.  
> > [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> > 
> > > have to scan the entire ‘prices’ table.
> > 
> > _sniff_ I smell premature optimization. 😉
> > 
> > Seriously, with database indexes… this is doubtful to be an issue.  
> > If it’s ever an issue you can cache the current price in the book  
> > model, but really… I wouldn’t be concerned about that for a while.
> > 
> > > I’d rather do it in such a way that it only saves the current price,  
> > > year, edition, etc. to a “stats” whenever the book is updated (without  
> > > any explicit association).
> > 
> > This is the case either way. Just not convinced you need to cache this  
> > in the Book model from the get-go, which is what you’re leaning  
> > toward.
> 
> Thanks Robby, you may indeed be correct.
> 
> Is it safe to say your recommendation is to create a model for each  
> statistical attribute I want to archive?
> 
> ie:  
> Price  
> Year  
> Edition
> 
> …and associate them to the Book via: has\_many and then use the most  
> recent as the current price?

I can’t get the save to work across the association. The price is coming  
from a backend system un-related to rails so I have got the data itself  
no problem with “get\_price” and saving it to self.price is fine…but I  
can’t refactor this into saving to another model (ie: prices)

Book \< ActiveRecord::Base  
has\_many :prices  
before\_save :get\_price  
after\_save :set\_price

def get\_price  
price = Legacy::Data.new().price  
end

At this point my understanding breaks down…how do I save that  
“get\_price” value to the “Prices” model?

#brokenzy

def set\_price  
@price = self.prices.new  
@price.price = self.price  
end

---

<div class="post-metadata">

**Author:** ![chovy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/ecd19e/32.png) [@chovy](https://www.ruby-forum.com/u/chovy)\
**Post date:** [October 2, 2008, 2:45am UTC](https://www.ruby-forum.com/t/statistics-table-via-a-trigger/149916/8 "2008-10-02T02:45:39Z")

</div>

Robby R. wrote:

> On Wed, Oct 1, 2008 at 4:01 PM, Anthony E.  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > have to scan the entire ‘prices’ table.
> 
> _sniff_ I smell premature optimization. 😉
> 
> Seriously, with database indexes… this is doubtful to be an issue.  
> If it’s ever an issue you can cache the current price in the book  
> model, but really… I wouldn’t be concerned about that for a while.
> 
> > I’d rather do it in such a way that it only saves the current price,  
> > year, edition, etc. to a “stats” whenever the book is updated (without  
> > any explicit association).
> 
> This is the case either way. Just not convinced you need to cache this  
> in the Book model from the get-go, which is what you’re leaning  
> toward.

Thanks Robby, you may indeed be correct.

Is it safe to say your recommendation is to create a model for each  
statistical attribute I want to archive?

ie:  
Price  
Year  
Edition

…and associate them to the Book via: has\_many and then use the most  
recent as the current price?
