# Tag Cloud on rails?

**URL:** <https://www.ruby-forum.com/t/tag-cloud-on-rails/85488>\
**Category:** Rails\
**Created:** [February 14, 2007, 12:24am UTC](https://www.ruby-forum.com/t/tag-cloud-on-rails/85488 "2007-02-14T00:24:49Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![miked](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@miked](https://www.ruby-forum.com/u/miked)\
**Post date:** [February 14, 2007, 12:24am UTC](https://www.ruby-forum.com/t/tag-cloud-on-rails/85488/1 "2007-02-14T00:24:49Z")

</div>

Hi:

Anyone know of anyone that’s implemented AND made available a tag cloud  
implemented in rails?

Thanks!

Mike

---

<div class="post-metadata">

**Author:** ![miked](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@miked](https://www.ruby-forum.com/u/miked)\
**Post date:** [February 14, 2007, 11:13am UTC](https://www.ruby-forum.com/t/tag-cloud-on-rails/85488/2 "2007-02-14T11:13:05Z")

</div>

Mike D. wrote:

> Hi:
> 
> Anyone know of anyone that’s implemented AND made available a tag cloud  
> implemented in rails?
> 
> Thanks!
> 
> Mike

Like Michael, I’m using acts\_as\_taggable and adding a method to the Tag  
model but implementing it slightly differently. I’m pasting the code as  
is (and just looking at it fresh, it could be improved in places), but  
not all of it is needed (e.g. I needed to be able to restrict the tag  
cloud to certain models, and those lines are commented as optional

def self.tag\_cloud\_count(options={})  
except, only = options[:except].to\_a, options[:only].to\_a # optional  
raise ArgumentError, “You can only specify :except OR :only options”  
if !except.empty? && !only.empty? # optional  
conditions = “taggings.tag\_id = tags.id” if except.empty? &&  
only.empty?  
conditions = ["(taggings.tag\_id = tags.id) AND  
(taggings.taggable\_type IN (?))", only.collect {|m| m.to\_s.classify }]  
if !only.empty? # optional  
conditions = ["(taggings.tag\_id = tags.id) AND  
(taggings.taggable\_type NOT IN (?))", except.collect {|m|  
m.to\_s.classify }] if !except.empty? # optional  
find(:all, :select =\> “tags._, COUNT(_) AS tag\_count”, :joins =\>  
“INNER JOIN taggings”, :conditions =\> conditions, :group =\> “tags.name”,  
:order =\> “tags.name ASC”)  
end

Then in my app helper:  
def tag\_cloud\_for(tag\_cloud)  
max\_tag\_count = tag\_cloud.max {|a,b| a.tag\_count.to\_i \<=\>  
b.tag\_count.to\_i }.tag\_count.to\_f  
min\_tag\_count = tag\_cloud.min {|a,b| a.tag\_count.to\_i \<=\>  
b.tag\_count.to\_i }.tag\_count.to\_f  
min\_font\_size = 1.0  
max\_font\_size = 2.5  
mult = (max\_font\_size - min\_font\_size)/(max\_tag\_count -  
min\_tag\_count)  
output = tag\_cloud.collect { |tag| link\_to( tag.name,  
{:controller =\>  
‘search’, :tag =\> tag.name},  
{:style =\> “font-size:  
#{(((tag.tag\_count.to\_f - min\_tag\_count) \* mult) + min\_font\_size)}em”})  
}  
output.join(" ")  
end

In the helper method above the argument of the method is simply the  
collection of tags returned by to tag\_cloud\_count method. The cloud is  
output as a set of links, which go to my search controller, which  
returns all items tagged with the given term.

Of course, YMMV, but hopefully between this and Michael’s solution you  
should be able to find something that suits.

Cheers  
Chris

---

<div class="post-metadata">

**Author:** ![miked](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ed655f/32.png) [@miked](https://www.ruby-forum.com/u/miked)\
**Post date:** [February 14, 2007, 12:59am UTC](https://www.ruby-forum.com/t/tag-cloud-on-rails/85488/3 "2007-02-14T00:59:14Z")

</div>

On Wednesday 14 February 2007, Mike D. wrote:

> Hi:
> 
> Anyone know of anyone that’s implemented AND made available a tag  
> cloud implemented in rails?

Here’s what I’m using with Acts As Taggable (On Steroids).

I’ve added a method to the Tag model class for retrieving the N most  
popular tags

def self.find\_most\_popular(max\_count = 0)  
count\_col = Tag.connection.quote\_column\_name(‘count’)  
sql = “SELECT tags.id AS id, tags.name AS name, COUNT(\*) AS  
#{count\_col}”  
sql \<\< " FROM taggings JOIN tags ON taggings.tag\_id = tags.id"  
sql \<\< " GROUP BY tag\_id ORDER BY #{count\_col} DESC"  
sql \<\< " LIMIT #{max\_count.to\_i}" if max\_count.to\_i \> 0  
tags = Tag.find\_by\_sql(sql)  
tag\_count = tags.size  
tags.each do |tag|  
tag.send(:write\_attribute, :percentage, (tag.count \* 100) /  
tag\_count)  
end  
tags  
end

Acts As Taggable On Steroids has some other functionality for this, see  
its REAME.

In the PopularTagsHelper I have a method like this

def popular\_tag(t, options = {})  
wrap = options[:wrap] || ‘span’  
font\_size = t.percentage \* (options[:size\_scale] || 12)  
font\_weight = t.percentage \* (options[:weight\_scale] || 10)  
font\_size = [font\_size, options[:min\_size]].max if  
options[:min\_size]  
font\_size = [font\_size, options[:max\_size]].min if  
options[:max\_size]  
content\_tag(wrap,  
link\_to(t.name, ‘’),  
:title =\> “#{t.count} times”,  
:class =\> options[:class],  
:style =\> “font-size:#{font\_size}%;font-weight:#{font\_weight}%”  
)  
end

In the view

 \<% @popular\_tags.sort\_by(&:name).each do |t| -%\> \<%= popular\_tag(t, :wrap =\> 'li', :min\_size =\> 30, :max\_size =\> 400) %\> \<% end -%\> 

Finally some CSS

.tagcloud {  
text-align: center;  
width: 70%;  
}  
.tagcloud li {  
display: inline-block;  
display: -moz-inline-box;  
white-space: nowrap;  
vertical-align: middle;  
line-height: 1.2em;  
padding: 0 0.2em;  
}

On a self-serving note, let me point you to  
[http://schuerig.de/michael/blog/index.php/2007/02/14/popular-requests/](http://schuerig.de/michael/blog/index.php/2007/02/14/popular-requests/)

HTH,  
Michael

–  
Michael S.  
[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
[http://www.schuerig.de/michael/](http://www.schuerig.de/michael/)
