You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by fa...@apache.org on 2009/03/27 11:33:07 UTC

svn commit: r759091 [6/8] - in /labs/consite: ./ trunk/ trunk/conferences/ trunk/conferences/app/ trunk/conferences/app/controllers/ trunk/conferences/app/controllers/admin/ trunk/conferences/app/controllers/admin/con/ trunk/conferences/app/helpers/ tr...

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/CHANGELOG
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/CHANGELOG?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/CHANGELOG (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/CHANGELOG Fri Mar 27 10:32:54 2009
@@ -0,0 +1,167 @@
+[13 March 08]
+
+* Added helper methods for will_paginate compatibility (Clinton R. Nixon)
+* Fixed :conditions in tag_counts to accept array to sanitize (Clinton R. Nixon)
+
+[07 March 08]
+
+* Added support for regexp delimiter (Matt Aimonetti)
+
+[30 Jan 08]
+
+* Fix Tag.destroy_unused on Rails 2.0.
+
+[23 October 2007]
+
+* Make find_options_for_tag_counts and find_options_for_tagged_with dup their options.
+
+* Apply conditions properly in find_options_for_tag_counts.
+
+* Fix tag_cloud when no tags are present.
+
+[22 October 2007]
+
+* Fix find_tagged_with using :match_all and :include.
+
+* Use inner joins instead of left outer joins.
+
+[15 October 2007]
+
+* Make find_tagged_with correctly apply :conditions
+
+* Add Tag.destroy_unused option.
+
+[11 October 2007]
+
+* Make tag_counts work correctly with STI.
+
+[3 October 2007]
+
+* Improve documentation.
+
+* Fix TagsHelper and test.
+
+[2 October 2007]
+
+* Remove TagList.parse, use TagList.from instead.
+
+* Add :parse option to TagList#new, TagList#add, and TagList#remove.
+
+    tag_list = TagList.new("One, Two", :parse => true) # ["One", "Two"]
+    
+    tag_list # ["One", "Two"]
+    tag_list.add("Three, Four", :parse => true) # ["One", "Two", "Three", "Four"]
+    
+* Remove TagList#names.
+
+[29 September 2007]
+
+* Add TagsHelper to assist with generating tag clouds and provide a simple example.
+
+[27 September 2007]
+
+* Add #tag_counts method to get tag counts for a specific object's tags.
+
+* BACKWARDS INCOMPATIBILITY: Rename #find_options_for_tagged_with to #find_options_for_find_tagged_with
+
+[17 September 2007]
+
+* Fix clearing of cached tag list when all tags removed.
+
+[12 September 2007]
+
+* Make the TagList class inherit from Array.
+
+* Deprecate obsolete TagList#names.
+
+[6 September 2007]
+
+* Add TagList#include? and TagList#empty?
+
+[26 August 2006]
+
+* Remove deprecated Tag.delimiter. Use TagList.delimiter instead.
+
+[25 August 2007]
+
+* Make tag_counts work with has_many :through
+
+[23 August 2007]
+
+* Make search comparisons case-insensitive across different databases. [Moisés Machado]
+
+* Improve compatiblity with STI. [Moisés Machado]
+
+[25 July 2007]
+
+* Respect custom table names for the Tag and Tagging classes.
+
+* Fix the :exclude option for find_tagged_with
+
+[17 July 2007]
+
+* Make the migration work on edge rails
+
+[8 July 2007]
+
+* find_options_for_tagged_with should not alter its arguments
+
+[1 July 2007]
+
+* Fix incorrect tagging when the case of the tag list is changed.
+
+* Fix deprecated Tag.delimiter accessor.
+
+[23 June 2007]
+
+* Add validation to Tag model.
+
+* find_options_for_tagged_with should always return a hash.
+
+* find_tagged_with passing in no tags should return an empty array.
+
+* Improve compatibility with PostgreSQL.
+
+[21 June 2007]
+
+* Remove extra .rb from generated migration file name.
+
+[15 June 2007]
+
+* Introduce TagList class.
+
+* Various cleanups and improvements.
+
+* Use TagList.delimiter now, not Tag.delimiter. Tag.delimiter will be removed at some stage.
+
+[11 June 2007]
+
+* Restructure the creation of the options for find_tagged_with [Thijs Cadier]
+
+* Add an example migration with a generator.
+
+* Add caching.
+
+* Fix compatibility with Ruby < 1.8.6
+
+[23 April 2007]
+
+* Make tag_list to respect Tag.delimiter
+
+[31 March 2007]
+
+* Add Tag.delimiter accessor to change how tags are parsed.
+
+* Fix :include => :tags when used with find_tagged_with
+
+[7 March 2007]
+
+* Fix tag_counts for SQLServer [Brad Young]
+
+[21 Feb 2007]
+
+* Use scoping instead of TagCountsExtension [Michael Schuerig]
+
+[7 Jan 2007]
+
+* Add :match_all to find_tagged_with [Michael Sheakoski]

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/MIT-LICENSE
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/MIT-LICENSE?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/MIT-LICENSE (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/MIT-LICENSE Fri Mar 27 10:32:54 2009
@@ -0,0 +1,20 @@
+Copyright (c) 2006 Jonathan Viney
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/README
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/README?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/README (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/README Fri Mar 27 10:32:54 2009
@@ -0,0 +1,148 @@
+= acts_as_taggable_on_steroids
+
+If you find this plugin useful, please consider a donation to show your support!
+
+  http://www.paypal.com/cgi-bin/webscr?cmd=_send-money
+  
+  Email address: jonathan.viney@gmail.com
+  
+== Instructions
+
+This plugin is based on acts_as_taggable by DHH but includes extras
+such as tests, smarter tag assignment, and tag cloud calculations.
+
+== Installation
+
+  ruby script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids
+
+== Usage
+
+=== Prepare database
+
+Generate and apply the migration:
+
+  ruby script/generate acts_as_taggable_migration
+  rake db:migrate
+
+=== Basic tagging
+
+Let's suppose users have many posts and we want those posts to have tags.
+The first step is to add +acts_as_taggable+ to the Post class:
+
+  class Post < ActiveRecord::Base
+    acts_as_taggable
+    
+    belongs_to :user
+  end
+  
+We can now use the tagging methods provided by acts_as_taggable, <tt>#tag_list</tt> and <tt>#tag_list=</tt>. Both these
+methods work like regular attribute accessors.
+
+  p = Post.find(:first)
+  p.tag_list # []
+  p.tag_list = "Funny, Silly"
+  p.save
+  p.tag_list # ["Funny", "Silly"]
+  
+You can also add or remove arrays of tags.
+
+  p.tag_list.add("Great", "Awful")
+  p.tag_list.remove("Funny")
+
+=== Finding tagged objects
+
+To retrieve objects tagged with a certain tag, use find_tagged_with.
+
+  Post.find_tagged_with('Funny, Silly')
+  
+By default, find_tagged_with will find objects that have any of the given tags. To
+find only objects that are tagged with all the given tags, use match_all.
+
+  Post.find_tagged_with('Funny, Silly', :match_all => true)
+  
+See <tt>ActiveRecord::Acts::Taggable::InstanceMethods</tt> for more methods and options.
+
+=== Tag cloud calculations
+
+To construct tag clouds, the frequency of each tag needs to be calculated.
+Because we specified +acts_as_taggable+ on the <tt>Post</tt> class, we can
+get a calculation of all the tag counts by using <tt>Post.tag_counts</tt>. But what if we wanted a tag count for
+an single user's posts? To achieve this we call tag_counts on the association:
+
+  User.find(:first).posts.tag_counts
+  
+A helper is included to assist with generating tag clouds. Include it in your helper file:
+
+  module ApplicationHelper
+    include TagsHelper
+  end
+
+Here is an example that generates a tag cloud.
+
+Controller:
+
+  class PostController < ApplicationController
+    def tag_cloud
+      @tags = Post.tag_counts
+    end
+  end
+  
+View:
+  <% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %>
+    <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
+  <% end %>
+  
+CSS:
+
+  .css1 { font-size: 1.0em; }
+  .css2 { font-size: 1.2em; }
+  .css3 { font-size: 1.4em; }
+  .css4 { font-size: 1.6em; }
+
+=== Caching
+
+It is useful to cache the list of tags to reduce the number of queries executed. To do this,
+add a column named <tt>cached_tag_list</tt> to the model which is being tagged. The column should be long enough to hold
+the full tag list and must have a default value of null, not an empty string.
+
+  class CachePostTagList < ActiveRecord::Migration
+    def self.up
+      add_column :posts, :cached_tag_list, :string
+    end
+  end
+
+  class Post < ActiveRecord::Base
+    acts_as_taggable
+    
+    # The caching column defaults to cached_tag_list, but can be changed:
+    # 
+    # set_cached_tag_list_column_name "my_caching_column_name"
+  end
+
+The details of the caching are handled for you. Just continue to use the tag_list accessor as you normally would.
+Note that the cached tag list will not be updated if you directly create Tagging objects or manually append to the
+<tt>tags</tt> or <tt>taggings</tt> associations. To update the cached tag list you should call <tt>save_cached_tag_list</tt> manually.
+
+=== Delimiter
+
+If you want to change the delimiter used to parse and present tags, set TagList.delimiter.
+For example, to use spaces instead of commas, add the following to config/environment.rb:
+
+  TagList.delimiter = " "
+  
+You can also use a regexp as delimiter:
+
+  TagList.delimiter = /,|;/
+  
+The above code would parse the string and use ',' and ';' as delimiters.
+
+=== Unused tags
+
+Set Tag.destroy_unused to remove tags when they are no longer being
+used to tag any objects. Defaults to false.
+
+  Tag.destroy_unused = true
+
+=== Other
+
+Problems, comments, and suggestions all welcome. jonathan.viney@gmail.com  

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/README
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/Rakefile
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/Rakefile?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/Rakefile (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/Rakefile Fri Mar 27 10:32:54 2009
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the acts_as_taggable_on_steroids plugin.'
+Rake::TestTask.new(:test) do |t|
+  t.libs << 'lib'
+  t.pattern = 'test/**/*_test.rb'
+  t.verbose = true
+end
+
+desc 'Generate documentation for the acts_as_taggable_on_steroids plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+  rdoc.rdoc_dir = 'rdoc'
+  rdoc.title    = 'Acts As Taggable On Steroids'
+  rdoc.options << '--line-numbers' << '--inline-source'
+  rdoc.rdoc_files.include('README')
+  rdoc.rdoc_files.include('lib/**/*.rb')
+end

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,11 @@
+class ActsAsTaggableMigrationGenerator < Rails::Generator::Base 
+  def manifest 
+    record do |m| 
+      m.migration_template 'migration.rb', 'db/migrate' 
+    end 
+  end
+  
+  def file_name
+    "acts_as_taggable_migration"
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/templates/migration.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/templates/migration.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/templates/migration.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/templates/migration.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,26 @@
+class ActsAsTaggableMigration < ActiveRecord::Migration
+  def self.up
+    create_table :tags do |t|
+      t.column :name, :string
+    end
+    
+    create_table :taggings do |t|
+      t.column :tag_id, :integer
+      t.column :taggable_id, :integer
+      
+      # You should make sure that the column created is
+      # long enough to store the required class names.
+      t.column :taggable_type, :string
+      
+      t.column :created_at, :datetime
+    end
+    
+    add_index :taggings, :tag_id
+    add_index :taggings, [:taggable_id, :taggable_type]
+  end
+  
+  def self.down
+    drop_table :taggings
+    drop_table :tags
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/generators/acts_as_taggable_migration/templates/migration.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/init.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/init.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/init.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/init.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + '/lib/acts_as_taggable'

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/init.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/acts_as_taggable.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/acts_as_taggable.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/acts_as_taggable.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/acts_as_taggable.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,214 @@
+module ActiveRecord #:nodoc:
+  module Acts #:nodoc:
+    module Taggable #:nodoc:
+      def self.included(base)
+        base.extend(ClassMethods)
+      end
+      
+      module ClassMethods
+        def acts_as_taggable
+          has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag
+          has_many :tags, :through => :taggings
+          
+          before_save :save_cached_tag_list
+          after_save :save_tags
+          
+          include ActiveRecord::Acts::Taggable::InstanceMethods
+          extend ActiveRecord::Acts::Taggable::SingletonMethods
+          
+          alias_method_chain :reload, :tag_list
+        end
+        
+        def cached_tag_list_column_name
+          "cached_tag_list"
+        end
+        
+        def set_cached_tag_list_column_name(value = nil, &block)
+          define_attr_method :cached_tag_list_column_name, value, &block
+        end
+      end
+      
+      module SingletonMethods
+        # Pass either a tag string, or an array of strings or tags
+        # 
+        # Options:
+        #   :exclude - Find models that are not tagged with the given tags
+        #   :match_all - Find models that match all of the given tags, not just one
+        #   :conditions - A piece of SQL conditions to add to the query
+        def find_tagged_with(*args)
+          options = find_options_for_find_tagged_with(*args)
+          options.blank? ? [] : find(:all, options)
+        end
+
+        # will_paginate's method_missing function wants to hit
+        # find_all_tagged_with if you call paginate_tagged_with, which is
+        # obviously suboptimal
+        def find_all_tagged_with(*args)
+          find_tagged_with(*args)
+        end
+        
+        def find_options_for_find_tagged_with(tags, options = {})
+          tags = tags.is_a?(Array) ? TagList.new(tags.map(&:to_s)) : TagList.from(tags)
+          options = options.dup
+          
+          return {} if tags.empty?
+          
+          conditions = []
+          conditions << sanitize_sql(options.delete(:conditions)) if options[:conditions]
+          
+          taggings_alias, tags_alias = "#{table_name}_taggings", "#{table_name}_tags"
+          
+          if options.delete(:exclude)
+            conditions << <<-END
+              #{table_name}.id NOT IN
+                (SELECT #{Tagging.table_name}.taggable_id FROM #{Tagging.table_name}
+                 INNER JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id
+                 WHERE #{tags_condition(tags)} AND #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})
+            END
+          else
+            if options.delete(:match_all)
+              conditions << <<-END
+                (SELECT COUNT(*) FROM #{Tagging.table_name}
+                 INNER JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id
+                 WHERE #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)} AND
+                 taggable_id = #{table_name}.id AND
+                 #{tags_condition(tags)}) = #{tags.size}
+              END
+            else
+              conditions << tags_condition(tags, tags_alias)
+            end
+          end
+          
+          { :select => "DISTINCT #{table_name}.*",
+            :joins => "INNER JOIN #{Tagging.table_name} #{taggings_alias} ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key} AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)} " +
+                      "INNER JOIN #{Tag.table_name} #{tags_alias} ON #{tags_alias}.id = #{taggings_alias}.tag_id",
+            :conditions => conditions.join(" AND ")
+          }.reverse_merge!(options)
+        end
+        
+        # Calculate the tag counts for all tags.
+        # 
+        # Options:
+        #  :start_at - Restrict the tags to those created after a certain time
+        #  :end_at - Restrict the tags to those created before a certain time
+        #  :conditions - A piece of SQL conditions to add to the query
+        #  :limit - The maximum number of tags to return
+        #  :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
+        #  :at_least - Exclude tags with a frequency less than the given value
+        #  :at_most - Exclude tags with a frequency greater than the given value
+        def tag_counts(options = {})
+          Tag.find(:all, find_options_for_tag_counts(options))
+        end
+
+        # Find how many objects are tagged with a certain tag.
+        def count_by_tag(tag_name)
+          counts = tag_counts(:conditions => "tags.name = #{quote_value(tag_name)}")
+          counts[0].respond_to?(:count) ? counts[0].count : 0
+        end
+        
+        def find_options_for_tag_counts(options = {})
+          options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit
+          options = options.dup
+          
+          scope = scope(:find)
+          start_at = sanitize_sql(["#{Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
+          end_at = sanitize_sql(["#{Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
+          
+          conditions = [
+            "#{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)}",
+            sanitize_sql(options.delete(:conditions)),
+            scope && scope[:conditions],
+            start_at,
+            end_at
+          ]
+          
+          conditions << type_condition unless descends_from_active_record? 
+          conditions.compact!
+          conditions = conditions.join(' AND ')
+          
+          joins = ["INNER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"]
+          joins << "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{Tagging.table_name}.taggable_id"
+          joins << scope[:joins] if scope && scope[:joins]
+          
+          at_least  = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least]
+          at_most   = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most]
+          having    = [at_least, at_most].compact.join(' AND ')
+          group_by  = "#{Tag.table_name}.id, #{Tag.table_name}.name HAVING COUNT(*) > 0"
+          group_by << " AND #{having}" unless having.blank?
+          
+          { :select     => "#{Tag.table_name}.id, #{Tag.table_name}.name, COUNT(*) AS count", 
+            :joins      => joins.join(" "),
+            :conditions => conditions,
+            :group      => group_by
+          }.reverse_merge!(options)
+        end
+        
+        def caching_tag_list?
+          column_names.include?(cached_tag_list_column_name)
+        end
+        
+       private
+        def tags_condition(tags, table_name = Tag.table_name)
+          condition = tags.map { |t| sanitize_sql(["#{table_name}.name LIKE ?", t]) }.join(" OR ")
+          "(" + condition + ")"
+        end
+      end
+      
+      module InstanceMethods
+        def tag_list
+          return @tag_list if @tag_list
+          
+          if self.class.caching_tag_list? and !(cached_value = send(self.class.cached_tag_list_column_name)).nil?
+            @tag_list = TagList.from(cached_value)
+          else
+            @tag_list = TagList.new(*tags.map(&:name))
+          end
+        end
+        
+        def tag_list=(value)
+          @tag_list = TagList.from(value)
+        end
+        
+        def save_cached_tag_list
+          if self.class.caching_tag_list?
+            self[self.class.cached_tag_list_column_name] = tag_list.to_s
+          end
+        end
+        
+        def save_tags
+          return unless @tag_list
+          
+          new_tag_names = @tag_list - tags.map(&:name)
+          old_tags = tags.reject { |tag| @tag_list.include?(tag.name) }
+          
+          self.class.transaction do
+            if old_tags.any?
+              taggings.find(:all, :conditions => ["tag_id IN (?)", old_tags.map(&:id)]).each(&:destroy)
+              taggings.reset
+            end
+            
+            new_tag_names.each do |new_tag_name|
+              tags << Tag.find_or_create_with_like_by_name(new_tag_name)
+            end
+          end
+          
+          true
+        end
+        
+        # Calculate the tag counts for the tags used by this model.
+        #
+        # The possible options are the same as the tag_counts class method, excluding :conditions.
+        def tag_counts(options = {})
+          self.class.tag_counts({ :conditions => self.class.send(:tags_condition, tag_list) }.reverse_merge!(options))
+        end
+        
+        def reload_with_tag_list(*args) #:nodoc:
+          @tag_list = nil
+          reload_without_tag_list(*args)
+        end
+      end
+    end
+  end
+end
+
+ActiveRecord::Base.send(:include, ActiveRecord::Acts::Taggable)

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/acts_as_taggable.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,26 @@
+class Tag < ActiveRecord::Base
+  has_many :taggings
+  
+  validates_presence_of :name
+  validates_uniqueness_of :name
+  
+  cattr_accessor :destroy_unused
+  self.destroy_unused = false
+  
+  # LIKE is used for cross-database case-insensitivity
+  def self.find_or_create_with_like_by_name(name)
+    find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name)
+  end
+  
+  def ==(object)
+    super || (object.is_a?(Tag) && name == object.name)
+  end
+  
+  def to_s
+    name
+  end
+  
+  def count
+    read_attribute(:count).to_i
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_counts_extension.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_counts_extension.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_counts_extension.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_counts_extension.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,3 @@
+# Deprecated
+module TagCountsExtension #:nodoc:
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_counts_extension.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_list.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_list.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_list.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_list.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,91 @@
+class TagList < Array
+  cattr_accessor :delimiter
+  self.delimiter = ','
+  
+  def initialize(*args)
+    add(*args)
+  end
+  
+  # Add tags to the tag_list. Duplicate or blank tags will be ignored.
+  #
+  #   tag_list.add("Fun", "Happy")
+  # 
+  # Use the <tt>:parse</tt> option to add an unparsed tag string.
+  #
+  #   tag_list.add("Fun, Happy", :parse => true)
+  def add(*names)
+    extract_and_apply_options!(names)
+    concat(names)
+    clean!
+    self
+  end
+  
+  # Remove specific tags from the tag_list.
+  # 
+  #   tag_list.remove("Sad", "Lonely")
+  #
+  # Like #add, the <tt>:parse</tt> option can be used to remove multiple tags in a string.
+  # 
+  #   tag_list.remove("Sad, Lonely", :parse => true)
+  def remove(*names)
+    extract_and_apply_options!(names)
+    delete_if { |name| names.include?(name) }
+    self
+  end
+  
+  # Transform the tag_list into a tag string suitable for edting in a form.
+  # The tags are joined with <tt>TagList.delimiter</tt> and quoted if necessary.
+  #
+  #   tag_list = TagList.new("Round", "Square,Cube")
+  #   tag_list.to_s # 'Round, "Square,Cube"'
+  def to_s
+    clean!
+    
+    list = map do |name|
+      if delimiter.is_a?(Regexp)
+        name.match(delimiter) ? "\"#{name}\"" : name
+      else
+        name.include?(delimiter) ? "\"#{name}\"" : name
+      end
+    end
+    
+    list.join( delimiter.is_a?(Regexp) ? "#{delimiter.source.match(/[^\\\[\]\*\?\{\}\.\|]/)[0]} " : (delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ") )
+  end
+  
+ private
+  # Remove whitespace, duplicates, and blanks.
+  def clean!
+    reject!(&:blank?)
+    map!(&:strip)
+    uniq!
+  end
+  
+  def extract_and_apply_options!(args)
+    options = args.last.is_a?(Hash) ? args.pop : {}
+    options.assert_valid_keys :parse
+    
+    if options[:parse]
+      args.map! { |a| self.class.from(a) }
+    end
+    
+    args.flatten!
+  end
+  
+  class << self
+    # Returns a new TagList using the given tag string.
+    # 
+    #   tag_list = TagList.from("One , Two,  Three")
+    #   tag_list # ["One", "Two", "Three"]
+    def from(string)
+      returning new do |tag_list|
+        string = string.to_s.gsub('.', '').dup
+        
+        # Parse the quoted tags
+        string.gsub!(/"(.*?)"\s*#{delimiter}?\s*/) { tag_list << $1; "" }
+        string.gsub!(/'(.*?)'\s*#{delimiter}?\s*/) { tag_list << $1; "" }
+        
+        tag_list.add(string.split(delimiter))
+      end
+    end
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tag_list.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tagging.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tagging.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tagging.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tagging.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,12 @@
+class Tagging < ActiveRecord::Base #:nodoc:
+  belongs_to :tag
+  belongs_to :taggable, :polymorphic => true
+  
+  def after_destroy
+    if Tag.destroy_unused
+      if tag.taggings.count.zero?
+        tag.destroy
+      end
+    end
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tagging.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tags_helper.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tags_helper.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tags_helper.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tags_helper.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,13 @@
+module TagsHelper
+  # See the README for an example using tag_cloud.
+  def tag_cloud(tags, classes)
+    return if tags.empty?
+    
+    max_count = tags.sort_by(&:count).last.count.to_f
+    
+    tags.each do |tag|
+      index = ((tag.count / max_count) * (classes.size - 1)).round
+      yield tag, classes[index]
+    end
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/lib/tags_helper.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/abstract_unit.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/abstract_unit.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/abstract_unit.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/abstract_unit.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,97 @@
+require 'test/unit'
+
+begin
+  require File.dirname(__FILE__) + '/../../../../config/environment'
+rescue LoadError
+  require 'rubygems'
+  gem 'activerecord'
+  gem 'actionpack'
+  require 'active_record'
+  require 'action_controller'
+end
+
+# Search for fixtures first
+fixture_path = File.dirname(__FILE__) + '/fixtures/'
+Dependencies.load_paths.insert(0, fixture_path)
+
+require 'active_record/fixtures'
+
+require File.dirname(__FILE__) + '/../lib/acts_as_taggable'
+require_dependency File.dirname(__FILE__) + '/../lib/tag_list'
+require_dependency File.dirname(__FILE__) + '/../lib/tags_helper'
+
+ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log')
+ActiveRecord::Base.configurations = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
+ActiveRecord::Base.establish_connection(ENV['DB'] || 'mysql')
+
+load(File.dirname(__FILE__) + '/schema.rb')
+
+Test::Unit::TestCase.fixture_path = fixture_path
+
+class Test::Unit::TestCase #:nodoc:
+  self.use_transactional_fixtures = true
+  self.use_instantiated_fixtures  = false
+  
+  def assert_equivalent(expected, actual, message = nil)
+    if expected.first.is_a?(ActiveRecord::Base)
+      assert_equal expected.sort_by(&:id), actual.sort_by(&:id), message
+    else
+      assert_equal expected.sort, actual.sort, message
+    end
+  end
+  
+  def assert_tag_counts(tags, expected_values)
+    # Map the tag fixture names to real tag names
+    expected_values = expected_values.inject({}) do |hash, (tag, count)|
+      hash[tags(tag).name] = count
+      hash
+    end
+    
+    tags.each do |tag|
+      value = expected_values.delete(tag.name)
+      
+      assert_not_nil value, "Expected count for #{tag.name} was not provided"
+      assert_equal value, tag.count, "Expected value of #{value} for #{tag.name}, but was #{tag.count}"
+    end
+    
+    unless expected_values.empty?
+      assert false, "The following tag counts were not present: #{expected_values.inspect}"
+    end
+  end
+  
+  def assert_queries(num = 1)
+    $query_count = 0
+    yield
+  ensure
+    assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
+  end
+
+  def assert_no_queries(&block)
+    assert_queries(0, &block)
+  end
+  
+  # From Rails trunk
+  def assert_difference(expressions, difference = 1, message = nil, &block)
+    expression_evaluations = [expressions].flatten.collect{|expression| lambda { eval(expression, block.binding) } } 
+    
+    original_values = expression_evaluations.inject([]) { |memo, expression| memo << expression.call }
+    yield
+    expression_evaluations.each_with_index do |expression, i|
+      assert_equal original_values[i] + difference, expression.call, message
+    end
+  end
+  
+  def assert_no_difference(expressions, message = nil, &block)
+    assert_difference expressions, 0, message, &block
+  end
+end
+
+ActiveRecord::Base.connection.class.class_eval do  
+  def execute_with_counting(sql, name = nil, &block)
+    $query_count ||= 0
+    $query_count += 1
+    execute_without_counting(sql, name, &block)
+  end
+  
+  alias_method_chain :execute, :counting
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/abstract_unit.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/acts_as_taggable_test.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/acts_as_taggable_test.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/acts_as_taggable_test.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/acts_as_taggable_test.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,347 @@
+require File.dirname(__FILE__) + '/abstract_unit'
+
+class ActsAsTaggableOnSteroidsTest < Test::Unit::TestCase
+  fixtures :tags, :taggings, :posts, :users, :photos, :subscriptions, :magazines
+  
+  def test_find_tagged_with
+    assert_equivalent [posts(:jonathan_sky), posts(:sam_flowers)], Post.find_tagged_with('"Very good"')
+    assert_equal Post.find_tagged_with('"Very good"'), Post.find_tagged_with(['Very good'])
+    assert_equal Post.find_tagged_with('"Very good"'), Post.find_tagged_with([tags(:good)])
+    
+    assert_equivalent [photos(:jonathan_dog), photos(:sam_flower), photos(:sam_sky)], Photo.find_tagged_with('Nature')
+    assert_equal Photo.find_tagged_with('Nature'), Photo.find_tagged_with(['Nature'])
+    assert_equal Photo.find_tagged_with('Nature'), Photo.find_tagged_with([tags(:nature)])
+    
+    assert_equivalent [photos(:jonathan_bad_cat), photos(:jonathan_dog), photos(:jonathan_questioning_dog)], Photo.find_tagged_with('"Crazy animal" Bad')
+    assert_equal Photo.find_tagged_with('"Crazy animal" Bad'), Photo.find_tagged_with(['Crazy animal', 'Bad'])
+    assert_equal Photo.find_tagged_with('"Crazy animal" Bad'), Photo.find_tagged_with([tags(:animal), tags(:bad)])
+  end
+  
+  def test_find_tagged_with_nothing
+    assert_equal [], Post.find_tagged_with("")
+    assert_equal [], Post.find_tagged_with([])
+  end
+  
+  def test_find_tagged_with_nonexistant_tags
+    assert_equal [], Post.find_tagged_with('ABCDEFG')
+    assert_equal [], Photo.find_tagged_with(['HIJKLM'])
+    assert_equal [], Photo.find_tagged_with([Tag.new(:name => 'unsaved tag')])
+  end
+  
+  def test_find_tagged_with_match_all
+    assert_equivalent [photos(:jonathan_dog)], Photo.find_tagged_with('Crazy animal, "Nature"', :match_all => true)
+  end
+  
+  def test_find_tagged_with_match_all_and_include
+    assert_equivalent [posts(:jonathan_sky), posts(:sam_flowers)], Post.find_tagged_with(['Very good', 'Nature'], :match_all => true, :include => :tags)
+  end
+  
+  def test_find_tagged_with_conditions
+    assert_equal [], Post.find_tagged_with('"Very good", Nature', :conditions => '1=0')
+  end
+  
+  def test_find_tagged_with_duplicates_options_hash
+    options = { :conditions => '1=1' }.freeze
+    assert_nothing_raised { Post.find_tagged_with("Nature", options) }
+  end
+  
+  def test_find_tagged_with_exclusions
+    assert_equivalent [photos(:jonathan_questioning_dog), photos(:jonathan_bad_cat)], Photo.find_tagged_with("Nature", :exclude => true)
+    assert_equivalent [posts(:jonathan_grass), posts(:jonathan_rain), posts(:jonathan_cloudy), posts(:jonathan_still_cloudy)], Post.find_tagged_with("'Very good', Bad", :exclude => true)
+  end
+  
+  def test_find_options_for_find_tagged_with_no_tags_returns_empty_hash
+    assert_equal Hash.new, Post.find_options_for_find_tagged_with("")
+    assert_equal Hash.new, Post.find_options_for_find_tagged_with([nil])
+  end
+  
+  def test_find_options_for_find_tagged_with_leaves_arguments_unchanged
+    original_tags = photos(:jonathan_questioning_dog).tags.dup
+    Photo.find_options_for_find_tagged_with(photos(:jonathan_questioning_dog).tags)
+    assert_equal original_tags, photos(:jonathan_questioning_dog).tags
+  end
+  
+  def test_find_options_for_find_tagged_with_respects_custom_table_name
+    Tagging.table_name = "categorisations"
+    Tag.table_name = "categories"
+    
+    options = Photo.find_options_for_find_tagged_with("Hello")
+    
+    assert_no_match(/ taggings /, options[:joins])
+    assert_no_match(/ tags /, options[:joins])
+    
+    assert_match(/ categorisations /, options[:joins])
+    assert_match(/ categories /, options[:joins])
+  ensure
+    Tagging.table_name = "taggings"
+    Tag.table_name = "tags"
+  end
+  
+  def test_include_tags_on_find_tagged_with
+    assert_nothing_raised do
+      Photo.find_tagged_with('Nature', :include => :tags)
+      Photo.find_tagged_with("Nature", :include => { :taggings => :tag })
+    end
+  end
+  
+  def test_basic_tag_counts_on_class
+    assert_tag_counts Post.tag_counts, :good => 2, :nature => 7, :question => 1, :bad => 1
+    assert_tag_counts Photo.tag_counts, :good => 1, :nature => 3, :question => 1, :bad => 1, :animal => 3
+  end
+  
+  def test_tag_counts_on_class_with_date_conditions
+    assert_tag_counts Post.tag_counts(:start_at => Date.new(2006, 8, 4)), :good => 1, :nature => 5, :question => 1, :bad => 1
+    assert_tag_counts Post.tag_counts(:end_at => Date.new(2006, 8, 6)), :good => 1, :nature => 4, :question => 1
+    assert_tag_counts Post.tag_counts(:start_at => Date.new(2006, 8, 5), :end_at => Date.new(2006, 8, 10)), :good => 1, :nature => 4, :bad => 1
+    
+    assert_tag_counts Photo.tag_counts(:start_at => Date.new(2006, 8, 12), :end_at => Date.new(2006, 8, 19)), :good => 1, :nature => 2, :bad => 1, :question => 1, :animal => 3
+  end
+  
+  def test_tag_counts_on_class_with_frequencies
+    assert_tag_counts Photo.tag_counts(:at_least => 2), :nature => 3, :animal => 3
+    assert_tag_counts Photo.tag_counts(:at_most => 2), :good => 1, :question => 1, :bad => 1
+  end
+  
+  def test_tag_counts_on_class_with_frequencies_and_conditions
+    assert_tag_counts Photo.tag_counts(:at_least => 2, :conditions => '1=1'), :nature => 3, :animal => 3
+  end
+  
+  def test_tag_counts_duplicates_options_hash
+    options = { :at_least => 2, :conditions => '1=1' }.freeze
+    assert_nothing_raised { Photo.tag_counts(options) }
+  end
+  
+  def test_tag_counts_with_limit
+    assert_equal 2, Photo.tag_counts(:limit => 2).size
+    assert_equal 1, Post.tag_counts(:at_least => 4, :limit => 2).size
+  end
+  
+  def test_tag_counts_with_limit_and_order
+    assert_equal [tags(:nature), tags(:good)], Post.tag_counts(:order => 'count desc', :limit => 2)
+  end
+  
+  def test_tag_counts_on_association
+    assert_tag_counts users(:jonathan).posts.tag_counts, :good => 1, :nature => 5, :question => 1
+    assert_tag_counts users(:sam).posts.tag_counts, :good => 1, :nature => 2, :bad => 1
+    
+    assert_tag_counts users(:jonathan).photos.tag_counts, :animal => 3, :nature => 1, :question => 1, :bad => 1
+    assert_tag_counts users(:sam).photos.tag_counts, :nature => 2, :good => 1
+  end
+  
+  def test_tag_counts_on_association_with_options
+    assert_equal [], users(:jonathan).posts.tag_counts(:conditions => '1=0')
+    assert_tag_counts users(:jonathan).posts.tag_counts(:at_most => 2), :good => 1, :question => 1
+  end
+  
+  def test_tag_counts_on_has_many_through
+    assert_tag_counts users(:jonathan).magazines.tag_counts, :good => 1
+  end
+  
+  def test_tag_counts_respects_custom_table_names
+    Tagging.table_name = "categorisations"
+    Tag.table_name = "categories"
+    
+    options = Photo.find_options_for_tag_counts(:start_at => 2.weeks.ago, :end_at => Date.today)
+    sql = options.values.join(' ')
+    
+    assert_no_match /taggings/, sql
+    assert_no_match /tags/, sql
+    
+    assert_match /categorisations/, sql
+    assert_match /categories/, sql
+  ensure
+    Tagging.table_name = "taggings"
+    Tag.table_name = "tags"
+  end
+  
+  def test_tag_list_reader
+    assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    assert_equivalent ["Bad", "Crazy animal"], photos(:jonathan_bad_cat).tag_list
+  end
+  
+  def test_reassign_tag_list
+    assert_equivalent ["Nature", "Question"], posts(:jonathan_rain).tag_list
+    posts(:jonathan_rain).taggings.reload
+    
+    # Only an update of the posts table should be executed
+    assert_queries 1 do
+      posts(:jonathan_rain).update_attributes!(:tag_list => posts(:jonathan_rain).tag_list.to_s)
+    end
+    
+    assert_equivalent ["Nature", "Question"], posts(:jonathan_rain).tag_list
+  end
+  
+  def test_new_tags
+    assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    posts(:jonathan_sky).update_attributes!(:tag_list => "#{posts(:jonathan_sky).tag_list}, One, Two")
+    assert_equivalent ["Very good", "Nature", "One", "Two"], posts(:jonathan_sky).tag_list
+  end
+  
+  def test_remove_tag
+    assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    posts(:jonathan_sky).update_attributes!(:tag_list => "Nature")
+    assert_equivalent ["Nature"], posts(:jonathan_sky).tag_list
+  end
+  
+  def test_change_case_of_tags
+    original_tag_names = photos(:jonathan_questioning_dog).tag_list
+    photos(:jonathan_questioning_dog).update_attributes!(:tag_list => photos(:jonathan_questioning_dog).tag_list.to_s.upcase)
+    
+    # The new tag list is not uppercase becuase the AR finders are not case-sensitive
+    # and find the old tags when re-tagging with the uppercase tags.
+    assert_equivalent original_tag_names, photos(:jonathan_questioning_dog).reload.tag_list
+  end
+  
+  def test_remove_and_add_tag
+    assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    posts(:jonathan_sky).update_attributes!(:tag_list => "Nature, Beautiful")
+    assert_equivalent ["Nature", "Beautiful"], posts(:jonathan_sky).tag_list
+  end
+  
+  def test_tags_not_saved_if_validation_fails
+    assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    assert !posts(:jonathan_sky).update_attributes(:tag_list => "One, Two", :text => "")
+    assert_equivalent ["Very good", "Nature"], Post.find(posts(:jonathan_sky).id).tag_list
+  end
+  
+  def test_tag_list_accessors_on_new_record
+    p = Post.new(:text => 'Test')
+    
+    assert p.tag_list.blank?
+    p.tag_list = "One, Two"
+    assert_equal "One, Two", p.tag_list.to_s
+  end
+  
+  def test_clear_tag_list_with_nil
+    p = photos(:jonathan_questioning_dog)
+    
+    assert !p.tag_list.blank?
+    assert p.update_attributes(:tag_list => nil)
+    assert p.tag_list.blank?
+    
+    assert p.reload.tag_list.blank?
+  end
+  
+  def test_clear_tag_list_with_string
+    p = photos(:jonathan_questioning_dog)
+    
+    assert !p.tag_list.blank?
+    assert p.update_attributes(:tag_list => '  ')
+    assert p.tag_list.blank?
+    
+    assert p.reload.tag_list.blank?
+  end
+  
+  def test_tag_list_reset_on_reload
+    p = photos(:jonathan_questioning_dog)
+    assert !p.tag_list.blank?
+    p.tag_list = nil
+    assert p.tag_list.blank?
+    assert !p.reload.tag_list.blank?
+  end
+  
+  def test_instance_tag_counts
+    assert_tag_counts posts(:jonathan_sky).tag_counts, :good => 2, :nature => 7
+  end
+  
+  def test_tag_list_populated_when_cache_nil
+    assert_nil posts(:jonathan_sky).cached_tag_list
+    posts(:jonathan_sky).save!
+    assert_equal posts(:jonathan_sky).tag_list.to_s, posts(:jonathan_sky).cached_tag_list
+  end
+  
+  def test_cached_tag_list_used
+    posts(:jonathan_sky).save!
+    posts(:jonathan_sky).reload
+    
+    assert_no_queries do
+      assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list
+    end
+  end
+  
+  def test_cached_tag_list_not_used
+    # Load fixture and column information
+    posts(:jonathan_sky).taggings(:reload)
+    
+    assert_queries 1 do
+      # Tags association will be loaded
+      posts(:jonathan_sky).tag_list
+    end
+  end
+  
+  def test_cached_tag_list_updated
+    assert_nil posts(:jonathan_sky).cached_tag_list
+    posts(:jonathan_sky).save!
+    assert_equivalent ["Very good", "Nature"], TagList.from(posts(:jonathan_sky).cached_tag_list)
+    posts(:jonathan_sky).update_attributes!(:tag_list => "None")
+    
+    assert_equal 'None', posts(:jonathan_sky).cached_tag_list
+    assert_equal 'None', posts(:jonathan_sky).reload.cached_tag_list
+  end
+  
+  def test_clearing_cached_tag_list
+    # Generate the cached tag list
+    posts(:jonathan_sky).save!
+    
+    posts(:jonathan_sky).update_attributes!(:tag_list => "")
+    assert_equal "", posts(:jonathan_sky).cached_tag_list
+  end
+
+  def test_find_tagged_with_using_sti
+    special_post = SpecialPost.create!(:text => "Test", :tag_list => "Random")
+    
+    assert_equal [special_post],  SpecialPost.find_tagged_with("Random")
+    assert Post.find_tagged_with("Random").include?(special_post)
+  end
+  
+  def test_tag_counts_using_sti
+    SpecialPost.create!(:text => "Test", :tag_list => "Nature")
+    
+    assert_tag_counts SpecialPost.tag_counts, :nature => 1
+  end
+  
+  def test_case_insensitivity
+    assert_difference "Tag.count", 1 do
+      Post.create!(:text => "Test", :tag_list => "one")
+      Post.create!(:text => "Test", :tag_list => "One")
+    end
+    
+    assert_equal Post.find_tagged_with("Nature"), Post.find_tagged_with("nature")
+  end
+  
+  def test_tag_not_destroyed_when_unused
+    posts(:jonathan_sky).tag_list.add("Random")
+    posts(:jonathan_sky).save!
+  
+    assert_no_difference 'Tag.count' do
+      posts(:jonathan_sky).tag_list.remove("Random")
+      posts(:jonathan_sky).save!
+    end
+  end
+  
+  def test_tag_destroyed_when_unused
+    Tag.destroy_unused = true
+    
+    posts(:jonathan_sky).tag_list.add("Random")
+    posts(:jonathan_sky).save!
+    
+    assert_difference 'Tag.count', -1 do
+      posts(:jonathan_sky).tag_list.remove("Random")
+      posts(:jonathan_sky).save!
+    end
+  ensure
+    Tag.destroy_unused = false
+  end
+end
+
+class ActsAsTaggableOnSteroidsFormTest < Test::Unit::TestCase
+  fixtures :tags, :taggings, :posts, :users, :photos
+  
+  include ActionView::Helpers::FormHelper
+  
+  def test_tag_list_contents
+    fields_for :post, posts(:jonathan_sky) do |f|
+      assert_match /Very good, Nature/, f.text_field(:tag_list)
+    end
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/acts_as_taggable_test.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/database.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/database.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/database.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/database.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,10 @@
+mysql:
+  :adapter: mysql
+  :host: localhost
+  :username: rails
+  :password:
+  :database: rails_plugin_test
+
+sqlite3:
+  :adapter: sqlite3
+  :database: ':memory:'

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazine.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazine.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazine.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazine.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,3 @@
+class Magazine < ActiveRecord::Base
+  acts_as_taggable
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazine.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazines.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazines.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazines.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/magazines.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,7 @@
+ruby:
+  id: 1
+  name: Ruby
+  
+rails:
+  id: 2
+  name: Rails
\ No newline at end of file

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photo.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photo.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photo.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photo.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,8 @@
+class Photo < ActiveRecord::Base
+  acts_as_taggable
+  
+  belongs_to :user
+end
+
+class SpecialPhoto < Photo
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photo.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photos.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photos.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photos.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/photos.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,24 @@
+jonathan_dog:
+  id: 1
+  user_id: 1
+  title: A small dog
+  
+jonathan_questioning_dog:
+  id: 2
+  user_id: 1
+  title: What does this dog want?
+  
+jonathan_bad_cat:
+  id: 3
+  user_id: 1
+  title: Bad cat
+  
+sam_flower:
+  id: 4
+  user_id: 2
+  title: Flower
+  
+sam_sky:
+  id: 5
+  user_id: 2
+  title: Sky

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/post.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/post.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/post.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/post.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,7 @@
+class Post < ActiveRecord::Base
+  acts_as_taggable
+  
+  belongs_to :user
+  
+  validates_presence_of :text
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/post.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/posts.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/posts.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/posts.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/posts.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,34 @@
+jonathan_sky:
+  id: 1
+  user_id: 1
+  text: The sky is particularly blue today
+  
+jonathan_grass:
+  id: 2
+  user_id: 1
+  text: The grass seems very green
+  
+jonathan_rain:
+  id: 3
+  user_id: 1
+  text: Why does the rain fall?
+  
+jonathan_cloudy:
+  id: 4
+  user_id: 1
+  text: Is it cloudy?
+
+jonathan_still_cloudy:
+  id: 5
+  user_id: 1
+  text: Is it still cloudy?
+
+sam_ground:
+  id: 6
+  user_id: 2
+  text: The ground is looking too brown
+  
+sam_flowers:
+  id: 7
+  user_id: 2
+  text: Why are the flowers dead?
\ No newline at end of file

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/special_post.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/special_post.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/special_post.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/special_post.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,2 @@
+class SpecialPost < Post
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/special_post.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscription.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscription.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscription.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscription.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,4 @@
+class Subscription < ActiveRecord::Base
+  belongs_to :user
+  belongs_to :magazine
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscription.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscriptions.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscriptions.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscriptions.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/subscriptions.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,3 @@
+jonathan_rails:
+  user_id: 1
+  magazine_id: 1
\ No newline at end of file

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/taggings.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/taggings.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/taggings.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/taggings.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,149 @@
+# Posts
+jonathan_sky_good:
+  id: 1
+  tag_id: 1
+  taggable_id: 1
+  taggable_type: Post
+  created_at: 2006-08-01
+  
+jonathan_sky_nature:
+  id: 2
+  tag_id: 3
+  taggable_id: 1
+  taggable_type: Post
+  created_at: 2006-08-02
+  
+jonathan_grass_nature:
+  id: 3
+  tag_id: 3
+  taggable_id: 2
+  taggable_type: Post
+  created_at: 2006-08-03
+  
+jonathan_rain_question:
+  id: 4
+  tag_id: 4
+  taggable_id: 3
+  taggable_type: Post
+  created_at: 2006-08-04
+  
+jonathan_rain_nature:
+  id: 5
+  tag_id: 3
+  taggable_id: 3
+  taggable_type: Post
+  created_at: 2006-08-05
+  
+jonathan_cloudy_nature:
+  id: 6
+  tag_id: 3
+  taggable_id: 4
+  taggable_type: Post
+  created_at: 2006-08-06
+  
+jonathan_still_cloudy_nature:
+  id: 7
+  tag_id: 3
+  taggable_id: 5
+  taggable_type: Post
+  created_at: 2006-08-07
+
+sam_ground_nature:
+  id: 8
+  tag_id: 3
+  taggable_id: 6
+  taggable_type: Post
+  created_at: 2006-08-08
+  
+sam_ground_bad:
+  id: 9
+  tag_id: 2
+  taggable_id: 6
+  taggable_type: Post
+  created_at: 2006-08-09
+  
+sam_flowers_good:
+  id: 10
+  tag_id: 1
+  taggable_id: 7
+  taggable_type: Post
+  created_at: 2006-08-10
+  
+sam_flowers_nature:
+  id: 11
+  tag_id: 3
+  taggable_id: 7
+  taggable_type: Post
+  created_at: 2006-08-11
+  
+# Photos
+jonathan_dog_animal:
+  id: 12
+  tag_id: 5
+  taggable_id: 1
+  taggable_type: Photo
+  created_at: 2006-08-12
+  
+jonathan_dog_nature:
+  id: 13
+  tag_id: 3
+  taggable_id: 1
+  taggable_type: Photo
+  created_at: 2006-08-13
+  
+jonathan_questioning_dog_animal:
+  id: 14
+  tag_id: 5
+  taggable_id: 2
+  taggable_type: Photo
+  created_at: 2006-08-14
+  
+jonathan_questioning_dog_question:
+  id: 15
+  tag_id: 4
+  taggable_id: 2
+  taggable_type: Photo
+  created_at: 2006-08-15
+  
+jonathan_bad_cat_bad:
+  id: 16
+  tag_id: 2
+  taggable_id: 3
+  taggable_type: Photo
+  created_at: 2006-08-16
+  
+jonathan_bad_cat_animal:
+  id: 17
+  tag_id: 5
+  taggable_id: 3
+  taggable_type: Photo
+  created_at: 2006-08-17
+  
+sam_flower_nature:
+  id: 18
+  tag_id: 3
+  taggable_id: 4
+  taggable_type: Photo
+  created_at: 2006-08-18
+  
+sam_flower_good:
+  id: 19
+  tag_id: 1
+  taggable_id: 4
+  taggable_type: Photo
+  created_at: 2006-08-19
+  
+sam_sky_nature:
+  id: 20
+  tag_id: 3
+  taggable_id: 5
+  taggable_type: Photo
+  created_at: 2006-08-20
+
+# Magazines
+ruby_good:
+  id: 50
+  tag_id: 1
+  taggable_id: 1
+  taggable_type: Magazine
+  created_at: 2007-08-25

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/tags.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/tags.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/tags.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/tags.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,19 @@
+good:
+  id: 1
+  name: Very good
+  
+bad:
+  id: 2
+  name: Bad
+  
+nature:
+  id: 3
+  name: Nature
+  
+question:
+  id: 4
+  name: Question
+  
+animal:
+  id: 5
+  name: Crazy animal
\ No newline at end of file

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/user.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/user.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/user.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/user.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,7 @@
+class User < ActiveRecord::Base
+  has_many :posts
+  has_many :photos
+  
+  has_many :subscriptions
+  has_many :magazines, :through => :subscriptions
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/user.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/users.yml
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/users.yml?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/users.yml (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/fixtures/users.yml Fri Mar 27 10:32:54 2009
@@ -0,0 +1,7 @@
+jonathan:
+  id: 1
+  name: Jonathan
+  
+sam:
+  id: 2
+  name: Sam

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/schema.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/schema.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/schema.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/schema.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,37 @@
+ActiveRecord::Schema.define :version => 0 do
+  create_table :tags, :force => true do |t|
+    t.column :name, :string
+  end
+  
+  create_table :taggings, :force => true do |t|
+    t.column :tag_id, :integer
+    t.column :taggable_id, :integer
+    t.column :taggable_type, :string
+    t.column :created_at, :datetime
+  end
+  
+  create_table :users, :force => true do |t|
+    t.column :name, :string
+  end
+  
+  create_table :posts, :force => true do |t|
+    t.column :text, :text
+    t.column :cached_tag_list, :string
+    t.column :user_id, :integer
+    t.column :type, :string
+  end
+  
+  create_table :photos, :force => true do |t|
+    t.column :title, :string
+    t.column :user_id, :integer
+  end
+  
+  create_table :subscriptions, :force => true do |t|
+    t.column :user_id, :integer
+    t.column :magazine_id, :integer
+  end
+  
+  create_table :magazines, :force => true do |t|
+    t.column :name, :string
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/schema.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_list_test.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_list_test.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_list_test.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_list_test.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,106 @@
+require File.dirname(__FILE__) + '/abstract_unit'
+
+class TagListTest < Test::Unit::TestCase
+  def test_from_leaves_string_unchanged
+    tags = '"One  ", Two'
+    original = tags.dup
+    TagList.from(tags)
+    assert_equal tags, original
+  end
+  
+  def test_from_single_name
+    assert_equal %w(Fun), TagList.from("Fun")
+    assert_equal %w(Fun), TagList.from('"Fun"')
+  end
+  
+  def test_from_blank
+    assert_equal [], TagList.from(nil)
+    assert_equal [], TagList.from("")
+  end
+  
+  def test_from_single_quoted_tag
+    assert_equal ['with, comma'], TagList.from('"with, comma"')
+  end
+  
+  def test_spaces_do_not_delineate
+    assert_equal ['A B', 'C'], TagList.from('A B, C')
+  end
+  
+  def test_from_multiple_tags
+    assert_equivalent %w(Alpha Beta Delta Gamma), TagList.from("Alpha, Beta, Delta, Gamma")
+  end
+  
+  def test_from_multiple_tags_with_quotes
+    assert_equivalent %w(Alpha Beta Delta Gamma), TagList.from('Alpha,  "Beta",  Gamma , "Delta"')
+  end
+  
+  def test_from_with_single_quotes
+    assert_equivalent ['A B', 'C'], TagList.from("'A B', C")
+  end
+  
+  def test_from_multiple_tags_with_quote_and_commas
+    assert_equivalent ['Alpha, Beta', 'Delta', 'Gamma, something'], TagList.from('"Alpha, Beta", Delta, "Gamma, something"')
+  end
+  
+  def test_from_removes_white_space
+    assert_equivalent %w(Alpha Beta), TagList.from('" Alpha   ", "Beta  "')
+    assert_equivalent %w(Alpha Beta), TagList.from('  Alpha,  Beta ')
+  end
+
+  def test_from_removes_dots
+    assert_equivalent %w(Alpha Beta), TagList.from('Alpha., Beta')
+    assert_equivalent %w(Alpha Beta), TagList.from('Alpha, Be.ta')
+  end
+  
+  def test_alternative_delimiter
+    TagList.delimiter = " "
+    
+    assert_equal %w(One Two), TagList.from("One Two")
+    assert_equal ['One two', 'three', 'four'], TagList.from('"One two" three four')
+  ensure
+    TagList.delimiter = ","
+  end
+  
+  def test_duplicate_tags_removed
+    assert_equal %w(One), TagList.from("One, One")
+  end
+  
+  def test_to_s_with_commas
+    assert_equal "Question, Crazy Animal", TagList.new("Question", "Crazy Animal").to_s
+  end
+  
+  def test_to_s_with_alternative_delimiter
+    TagList.delimiter = " "
+    
+    assert_equal '"Crazy Animal" Question', TagList.new("Crazy Animal", "Question").to_s
+  ensure
+    TagList.delimiter = ","
+  end
+  
+  def test_add
+    tag_list = TagList.new("One")
+    assert_equal %w(One), tag_list
+    
+    assert_equal %w(One Two), tag_list.add("Two")
+    assert_equal %w(One Two Three), tag_list.add(["Three"])
+  end
+  
+  def test_remove
+    tag_list = TagList.new("One", "Two")
+    assert_equal %w(Two), tag_list.remove("One")
+    assert_equal %w(), tag_list.remove(["Two"])
+  end
+  
+  def test_new_with_parsing
+    assert_equal %w(One Two), TagList.new("One, Two", :parse => true)
+  end
+  
+  def test_add_with_parsing
+    assert_equal %w(One Two), TagList.new.add("One, Two", :parse => true)
+  end
+  
+  def test_remove_with_parsing
+    tag_list = TagList.from("Three, Four, Five")
+    assert_equal %w(Four), tag_list.remove("Three, Five", :parse => true)
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_list_test.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_test.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_test.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_test.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_test.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,34 @@
+require File.dirname(__FILE__) + '/abstract_unit'
+
+class TagTest < Test::Unit::TestCase
+  fixtures :tags, :taggings, :users, :photos, :posts
+  
+  def test_name_required
+    t = Tag.create
+    assert_match /blank/, t.errors[:name].to_s
+  end
+  
+  def test_name_unique
+    t = Tag.create!(:name => "My tag")
+    duplicate = t.clone
+    
+    assert !duplicate.save
+    assert_match /taken/, duplicate.errors[:name].to_s
+  end
+  
+  def test_taggings
+    assert_equivalent [taggings(:jonathan_sky_good), taggings(:sam_flowers_good), taggings(:sam_flower_good), taggings(:ruby_good)], tags(:good).taggings
+    assert_equivalent [taggings(:sam_ground_bad), taggings(:jonathan_bad_cat_bad)], tags(:bad).taggings
+  end
+  
+  def test_to_s
+    assert_equal tags(:good).name, tags(:good).to_s
+  end
+  
+  def test_equality
+    assert_equal tags(:good), tags(:good)
+    assert_equal Tag.find(1), Tag.find(1)
+    assert_equal Tag.new(:name => 'A'), Tag.new(:name => 'A')
+    assert_not_equal Tag.new(:name => 'A'), Tag.new(:name => 'B')
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tag_test.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tagging_test.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tagging_test.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tagging_test.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tagging_test.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,13 @@
+require File.dirname(__FILE__) + '/abstract_unit'
+
+class TaggingTest < Test::Unit::TestCase
+  fixtures :tags, :taggings, :posts
+  
+  def test_tag
+    assert_equal tags(:good), taggings(:jonathan_sky_good).tag
+  end
+  
+  def test_taggable
+    assert_equal posts(:jonathan_sky), taggings(:jonathan_sky_good).taggable
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tagging_test.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tags_helper_test.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tags_helper_test.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tags_helper_test.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tags_helper_test.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,28 @@
+require File.dirname(__FILE__) + '/abstract_unit'
+
+class TagsHelperTest < Test::Unit::TestCase
+  fixtures :tags, :taggings, :posts
+  
+  include TagsHelper
+  
+  def test_tag_cloud
+    cloud_elements = []
+    
+    tag_cloud Post.tag_counts, %w(css1 css2 css3 css4) do |tag, css_class|
+      cloud_elements << [tag, css_class]
+    end
+    
+    assert_equal [
+      [tags(:good), "css2"],
+      [tags(:bad), "css1"],
+      [tags(:nature), "css4"],
+      [tags(:question), "css1"]
+    ], cloud_elements
+  end
+  
+  def test_tag_cloud_when_no_tags
+    tag_cloud SpecialPost.tag_counts, %w(css1) do
+      assert false, "tag_cloud should not yield"
+    end
+  end
+end

Propchange: labs/consite/trunk/conferences/vendor/plugins/acts_as_taggable_on_steriods/test/tags_helper_test.rb
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/file_column/CHANGELOG
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/file_column/CHANGELOG?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/file_column/CHANGELOG (added)
+++ labs/consite/trunk/conferences/vendor/plugins/file_column/CHANGELOG Fri Mar 27 10:32:54 2009
@@ -0,0 +1,69 @@
+*svn*
+    * allow for directories in file_column dirs as well
+    * use subdirs for versions instead of fiddling with filename
+    * url_for_image_column_helper for dynamic resizing of images from views
+    * new "crop" feature [Sean Treadway]
+    * url_for_file_column helper: do not require model objects to be stored in
+      instance variables
+    * allow more fined-grained control over :store_dir via callback
+      methods [Gerret Apelt]
+    * allow assignment of regular file objects
+    * validation of file format and file size [Kyle Maxwell]
+    * validation of image dimensions [Lee O'Mara]
+    * file permissions can be set via :permissions option
+    * fixed bug that prevents deleting of file via assigning nil if
+      column is declared as NON NULL on some databases
+    * don't expand absolute paths. This is necessary for file_column to work
+      when your rails app is deployed into a sub-directory via a symbolic link
+    * url_for_*_column will no longer return absolute URLs! Instead, although the
+      generated URL starts with a slash, it will be relative to your application's
+      root URL. This is so, because rails' image_tag helper will automatically
+      convert it to an absolute URL. If you need an absolute URL (e.g., to pass
+      it to link_to) use url_for_file_column's :absolute => true option.
+    * added support for file_column enabled unit tests [Manuel Holtgrewe]
+    * support for custom transformation of images [Frederik Fix]
+    * allow setting of image attributes (e.g., quality) [Frederik Fix]
+    * :magick columns can optionally ignore non-images (i.e., do not try to
+       resize them)
+
+0.3.1
+    * make object with file_columns serializable
+    * use normal require for RMagick, so that it works with gem
+      and custom install as well
+
+0.3
+    * fixed bug where empty file uploads were not recognized with some browsers
+    * fixed bug on windows when "file" utility is not present
+    * added option to disable automatic file extension correction
+    * Only allow one attribute per call to file_column, so that options only
+      apply to one argument
+    * try to detect when people forget to set the form encoding to
+      'multipart/form-data'
+    * converted to rails plugin
+    * easy integration with RMagick
+
+0.2
+    * complete rewrite using state pattern
+    * fixed sanitize filename [Michael Raidel]
+    * fixed bug when no file was uploaded [Michael Raidel]
+    * try to fix filename extensions [Michael Raidel]
+    * Feed absolute paths through File.expand_path to make them as simple as possible
+    * Make file_column_field helper work with auto-ids (e.g., "event[]")
+
+0.1.3
+    * test cases with more than 1 file_column
+    * fixed bug when file_column was called with several arguments
+    * treat empty ("") file_columns as nil
+    * support for binary files on windows
+
+0.1.2
+    * better rails integration, so that you do not have to include the modules yourself. You
+      just have to "require 'rails_file_column'" in your "config/environment.rb"
+    * Rakefile for testing and packaging
+
+0.1.1 (2005-08-11)
+    * fixed nasty bug in url_for_file_column that made it unusable on Apache
+    * prepared for public release
+    
+0.1 (2005-08-10)
+    * initial release

Added: labs/consite/trunk/conferences/vendor/plugins/file_column/README
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/file_column/README?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/file_column/README (added)
+++ labs/consite/trunk/conferences/vendor/plugins/file_column/README Fri Mar 27 10:32:54 2009
@@ -0,0 +1,54 @@
+FEATURES
+========
+
+Let's assume an model class named Entry, where we want to define the "image" column
+as a "file_upload" column.
+
+class Entry < ActiveRecord::Base
+  file_column :image
+end
+
+* every entry can have one uploaded file, the filename will be stored in the "image" column
+
+* files will be stored in "public/entry/image/<entry.id>/filename.ext"
+
+* Newly uploaded files will be stored in "public/entry/tmp/<random>/filename.ext" so that
+  they can be reused in form redisplays (due to validation etc.)
+
+* in a view, "<%= file_column_field 'entry', 'image' %> will create a file upload field as well
+  as a hidden field to recover files uploaded before in a case of a form redisplay
+
+* in a view, "<%= url_for_file_column 'entry', 'image' %> will create an URL to access the
+  uploaded file. Note that you need an Entry object in the instance variable @entry for this
+  to work.
+
+* easy integration with RMagick to resize images and/or create thumb-nails.
+
+USAGE
+=====
+
+Just drop the whole directory into your application's "vendor/plugins" directory. Starting
+with version 1.0rc of rails, it will be automatically picked for you by rails plugin
+mechanism.
+
+DOCUMENTATION
+=============
+
+Please look at the rdoc-generated documentation in the "doc" directory.
+
+RUNNING UNITTESTS
+=================
+
+There are extensive unittests in the "test" directory. Currently, only MySQL is supported, but
+you should be able to easily fix this by looking at "connection.rb". You have to create a
+database for the tests and put the connection information into "connection.rb". The schema
+for MySQL can be found in "test/fixtures/mysql.sql".
+
+You can run the tests by starting the "*_test.rb" in the directory "test"
+
+BUGS & FEEDBACK
+===============
+
+Bug reports (as well as patches) and feedback are very welcome. Please send it to
+sebastian.kanthak@muehlheim.de
+

Propchange: labs/consite/trunk/conferences/vendor/plugins/file_column/README
------------------------------------------------------------------------------
    svn:eol-style = native

Added: labs/consite/trunk/conferences/vendor/plugins/file_column/Rakefile
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/file_column/Rakefile?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/file_column/Rakefile (added)
+++ labs/consite/trunk/conferences/vendor/plugins/file_column/Rakefile Fri Mar 27 10:32:54 2009
@@ -0,0 +1,36 @@
+task :default => [:test]
+
+PKG_NAME = "file-column"
+PKG_VERSION = "0.3.1"
+
+PKG_DIR = "release/#{PKG_NAME}-#{PKG_VERSION}"
+
+task :clean do
+  rm_rf "release"
+end
+
+task :setup_directories do
+  mkpath "release"
+end
+
+
+task :checkout_release => :setup_directories do
+  rm_rf PKG_DIR
+  revision = ENV["REVISION"] || "HEAD"
+  sh "svn export -r #{revision} . #{PKG_DIR}"
+end
+
+task :release_docs => :checkout_release do
+  sh "cd #{PKG_DIR}; rdoc lib"
+end
+
+task :package => [:checkout_release, :release_docs] do
+  sh "cd release; tar czf #{PKG_NAME}-#{PKG_VERSION}.tar.gz #{PKG_NAME}-#{PKG_VERSION}"
+end
+
+task :test do
+  sh "cd test; ruby file_column_test.rb"
+  sh "cd test; ruby file_column_helper_test.rb"
+  sh "cd test; ruby magick_test.rb"
+  sh "cd test; ruby magick_view_only_test.rb"
+end

Added: labs/consite/trunk/conferences/vendor/plugins/file_column/TODO
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/file_column/TODO?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/file_column/TODO (added)
+++ labs/consite/trunk/conferences/vendor/plugins/file_column/TODO Fri Mar 27 10:32:54 2009
@@ -0,0 +1,6 @@
+* document configuration options better
+* support setting of permissions
+* validation methods for file format/size
+* delete stale files from tmp directories
+
+* ensure valid URLs are created even when deployed at sub-path (compute_public_url?)

Added: labs/consite/trunk/conferences/vendor/plugins/file_column/init.rb
URL: http://svn.apache.org/viewvc/labs/consite/trunk/conferences/vendor/plugins/file_column/init.rb?rev=759091&view=auto
==============================================================================
--- labs/consite/trunk/conferences/vendor/plugins/file_column/init.rb (added)
+++ labs/consite/trunk/conferences/vendor/plugins/file_column/init.rb Fri Mar 27 10:32:54 2009
@@ -0,0 +1,13 @@
+# plugin init file for rails
+# this file will be picked up by rails automatically and
+# add the file_column extensions to rails
+
+require 'file_column'
+require 'file_compat'
+require 'file_column_helper'
+require 'validations'
+require 'test_case'
+
+ActiveRecord::Base.send(:include, FileColumn)
+ActionView::Base.send(:include, FileColumnHelper)
+ActiveRecord::Base.send(:include, FileColumn::Validations)
\ No newline at end of file

Propchange: labs/consite/trunk/conferences/vendor/plugins/file_column/init.rb
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org