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