Acts As Popular
Acts As Popular makes models know about popularity and the way it is updated between their records.
Example
Let’s take models Product and Tag. Every product has a popularity field that is recorded in some way from the users. We want to make a tag cloud with tags bigger if they have more popular products associated. We just have to add a few lines to the models:
[code lang=”ruby”]
class Product < ActiveRecord::Base
acts_as_popular
has_and_belongs_to_many :tags , :update_popularity => true
end
class Tag < ActiveRecord::Base
acts_as_popular
has_and_belongs_to_many :products
end
[/code]
Both Product and Tag have a popularity integer field in the database.
Now, every time an Product is created, destroyed or it's popularity field updated the popularities of it's associated tags are also updated. The popularity of each tag is the sum of the popularities of it's associated product items. This also works for has_many, has_one and belongs_to associations.
How it works
The popularity is propagated from the record of the model that has :update_popularity => true in it’s body to the record of the model targeted by the association - in our example from products to tags. Be careful how you put these because if the :update_popularity definitions form a cycle the script will enter in an infinite update cycle - in our example this can happen if we put :update_popularity => true after has_and_belongs_to_many :products .
The plugin may prove useful particularly in keeping code DRY on complex models with more than one layer of popularity updating. In our example we could add a Category model and make every Tag belong to a Category and we would make the popularity of each category update automatically by adding belongs_to :category, :update_popularity => true to the Tag model.
Final word
The script can be considered still under development. It works in an application of mine with a complex model yet I think it needs more testing. Let me know if you encounter problems using it.
Download the plugin . Enjoy!
Hey man that seems cool. Can you show us a bit of the model you’re ranking by popularity? I maybe need a deep example to fully understand the mechanics.. Anyway I’ll give it a try!
Comment by Paolo Dona — June 20, 2006 @ 3:45 am
Hi,
Here it goes (it’s adjusted for more clarity and I’ll skip the irrelevant details) :
The users may rate the products rate in a way that can be considered a definition of their popularity. Something like “I like this a bit” - 1 popularity point , “I like this a lot” - 3 popularity points, “Just great!” - 5 popularity points. This will be the “Opinion” of some user. This starting point.
pinions
The opinion
[code]
belongs_to :user
belongs_to :product, :update_popularity => true
[/code]
Every product
[code]
has_many
belongs_to :place, :update_popularity => true
belongs_to :created_by, :update_popularity => true
has_and_belongs_to_many :tags, :update_popularity => true
[/code]
Every place
[code]
belongs_to :city, :update_popularity => true
[/code]
Having these in the models every time someone expresses on opinion on a product all the associated records are adjusted considering that opinion.
Here’s a little story.
Alice adds the product “Muddy toothpaste” to the “Chioshc” store in Timisoara. She tags it “Toothpaste” and “Muddy”. The Muddy toothpaste has no opinions so it’s popularity is for now 0 and nothing special happens.
Bob decides that he likes the toothpaste a lot. So he posts an opinion with the popularity 3. This is where the plugin starts working…
It increases the product’s popularity by 3. Then it increases the popularity of “Chioshc” the same way that is turn increases the popularity of Timisoara by 3. Also, the popularity of it’s creator, “Alice” is increased by the same amount. The popularity of every associated tag is increased so now “Muddy”’s popularity is higher with 3 points.
This is about it does. Oh, if Bob decides that he actually thinks the toothpaste is great, everything is adjusted accordingly. This also happens if the toothpaste or the city or something else is deleted or adjusted. The plugin keeps everything updated.
Having the popularity in the database, we can query the database for the most popular tags and make a tag cloud or for the most popular cities to put first in our list.
Hope you’ll find it useful.
Comment by Cosmin Radoi — June 21, 2006 @ 1:49 am
What does the database look like? Is there a popularity column that’s an int (mysql)?
Comment by nooby — July 5, 2006 @ 12:10 pm
Yes, every table for which popularity is relevant has an “popularity” named column that can hold int like values (int or longint in mysql).
Comment by Cosmin Radoi — July 6, 2006 @ 6:39 am