Tags
We will use acts_as_taggable_on_steroids (one of many tagging plugins for RoR) and will_paginate (one of many pagination plugins for RoR)acts_as_taggable_on_steroids
Install:script/plugin source http://svn.viney.net.nz/things/rails/plugins/ script/plugin install acts_as_taggable_on_steroids
will_paginate
Install:script/plugin install svn://errtheblog.com/svn/plugins/will_paginate
Create db structure
ruby script/generate acts_as_taggable_migration rake db:migrate
Edit the model
app/models/coffee_house.rbadd the line:
acts_as_taggable
Adding and displaying tags
- tag input field -- app/views/coffee_house/_form.rhtml:
<p><label for="coffee_house_tag_list">Tags</label><br> <%= text_field 'coffee_house', 'tag_list' %></p> - display tags -- app/views/coffee_house/show.rhtml:
<%= @coffee_house.tag_list.join(', ') %>
Tag cloud
- app/helpers/application.rb
include TagsHelper
- app/controllers/coffee_house_controller.rb#list
def list @coffee_house_pages, @coffee_houses = paginate :coffee_houses, :per_page => 10 @tags = CoffeeHouse.tag_counts end - public/stylesheets/coffee_house.css
.tag_cloud {width:500px;border:1px solid black;padding:5px} .css1 { font-size: 1.0em; } .css2 { font-size: 1.2em; } .css3 { font-size: 1.4em; } .css4 { font-size: 1.6em; } - app/views/coffee_house/list.rhtml
<div class="tag_cloud"> <% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %> <%= link_to tag.name, { :action => :list_tagged, :id => tag.name }, :class => css_class %> <% end %> <div>
Tag search
- We need a list_tagged action in the controller, that will perform a search on coffee houses tagged with the given tag and provide pagination for the results. The built-in RoR paginator is not best suited for this (plus it will no longer be a built-in in RoR 2.0), so we'll use will_paginate.
app/controllers/coffee_house_controller.rb
def list_tagged if params[:id] @tag = params[:id] params[:page]||=1 @coffee_houses = WillPaginate::Collection.create(params[:page],5) do |pager| result = CoffeeHouse.find_tagged_with(@tag,{:limit=>pager.per_page,:offset=>pager.offset}) pager.replace(result) options = CoffeeHouse.find_options_for_find_tagged_with(@tag); options.delete(:select) options.merge({:select => 'count(distinct coffee_houses.id)'}) pager.total_entries = CoffeeHouse.count(options) end else redirect_to :action => 'list' end end - We need a view to display search results. It will not be very different from the list view, so let's design it the DRY way:
- create a list element partial -- app/views/coffee_house/_list_element.rhtml
<div class="coffee_house"> <% photo = coffee_house.photos.first %> <%= image_tag(photo.public_filename('thumb'),:class=>'thumb') if photo %> <div class="info"> <h3><%= link_to coffee_house.name, :controller => 'coffee_house', :action => 'show', :id => coffee_house %></h3> <p><%= link_to coffee_house.company.name, :controller => 'company', :action => 'show', :id=>coffee_house.company if coffee_house.company %></p> <p><%= "#{coffee_house.street} #{coffee_house.building_number}" %></p> <p><%= link_to coffee_house.city.name, :controller => 'city', :action => 'show', :id => coffee_house.city if coffee_house.city %></p> </div> <div style="clear:both"></div> </div> - change app/views/coffee_house/list.rhtml to use the partial
<% for coffee_house in @coffee_houses %> <%= render :partial => 'list_element', :locals => {'coffee_house' => coffee_house} %> <div> <%= link_to 'Show', :action => 'show', :id=>coffee_house %> <%= link_to 'Edit', :action => 'edit', :id => coffee_house %> <%= link_to 'Destroy', {:action => 'destroy', :id=>coffee_house}, :method => :post %> </div> <% end %> - add style definitions to public/stylesheets/coffee_house.css
.coffee_house{ width: 400px; border: 1px solid #000000; margin: 10px; } .thumb{ float:left; } .info{ width: 300px; float:right; } - check if coffee_house/list displays correctly
- create app/views/coffee_house/list_tagged.rhtml
<h1>Listing Coffee Houses tagged with <%= @tag %></h1> <% for coffee_house in @coffee_houses %> <%= render :partial => 'list_element', :locals => {'coffee_house' => coffee_house} %> <% end %> <%= will_paginate @coffee_houses %> - click on a tag in tag cloud to test