diff options
| author | hukl <hukl@eight.local> | 2009-02-02 23:25:15 +0100 |
|---|---|---|
| committer | hukl <hukl@eight.local> | 2009-02-02 23:25:15 +0100 |
| commit | 1c8bcc58d410db6d7eb5f1629813f08f78f47fa1 (patch) | |
| tree | 4b80c2b39ee2702e52ece2cbaaf507b0910b1437 /vendor | |
| parent | efbd264d62189ac6bbb80961ddef058240f16435 (diff) | |
add acts_as_taggable_on_steroids to replaces
custom flagging facilities
Diffstat (limited to 'vendor')
32 files changed, 1658 insertions, 0 deletions
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/CHANGELOG b/vendor/plugins/acts_as_taggable_on_steroids/CHANGELOG new file mode 100644 index 0000000..f314bd9 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/CHANGELOG | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | [13 March 08] | ||
| 2 | |||
| 3 | * Added helper methods for will_paginate compatibility (Clinton R. Nixon) | ||
| 4 | * Fixed :conditions in tag_counts to accept array to sanitize (Clinton R. Nixon) | ||
| 5 | |||
| 6 | [07 March 08] | ||
| 7 | |||
| 8 | * Added support for regexp delimiter (Matt Aimonetti) | ||
| 9 | |||
| 10 | [30 Jan 08] | ||
| 11 | |||
| 12 | * Fix Tag.destroy_unused on Rails 2.0. | ||
| 13 | |||
| 14 | [23 October 2007] | ||
| 15 | |||
| 16 | * Make find_options_for_tag_counts and find_options_for_tagged_with dup their options. | ||
| 17 | |||
| 18 | * Apply conditions properly in find_options_for_tag_counts. | ||
| 19 | |||
| 20 | * Fix tag_cloud when no tags are present. | ||
| 21 | |||
| 22 | [22 October 2007] | ||
| 23 | |||
| 24 | * Fix find_tagged_with using :match_all and :include. | ||
| 25 | |||
| 26 | * Use inner joins instead of left outer joins. | ||
| 27 | |||
| 28 | [15 October 2007] | ||
| 29 | |||
| 30 | * Make find_tagged_with correctly apply :conditions | ||
| 31 | |||
| 32 | * Add Tag.destroy_unused option. | ||
| 33 | |||
| 34 | [11 October 2007] | ||
| 35 | |||
| 36 | * Make tag_counts work correctly with STI. | ||
| 37 | |||
| 38 | [3 October 2007] | ||
| 39 | |||
| 40 | * Improve documentation. | ||
| 41 | |||
| 42 | * Fix TagsHelper and test. | ||
| 43 | |||
| 44 | [2 October 2007] | ||
| 45 | |||
| 46 | * Remove TagList.parse, use TagList.from instead. | ||
| 47 | |||
| 48 | * Add :parse option to TagList#new, TagList#add, and TagList#remove. | ||
| 49 | |||
| 50 | tag_list = TagList.new("One, Two", :parse => true) # ["One", "Two"] | ||
| 51 | |||
| 52 | tag_list # ["One", "Two"] | ||
| 53 | tag_list.add("Three, Four", :parse => true) # ["One", "Two", "Three", "Four"] | ||
| 54 | |||
| 55 | * Remove TagList#names. | ||
| 56 | |||
| 57 | [29 September 2007] | ||
| 58 | |||
| 59 | * Add TagsHelper to assist with generating tag clouds and provide a simple example. | ||
| 60 | |||
| 61 | [27 September 2007] | ||
| 62 | |||
| 63 | * Add #tag_counts method to get tag counts for a specific object's tags. | ||
| 64 | |||
| 65 | * BACKWARDS INCOMPATIBILITY: Rename #find_options_for_tagged_with to #find_options_for_find_tagged_with | ||
| 66 | |||
| 67 | [17 September 2007] | ||
| 68 | |||
| 69 | * Fix clearing of cached tag list when all tags removed. | ||
| 70 | |||
| 71 | [12 September 2007] | ||
| 72 | |||
| 73 | * Make the TagList class inherit from Array. | ||
| 74 | |||
| 75 | * Deprecate obsolete TagList#names. | ||
| 76 | |||
| 77 | [6 September 2007] | ||
| 78 | |||
| 79 | * Add TagList#include? and TagList#empty? | ||
| 80 | |||
| 81 | [26 August 2006] | ||
| 82 | |||
| 83 | * Remove deprecated Tag.delimiter. Use TagList.delimiter instead. | ||
| 84 | |||
| 85 | [25 August 2007] | ||
| 86 | |||
| 87 | * Make tag_counts work with has_many :through | ||
| 88 | |||
| 89 | [23 August 2007] | ||
| 90 | |||
| 91 | * Make search comparisons case-insensitive across different databases. [Moisés Machado] | ||
| 92 | |||
| 93 | * Improve compatiblity with STI. [Moisés Machado] | ||
| 94 | |||
| 95 | [25 July 2007] | ||
| 96 | |||
| 97 | * Respect custom table names for the Tag and Tagging classes. | ||
| 98 | |||
| 99 | * Fix the :exclude option for find_tagged_with | ||
| 100 | |||
| 101 | [17 July 2007] | ||
| 102 | |||
| 103 | * Make the migration work on edge rails | ||
| 104 | |||
| 105 | [8 July 2007] | ||
| 106 | |||
| 107 | * find_options_for_tagged_with should not alter its arguments | ||
| 108 | |||
| 109 | [1 July 2007] | ||
| 110 | |||
| 111 | * Fix incorrect tagging when the case of the tag list is changed. | ||
| 112 | |||
| 113 | * Fix deprecated Tag.delimiter accessor. | ||
| 114 | |||
| 115 | [23 June 2007] | ||
| 116 | |||
| 117 | * Add validation to Tag model. | ||
| 118 | |||
| 119 | * find_options_for_tagged_with should always return a hash. | ||
| 120 | |||
| 121 | * find_tagged_with passing in no tags should return an empty array. | ||
| 122 | |||
| 123 | * Improve compatibility with PostgreSQL. | ||
| 124 | |||
| 125 | [21 June 2007] | ||
| 126 | |||
| 127 | * Remove extra .rb from generated migration file name. | ||
| 128 | |||
| 129 | [15 June 2007] | ||
| 130 | |||
| 131 | * Introduce TagList class. | ||
| 132 | |||
| 133 | * Various cleanups and improvements. | ||
| 134 | |||
| 135 | * Use TagList.delimiter now, not Tag.delimiter. Tag.delimiter will be removed at some stage. | ||
| 136 | |||
| 137 | [11 June 2007] | ||
| 138 | |||
| 139 | * Restructure the creation of the options for find_tagged_with [Thijs Cadier] | ||
| 140 | |||
| 141 | * Add an example migration with a generator. | ||
| 142 | |||
| 143 | * Add caching. | ||
| 144 | |||
| 145 | * Fix compatibility with Ruby < 1.8.6 | ||
| 146 | |||
| 147 | [23 April 2007] | ||
| 148 | |||
| 149 | * Make tag_list to respect Tag.delimiter | ||
| 150 | |||
| 151 | [31 March 2007] | ||
| 152 | |||
| 153 | * Add Tag.delimiter accessor to change how tags are parsed. | ||
| 154 | |||
| 155 | * Fix :include => :tags when used with find_tagged_with | ||
| 156 | |||
| 157 | [7 March 2007] | ||
| 158 | |||
| 159 | * Fix tag_counts for SQLServer [Brad Young] | ||
| 160 | |||
| 161 | [21 Feb 2007] | ||
| 162 | |||
| 163 | * Use scoping instead of TagCountsExtension [Michael Schuerig] | ||
| 164 | |||
| 165 | [7 Jan 2007] | ||
| 166 | |||
| 167 | * Add :match_all to find_tagged_with [Michael Sheakoski] | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/MIT-LICENSE b/vendor/plugins/acts_as_taggable_on_steroids/MIT-LICENSE new file mode 100644 index 0000000..602bda2 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/MIT-LICENSE | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | Copyright (c) 2006 Jonathan Viney | ||
| 2 | |||
| 3 | Permission is hereby granted, free of charge, to any person obtaining | ||
| 4 | a copy of this software and associated documentation files (the | ||
| 5 | "Software"), to deal in the Software without restriction, including | ||
| 6 | without limitation the rights to use, copy, modify, merge, publish, | ||
| 7 | distribute, sublicense, and/or sell copies of the Software, and to | ||
| 8 | permit persons to whom the Software is furnished to do so, subject to | ||
| 9 | the following conditions: | ||
| 10 | |||
| 11 | The above copyright notice and this permission notice shall be | ||
| 12 | included in all copies or substantial portions of the Software. | ||
| 13 | |||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
| 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
| 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
| 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/README b/vendor/plugins/acts_as_taggable_on_steroids/README new file mode 100644 index 0000000..73b88fe --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/README | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | = acts_as_taggable_on_steroids | ||
| 2 | |||
| 3 | NOT THE OFFICIAL REPO, I just imported this project to get few bug fixed when I was using it for a project in early 2008. | ||
| 4 | |||
| 5 | USE AT YOUR OWN RISK | ||
| 6 | |||
| 7 | |||
| 8 | If you find this plugin useful, please consider a donation to show your support! | ||
| 9 | |||
| 10 | http://www.paypal.com/cgi-bin/webscr?cmd=_send-money | ||
| 11 | |||
| 12 | Email address: jonathan.viney@gmail.com | ||
| 13 | |||
| 14 | == Instructions | ||
| 15 | |||
| 16 | This plugin is based on acts_as_taggable by DHH but includes extras | ||
| 17 | such as tests, smarter tag assignment, and tag cloud calculations. | ||
| 18 | |||
| 19 | == Installation | ||
| 20 | |||
| 21 | ruby script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids | ||
| 22 | |||
| 23 | == Usage | ||
| 24 | |||
| 25 | === Prepare database | ||
| 26 | |||
| 27 | Generate and apply the migration: | ||
| 28 | |||
| 29 | ruby script/generate acts_as_taggable_migration | ||
| 30 | rake db:migrate | ||
| 31 | |||
| 32 | === Basic tagging | ||
| 33 | |||
| 34 | Let's suppose users have many posts and we want those posts to have tags. | ||
| 35 | The first step is to add +acts_as_taggable+ to the Post class: | ||
| 36 | |||
| 37 | class Post < ActiveRecord::Base | ||
| 38 | acts_as_taggable | ||
| 39 | |||
| 40 | belongs_to :user | ||
| 41 | end | ||
| 42 | |||
| 43 | We can now use the tagging methods provided by acts_as_taggable, <tt>#tag_list</tt> and <tt>#tag_list=</tt>. Both these | ||
| 44 | methods work like regular attribute accessors. | ||
| 45 | |||
| 46 | p = Post.find(:first) | ||
| 47 | p.tag_list # [] | ||
| 48 | p.tag_list = "Funny, Silly" | ||
| 49 | p.save | ||
| 50 | p.tag_list # ["Funny", "Silly"] | ||
| 51 | |||
| 52 | You can also add or remove arrays of tags. | ||
| 53 | |||
| 54 | p.tag_list.add("Great", "Awful") | ||
| 55 | p.tag_list.remove("Funny") | ||
| 56 | |||
| 57 | === Finding tagged objects | ||
| 58 | |||
| 59 | To retrieve objects tagged with a certain tag, use find_tagged_with. | ||
| 60 | |||
| 61 | Post.find_tagged_with('Funny, Silly') | ||
| 62 | |||
| 63 | By default, find_tagged_with will find objects that have any of the given tags. To | ||
| 64 | find only objects that are tagged with all the given tags, use match_all. | ||
| 65 | |||
| 66 | Post.find_tagged_with('Funny, Silly', :match_all => true) | ||
| 67 | |||
| 68 | See <tt>ActiveRecord::Acts::Taggable::InstanceMethods</tt> for more methods and options. | ||
| 69 | |||
| 70 | === Tag cloud calculations | ||
| 71 | |||
| 72 | To construct tag clouds, the frequency of each tag needs to be calculated. | ||
| 73 | Because we specified +acts_as_taggable+ on the <tt>Post</tt> class, we can | ||
| 74 | get a calculation of all the tag counts by using <tt>Post.tag_counts</tt>. But what if we wanted a tag count for | ||
| 75 | an single user's posts? To achieve this we call tag_counts on the association: | ||
| 76 | |||
| 77 | User.find(:first).posts.tag_counts | ||
| 78 | |||
| 79 | A helper is included to assist with generating tag clouds. Include it in your helper file: | ||
| 80 | |||
| 81 | module ApplicationHelper | ||
| 82 | include TagsHelper | ||
| 83 | end | ||
| 84 | |||
| 85 | Here is an example that generates a tag cloud. | ||
| 86 | |||
| 87 | Controller: | ||
| 88 | |||
| 89 | class PostController < ApplicationController | ||
| 90 | def tag_cloud | ||
| 91 | @tags = Post.tag_counts | ||
| 92 | end | ||
| 93 | end | ||
| 94 | |||
| 95 | View: | ||
| 96 | <% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %> | ||
| 97 | <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %> | ||
| 98 | <% end %> | ||
| 99 | |||
| 100 | CSS: | ||
| 101 | |||
| 102 | .css1 { font-size: 1.0em; } | ||
| 103 | .css2 { font-size: 1.2em; } | ||
| 104 | .css3 { font-size: 1.4em; } | ||
| 105 | .css4 { font-size: 1.6em; } | ||
| 106 | |||
| 107 | === Caching | ||
| 108 | |||
| 109 | It is useful to cache the list of tags to reduce the number of queries executed. To do this, | ||
| 110 | add a column named <tt>cached_tag_list</tt> to the model which is being tagged. The column should be long enough to hold | ||
| 111 | the full tag list and must have a default value of null, not an empty string. | ||
| 112 | |||
| 113 | class CachePostTagList < ActiveRecord::Migration | ||
| 114 | def self.up | ||
| 115 | add_column :posts, :cached_tag_list, :string | ||
| 116 | end | ||
| 117 | end | ||
| 118 | |||
| 119 | class Post < ActiveRecord::Base | ||
| 120 | acts_as_taggable | ||
| 121 | |||
| 122 | # The caching column defaults to cached_tag_list, but can be changed: | ||
| 123 | # | ||
| 124 | # set_cached_tag_list_column_name "my_caching_column_name" | ||
| 125 | end | ||
| 126 | |||
| 127 | The details of the caching are handled for you. Just continue to use the tag_list accessor as you normally would. | ||
| 128 | Note that the cached tag list will not be updated if you directly create Tagging objects or manually append to the | ||
| 129 | <tt>tags</tt> or <tt>taggings</tt> associations. To update the cached tag list you should call <tt>save_cached_tag_list</tt> manually. | ||
| 130 | |||
| 131 | === Delimiter | ||
| 132 | |||
| 133 | If you want to change the delimiter used to parse and present tags, set TagList.delimiter. | ||
| 134 | For example, to use spaces instead of commas, add the following to config/environment.rb: | ||
| 135 | |||
| 136 | TagList.delimiter = " " | ||
| 137 | |||
| 138 | You can also use a regexp as delimiter: | ||
| 139 | |||
| 140 | TagList.delimiter = /,|;/ | ||
| 141 | |||
| 142 | The above code would parse the string and use ',' and ';' as delimiters. | ||
| 143 | |||
| 144 | === Unused tags | ||
| 145 | |||
| 146 | Set Tag.destroy_unused to remove tags when they are no longer being | ||
| 147 | used to tag any objects. Defaults to false. | ||
| 148 | |||
| 149 | Tag.destroy_unused = true | ||
| 150 | |||
| 151 | === Other | ||
| 152 | |||
| 153 | Problems, comments, and suggestions all welcome. jonathan.viney@gmail.com | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/Rakefile b/vendor/plugins/acts_as_taggable_on_steroids/Rakefile new file mode 100644 index 0000000..d2c0003 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/Rakefile | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | require 'rake' | ||
| 2 | require 'rake/testtask' | ||
| 3 | require 'rake/rdoctask' | ||
| 4 | |||
| 5 | desc 'Default: run unit tests.' | ||
| 6 | task :default => :test | ||
| 7 | |||
| 8 | desc 'Test the acts_as_taggable_on_steroids plugin.' | ||
| 9 | Rake::TestTask.new(:test) do |t| | ||
| 10 | t.libs << 'lib' | ||
| 11 | t.pattern = 'test/**/*_test.rb' | ||
| 12 | t.verbose = true | ||
| 13 | end | ||
| 14 | |||
| 15 | desc 'Generate documentation for the acts_as_taggable_on_steroids plugin.' | ||
| 16 | Rake::RDocTask.new(:rdoc) do |rdoc| | ||
| 17 | rdoc.rdoc_dir = 'rdoc' | ||
| 18 | rdoc.title = 'Acts As Taggable On Steroids' | ||
| 19 | rdoc.options << '--line-numbers' << '--inline-source' | ||
| 20 | rdoc.rdoc_files.include('README') | ||
| 21 | rdoc.rdoc_files.include('lib/**/*.rb') | ||
| 22 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb b/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb new file mode 100644 index 0000000..be9b39c --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | class ActsAsTaggableMigrationGenerator < Rails::Generator::Base | ||
| 2 | def manifest | ||
| 3 | record do |m| | ||
| 4 | m.migration_template 'migration.rb', 'db/migrate' | ||
| 5 | end | ||
| 6 | end | ||
| 7 | |||
| 8 | def file_name | ||
| 9 | "acts_as_taggable_migration" | ||
| 10 | end | ||
| 11 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/templates/migration.rb b/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/templates/migration.rb new file mode 100644 index 0000000..ea0c2cc --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/templates/migration.rb | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | class ActsAsTaggableMigration < ActiveRecord::Migration | ||
| 2 | def self.up | ||
| 3 | create_table :tags do |t| | ||
| 4 | t.column :name, :string | ||
| 5 | end | ||
| 6 | |||
| 7 | create_table :taggings do |t| | ||
| 8 | t.column :tag_id, :integer | ||
| 9 | t.column :taggable_id, :integer | ||
| 10 | |||
| 11 | # You should make sure that the column created is | ||
| 12 | # long enough to store the required class names. | ||
| 13 | t.column :taggable_type, :string | ||
| 14 | |||
| 15 | t.column :created_at, :datetime | ||
| 16 | end | ||
| 17 | |||
| 18 | add_index :taggings, :tag_id | ||
| 19 | add_index :taggings, [:taggable_id, :taggable_type] | ||
| 20 | end | ||
| 21 | |||
| 22 | def self.down | ||
| 23 | drop_table :taggings | ||
| 24 | drop_table :tags | ||
| 25 | end | ||
| 26 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/init.rb b/vendor/plugins/acts_as_taggable_on_steroids/init.rb new file mode 100644 index 0000000..64505b9 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/init.rb | |||
| @@ -0,0 +1 @@ | |||
| require File.dirname(__FILE__) + '/lib/acts_as_taggable' | |||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/acts_as_taggable.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/acts_as_taggable.rb new file mode 100644 index 0000000..d537889 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/acts_as_taggable.rb | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | module ActiveRecord #:nodoc: | ||
| 2 | module Acts #:nodoc: | ||
| 3 | module Taggable #:nodoc: | ||
| 4 | def self.included(base) | ||
| 5 | base.extend(ClassMethods) | ||
| 6 | end | ||
| 7 | |||
| 8 | module ClassMethods | ||
| 9 | def acts_as_taggable | ||
| 10 | has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag | ||
| 11 | has_many :tags, :through => :taggings | ||
| 12 | |||
| 13 | before_save :save_cached_tag_list | ||
| 14 | after_save :save_tags | ||
| 15 | |||
| 16 | include ActiveRecord::Acts::Taggable::InstanceMethods | ||
| 17 | extend ActiveRecord::Acts::Taggable::SingletonMethods | ||
| 18 | |||
| 19 | alias_method_chain :reload, :tag_list | ||
| 20 | end | ||
| 21 | |||
| 22 | def cached_tag_list_column_name | ||
| 23 | "cached_tag_list" | ||
| 24 | end | ||
| 25 | |||
| 26 | def set_cached_tag_list_column_name(value = nil, &block) | ||
| 27 | define_attr_method :cached_tag_list_column_name, value, &block | ||
| 28 | end | ||
| 29 | end | ||
| 30 | |||
| 31 | module SingletonMethods | ||
| 32 | # Pass either a tag string, or an array of strings or tags | ||
| 33 | # | ||
| 34 | # Options: | ||
| 35 | # :exclude - Find models that are not tagged with the given tags | ||
| 36 | # :match_all - Find models that match all of the given tags, not just one | ||
| 37 | # :conditions - A piece of SQL conditions to add to the query | ||
| 38 | def find_tagged_with(*args) | ||
| 39 | options = find_options_for_find_tagged_with(*args) | ||
| 40 | options.blank? ? [] : find(:all, options) | ||
| 41 | end | ||
| 42 | |||
| 43 | # will_paginate's method_missing function wants to hit | ||
| 44 | # find_all_tagged_with if you call paginate_tagged_with, which is | ||
| 45 | # obviously suboptimal | ||
| 46 | def find_all_tagged_with(*args) | ||
| 47 | find_tagged_with(*args) | ||
| 48 | end | ||
| 49 | |||
| 50 | def find_options_for_find_tagged_with(tags, options = {}) | ||
| 51 | tags = tags.is_a?(Array) ? TagList.new(tags.map(&:to_s)) : TagList.from(tags) | ||
| 52 | options = options.dup | ||
| 53 | |||
| 54 | return {} if tags.empty? | ||
| 55 | |||
| 56 | conditions = [] | ||
| 57 | conditions << sanitize_sql(options.delete(:conditions)) if options[:conditions] | ||
| 58 | |||
| 59 | taggings_alias, tags_alias = "#{table_name}_taggings", "#{table_name}_tags" | ||
| 60 | |||
| 61 | if options.delete(:exclude) | ||
| 62 | conditions << <<-END | ||
| 63 | #{table_name}.id NOT IN | ||
| 64 | (SELECT #{Tagging.table_name}.taggable_id FROM #{Tagging.table_name} | ||
| 65 | INNER JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id | ||
| 66 | WHERE #{tags_condition(tags)} AND #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)}) | ||
| 67 | END | ||
| 68 | else | ||
| 69 | if options.delete(:match_all) | ||
| 70 | conditions << <<-END | ||
| 71 | (SELECT COUNT(*) FROM #{Tagging.table_name} | ||
| 72 | INNER JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id | ||
| 73 | WHERE #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)} AND | ||
| 74 | taggable_id = #{table_name}.id AND | ||
| 75 | #{tags_condition(tags)}) = #{tags.size} | ||
| 76 | END | ||
| 77 | else | ||
| 78 | conditions << tags_condition(tags, tags_alias) | ||
| 79 | end | ||
| 80 | end | ||
| 81 | |||
| 82 | { :select => "DISTINCT #{table_name}.*", | ||
| 83 | :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)} " + | ||
| 84 | "INNER JOIN #{Tag.table_name} #{tags_alias} ON #{tags_alias}.id = #{taggings_alias}.tag_id", | ||
| 85 | :conditions => conditions.join(" AND ") | ||
| 86 | }.reverse_merge!(options) | ||
| 87 | end | ||
| 88 | |||
| 89 | # Calculate the tag counts for all tags. | ||
| 90 | # | ||
| 91 | # Options: | ||
| 92 | # :start_at - Restrict the tags to those created after a certain time | ||
| 93 | # :end_at - Restrict the tags to those created before a certain time | ||
| 94 | # :conditions - A piece of SQL conditions to add to the query | ||
| 95 | # :limit - The maximum number of tags to return | ||
| 96 | # :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc' | ||
| 97 | # :at_least - Exclude tags with a frequency less than the given value | ||
| 98 | # :at_most - Exclude tags with a frequency greater than the given value | ||
| 99 | def tag_counts(options = {}) | ||
| 100 | Tag.find(:all, find_options_for_tag_counts(options)) | ||
| 101 | end | ||
| 102 | |||
| 103 | # Find how many objects are tagged with a certain tag. | ||
| 104 | def count_by_tag(tag_name) | ||
| 105 | counts = tag_counts(:conditions => "tags.name = #{quote_value(tag_name)}") | ||
| 106 | counts[0].respond_to?(:count) ? counts[0].count : 0 | ||
| 107 | end | ||
| 108 | |||
| 109 | def find_options_for_tag_counts(options = {}) | ||
| 110 | options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit | ||
| 111 | options = options.dup | ||
| 112 | |||
| 113 | scope = scope(:find) | ||
| 114 | start_at = sanitize_sql(["#{Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] | ||
| 115 | end_at = sanitize_sql(["#{Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at] | ||
| 116 | |||
| 117 | conditions = [ | ||
| 118 | "#{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)}", | ||
| 119 | sanitize_sql(options.delete(:conditions)), | ||
| 120 | scope && scope[:conditions], | ||
| 121 | start_at, | ||
| 122 | end_at | ||
| 123 | ] | ||
| 124 | |||
| 125 | conditions << type_condition unless descends_from_active_record? | ||
| 126 | conditions.compact! | ||
| 127 | conditions = conditions.join(' AND ') | ||
| 128 | |||
| 129 | joins = ["INNER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"] | ||
| 130 | joins << "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{Tagging.table_name}.taggable_id" | ||
| 131 | joins << scope[:joins] if scope && scope[:joins] | ||
| 132 | |||
| 133 | at_least = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least] | ||
| 134 | at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most] | ||
| 135 | having = [at_least, at_most].compact.join(' AND ') | ||
| 136 | group_by = "#{Tag.table_name}.id, #{Tag.table_name}.name HAVING COUNT(*) > 0" | ||
| 137 | group_by << " AND #{having}" unless having.blank? | ||
| 138 | |||
| 139 | { :select => "#{Tag.table_name}.id, #{Tag.table_name}.name, COUNT(*) AS count", | ||
| 140 | :joins => joins.join(" "), | ||
| 141 | :conditions => conditions, | ||
| 142 | :group => group_by | ||
| 143 | }.reverse_merge!(options) | ||
| 144 | end | ||
| 145 | |||
| 146 | def caching_tag_list? | ||
| 147 | column_names.include?(cached_tag_list_column_name) | ||
| 148 | end | ||
| 149 | |||
| 150 | private | ||
| 151 | def tags_condition(tags, table_name = Tag.table_name) | ||
| 152 | condition = tags.map { |t| sanitize_sql(["#{table_name}.name LIKE ?", t]) }.join(" OR ") | ||
| 153 | "(" + condition + ")" | ||
| 154 | end | ||
| 155 | end | ||
| 156 | |||
| 157 | module InstanceMethods | ||
| 158 | def tag_list | ||
| 159 | return @tag_list if @tag_list | ||
| 160 | |||
| 161 | if self.class.caching_tag_list? and !(cached_value = send(self.class.cached_tag_list_column_name)).nil? | ||
| 162 | @tag_list = TagList.from(cached_value) | ||
| 163 | else | ||
| 164 | @tag_list = TagList.new(*tags.map(&:name)) | ||
| 165 | end | ||
| 166 | end | ||
| 167 | |||
| 168 | def tag_list=(value) | ||
| 169 | @tag_list = TagList.from(value) | ||
| 170 | end | ||
| 171 | |||
| 172 | def save_cached_tag_list | ||
| 173 | if self.class.caching_tag_list? | ||
| 174 | self[self.class.cached_tag_list_column_name] = tag_list.to_s | ||
| 175 | end | ||
| 176 | end | ||
| 177 | |||
| 178 | def save_tags | ||
| 179 | return unless @tag_list | ||
| 180 | |||
| 181 | new_tag_names = @tag_list - tags.map(&:name) | ||
| 182 | old_tags = tags.reject { |tag| @tag_list.include?(tag.name) } | ||
| 183 | |||
| 184 | self.class.transaction do | ||
| 185 | if old_tags.any? | ||
| 186 | taggings.find(:all, :conditions => ["tag_id IN (?)", old_tags.map(&:id)]).each(&:destroy) | ||
| 187 | taggings.reset | ||
| 188 | end | ||
| 189 | |||
| 190 | new_tag_names.each do |new_tag_name| | ||
| 191 | tags << Tag.find_or_create_with_like_by_name(new_tag_name) | ||
| 192 | end | ||
| 193 | end | ||
| 194 | |||
| 195 | true | ||
| 196 | end | ||
| 197 | |||
| 198 | # Calculate the tag counts for the tags used by this model. | ||
| 199 | # | ||
| 200 | # The possible options are the same as the tag_counts class method, excluding :conditions. | ||
| 201 | def tag_counts(options = {}) | ||
| 202 | self.class.tag_counts({ :conditions => self.class.send(:tags_condition, tag_list) }.reverse_merge!(options)) | ||
| 203 | end | ||
| 204 | |||
| 205 | def reload_with_tag_list(*args) #:nodoc: | ||
| 206 | @tag_list = nil | ||
| 207 | reload_without_tag_list(*args) | ||
| 208 | end | ||
| 209 | end | ||
| 210 | end | ||
| 211 | end | ||
| 212 | end | ||
| 213 | |||
| 214 | ActiveRecord::Base.send(:include, ActiveRecord::Acts::Taggable) | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/tag.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag.rb new file mode 100644 index 0000000..91859d5 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag.rb | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | class Tag < ActiveRecord::Base | ||
| 2 | has_many :taggings | ||
| 3 | |||
| 4 | validates_presence_of :name | ||
| 5 | validates_uniqueness_of :name | ||
| 6 | |||
| 7 | cattr_accessor :destroy_unused | ||
| 8 | self.destroy_unused = false | ||
| 9 | |||
| 10 | # LIKE is used for cross-database case-insensitivity | ||
| 11 | def self.find_or_create_with_like_by_name(name) | ||
| 12 | find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name) | ||
| 13 | end | ||
| 14 | |||
| 15 | def ==(object) | ||
| 16 | super || (object.is_a?(Tag) && name == object.name) | ||
| 17 | end | ||
| 18 | |||
| 19 | def to_s | ||
| 20 | name | ||
| 21 | end | ||
| 22 | |||
| 23 | def count | ||
| 24 | read_attribute(:count).to_i | ||
| 25 | end | ||
| 26 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_counts_extension.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_counts_extension.rb new file mode 100644 index 0000000..a1d13b8 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_counts_extension.rb | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | # Deprecated | ||
| 2 | module TagCountsExtension #:nodoc: | ||
| 3 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_list.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_list.rb new file mode 100644 index 0000000..01325b8 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/tag_list.rb | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | class TagList < Array | ||
| 2 | cattr_accessor :delimiter | ||
| 3 | self.delimiter = ',' | ||
| 4 | |||
| 5 | def initialize(*args) | ||
| 6 | add(*args) | ||
| 7 | end | ||
| 8 | |||
| 9 | # Add tags to the tag_list. Duplicate or blank tags will be ignored. | ||
| 10 | # | ||
| 11 | # tag_list.add("Fun", "Happy") | ||
| 12 | # | ||
| 13 | # Use the <tt>:parse</tt> option to add an unparsed tag string. | ||
| 14 | # | ||
| 15 | # tag_list.add("Fun, Happy", :parse => true) | ||
| 16 | def add(*names) | ||
| 17 | extract_and_apply_options!(names) | ||
| 18 | concat(names) | ||
| 19 | clean! | ||
| 20 | self | ||
| 21 | end | ||
| 22 | |||
| 23 | # Remove specific tags from the tag_list. | ||
| 24 | # | ||
| 25 | # tag_list.remove("Sad", "Lonely") | ||
| 26 | # | ||
| 27 | # Like #add, the <tt>:parse</tt> option can be used to remove multiple tags in a string. | ||
| 28 | # | ||
| 29 | # tag_list.remove("Sad, Lonely", :parse => true) | ||
| 30 | def remove(*names) | ||
| 31 | extract_and_apply_options!(names) | ||
| 32 | delete_if { |name| names.include?(name) } | ||
| 33 | self | ||
| 34 | end | ||
| 35 | |||
| 36 | # Transform the tag_list into a tag string suitable for edting in a form. | ||
| 37 | # The tags are joined with <tt>TagList.delimiter</tt> and quoted if necessary. | ||
| 38 | # | ||
| 39 | # tag_list = TagList.new("Round", "Square,Cube") | ||
| 40 | # tag_list.to_s # 'Round, "Square,Cube"' | ||
| 41 | def to_s | ||
| 42 | clean! | ||
| 43 | |||
| 44 | list = map do |name| | ||
| 45 | if delimiter.is_a?(Regexp) | ||
| 46 | name.match(delimiter) ? "\"#{name}\"" : name | ||
| 47 | else | ||
| 48 | name.include?(delimiter) ? "\"#{name}\"" : name | ||
| 49 | end | ||
| 50 | end | ||
| 51 | |||
| 52 | list.join( delimiter.is_a?(Regexp) ? "#{delimiter.source.match(/[^\\\[\]\*\?\{\}\.\|]/)[0]} " : (delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ") ) | ||
| 53 | end | ||
| 54 | |||
| 55 | private | ||
| 56 | # Remove whitespace, duplicates, and blanks. | ||
| 57 | def clean! | ||
| 58 | reject!(&:blank?) | ||
| 59 | map!(&:strip) | ||
| 60 | uniq! | ||
| 61 | end | ||
| 62 | |||
| 63 | def extract_and_apply_options!(args) | ||
| 64 | options = args.last.is_a?(Hash) ? args.pop : {} | ||
| 65 | options.assert_valid_keys :parse | ||
| 66 | |||
| 67 | if options[:parse] | ||
| 68 | args.map! { |a| self.class.from(a) } | ||
| 69 | end | ||
| 70 | |||
| 71 | args.flatten! | ||
| 72 | end | ||
| 73 | |||
| 74 | class << self | ||
| 75 | # Returns a new TagList using the given tag string. | ||
| 76 | # | ||
| 77 | # tag_list = TagList.from("One , Two, Three") | ||
| 78 | # tag_list # ["One", "Two", "Three"] | ||
| 79 | def from(string) | ||
| 80 | returning new do |tag_list| | ||
| 81 | string = string.to_s.gsub('.', '').dup | ||
| 82 | |||
| 83 | # Parse the quoted tags | ||
| 84 | string.gsub!(/"(.*?)"\s*#{delimiter}?\s*/) { tag_list << $1; "" } | ||
| 85 | string.gsub!(/'(.*?)'\s*#{delimiter}?\s*/) { tag_list << $1; "" } | ||
| 86 | |||
| 87 | tag_list.add(string.split(delimiter)) | ||
| 88 | end | ||
| 89 | end | ||
| 90 | end | ||
| 91 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/tagging.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/tagging.rb new file mode 100644 index 0000000..87bc44d --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/tagging.rb | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | class Tagging < ActiveRecord::Base #:nodoc: | ||
| 2 | belongs_to :tag | ||
| 3 | belongs_to :taggable, :polymorphic => true | ||
| 4 | |||
| 5 | def after_destroy | ||
| 6 | if Tag.destroy_unused | ||
| 7 | if tag.taggings.count.zero? | ||
| 8 | tag.destroy | ||
| 9 | end | ||
| 10 | end | ||
| 11 | end | ||
| 12 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/lib/tags_helper.rb b/vendor/plugins/acts_as_taggable_on_steroids/lib/tags_helper.rb new file mode 100644 index 0000000..d5644b7 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/lib/tags_helper.rb | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | module TagsHelper | ||
| 2 | # See the README for an example using tag_cloud. | ||
| 3 | def tag_cloud(tags, classes) | ||
| 4 | return if tags.empty? | ||
| 5 | |||
| 6 | max_count = tags.sort_by(&:count).last.count.to_f | ||
| 7 | |||
| 8 | tags.each do |tag| | ||
| 9 | index = ((tag.count / max_count) * (classes.size - 1)).round | ||
| 10 | yield tag, classes[index] | ||
| 11 | end | ||
| 12 | end | ||
| 13 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/abstract_unit.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/abstract_unit.rb new file mode 100644 index 0000000..42e277a --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/abstract_unit.rb | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | require 'test/unit' | ||
| 2 | |||
| 3 | begin | ||
| 4 | require File.dirname(__FILE__) + '/../../../../config/environment' | ||
| 5 | rescue LoadError | ||
| 6 | require 'rubygems' | ||
| 7 | gem 'activerecord' | ||
| 8 | gem 'actionpack' | ||
| 9 | require 'active_record' | ||
| 10 | require 'action_controller' | ||
| 11 | end | ||
| 12 | |||
| 13 | # Search for fixtures first | ||
| 14 | fixture_path = File.dirname(__FILE__) + '/fixtures/' | ||
| 15 | Dependencies.load_paths.insert(0, fixture_path) | ||
| 16 | |||
| 17 | require 'active_record/fixtures' | ||
| 18 | |||
| 19 | require File.dirname(__FILE__) + '/../lib/acts_as_taggable' | ||
| 20 | require_dependency File.dirname(__FILE__) + '/../lib/tag_list' | ||
| 21 | require_dependency File.dirname(__FILE__) + '/../lib/tags_helper' | ||
| 22 | |||
| 23 | ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + '/debug.log') | ||
| 24 | ActiveRecord::Base.configurations = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) | ||
| 25 | ActiveRecord::Base.establish_connection(ENV['DB'] || 'mysql') | ||
| 26 | |||
| 27 | load(File.dirname(__FILE__) + '/schema.rb') | ||
| 28 | |||
| 29 | Test::Unit::TestCase.fixture_path = fixture_path | ||
| 30 | |||
| 31 | class Test::Unit::TestCase #:nodoc: | ||
| 32 | self.use_transactional_fixtures = true | ||
| 33 | self.use_instantiated_fixtures = false | ||
| 34 | |||
| 35 | def assert_equivalent(expected, actual, message = nil) | ||
| 36 | if expected.first.is_a?(ActiveRecord::Base) | ||
| 37 | assert_equal expected.sort_by(&:id), actual.sort_by(&:id), message | ||
| 38 | else | ||
| 39 | assert_equal expected.sort, actual.sort, message | ||
| 40 | end | ||
| 41 | end | ||
| 42 | |||
| 43 | def assert_tag_counts(tags, expected_values) | ||
| 44 | # Map the tag fixture names to real tag names | ||
| 45 | expected_values = expected_values.inject({}) do |hash, (tag, count)| | ||
| 46 | hash[tags(tag).name] = count | ||
| 47 | hash | ||
| 48 | end | ||
| 49 | |||
| 50 | tags.each do |tag| | ||
| 51 | value = expected_values.delete(tag.name) | ||
| 52 | |||
| 53 | assert_not_nil value, "Expected count for #{tag.name} was not provided" | ||
| 54 | assert_equal value, tag.count, "Expected value of #{value} for #{tag.name}, but was #{tag.count}" | ||
| 55 | end | ||
| 56 | |||
| 57 | unless expected_values.empty? | ||
| 58 | assert false, "The following tag counts were not present: #{expected_values.inspect}" | ||
| 59 | end | ||
| 60 | end | ||
| 61 | |||
| 62 | def assert_queries(num = 1) | ||
| 63 | $query_count = 0 | ||
| 64 | yield | ||
| 65 | ensure | ||
| 66 | assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed." | ||
| 67 | end | ||
| 68 | |||
| 69 | def assert_no_queries(&block) | ||
| 70 | assert_queries(0, &block) | ||
| 71 | end | ||
| 72 | |||
| 73 | # From Rails trunk | ||
| 74 | def assert_difference(expressions, difference = 1, message = nil, &block) | ||
| 75 | expression_evaluations = [expressions].flatten.collect{|expression| lambda { eval(expression, block.binding) } } | ||
| 76 | |||
| 77 | original_values = expression_evaluations.inject([]) { |memo, expression| memo << expression.call } | ||
| 78 | yield | ||
| 79 | expression_evaluations.each_with_index do |expression, i| | ||
| 80 | assert_equal original_values[i] + difference, expression.call, message | ||
| 81 | end | ||
| 82 | end | ||
| 83 | |||
| 84 | def assert_no_difference(expressions, message = nil, &block) | ||
| 85 | assert_difference expressions, 0, message, &block | ||
| 86 | end | ||
| 87 | end | ||
| 88 | |||
| 89 | ActiveRecord::Base.connection.class.class_eval do | ||
| 90 | def execute_with_counting(sql, name = nil, &block) | ||
| 91 | $query_count ||= 0 | ||
| 92 | $query_count += 1 | ||
| 93 | execute_without_counting(sql, name, &block) | ||
| 94 | end | ||
| 95 | |||
| 96 | alias_method_chain :execute, :counting | ||
| 97 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/acts_as_taggable_test.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/acts_as_taggable_test.rb new file mode 100644 index 0000000..90ea3c4 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/acts_as_taggable_test.rb | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | require File.dirname(__FILE__) + '/abstract_unit' | ||
| 2 | |||
| 3 | class ActsAsTaggableOnSteroidsTest < Test::Unit::TestCase | ||
| 4 | fixtures :tags, :taggings, :posts, :users, :photos, :subscriptions, :magazines | ||
| 5 | |||
| 6 | def test_find_tagged_with | ||
| 7 | assert_equivalent [posts(:jonathan_sky), posts(:sam_flowers)], Post.find_tagged_with('"Very good"') | ||
| 8 | assert_equal Post.find_tagged_with('"Very good"'), Post.find_tagged_with(['Very good']) | ||
| 9 | assert_equal Post.find_tagged_with('"Very good"'), Post.find_tagged_with([tags(:good)]) | ||
| 10 | |||
| 11 | assert_equivalent [photos(:jonathan_dog), photos(:sam_flower), photos(:sam_sky)], Photo.find_tagged_with('Nature') | ||
| 12 | assert_equal Photo.find_tagged_with('Nature'), Photo.find_tagged_with(['Nature']) | ||
| 13 | assert_equal Photo.find_tagged_with('Nature'), Photo.find_tagged_with([tags(:nature)]) | ||
| 14 | |||
| 15 | assert_equivalent [photos(:jonathan_bad_cat), photos(:jonathan_dog), photos(:jonathan_questioning_dog)], Photo.find_tagged_with('"Crazy animal" Bad') | ||
| 16 | assert_equal Photo.find_tagged_with('"Crazy animal" Bad'), Photo.find_tagged_with(['Crazy animal', 'Bad']) | ||
| 17 | assert_equal Photo.find_tagged_with('"Crazy animal" Bad'), Photo.find_tagged_with([tags(:animal), tags(:bad)]) | ||
| 18 | end | ||
| 19 | |||
| 20 | def test_find_tagged_with_nothing | ||
| 21 | assert_equal [], Post.find_tagged_with("") | ||
| 22 | assert_equal [], Post.find_tagged_with([]) | ||
| 23 | end | ||
| 24 | |||
| 25 | def test_find_tagged_with_nonexistant_tags | ||
| 26 | assert_equal [], Post.find_tagged_with('ABCDEFG') | ||
| 27 | assert_equal [], Photo.find_tagged_with(['HIJKLM']) | ||
| 28 | assert_equal [], Photo.find_tagged_with([Tag.new(:name => 'unsaved tag')]) | ||
| 29 | end | ||
| 30 | |||
| 31 | def test_find_tagged_with_match_all | ||
| 32 | assert_equivalent [photos(:jonathan_dog)], Photo.find_tagged_with('Crazy animal, "Nature"', :match_all => true) | ||
| 33 | end | ||
| 34 | |||
| 35 | def test_find_tagged_with_match_all_and_include | ||
| 36 | assert_equivalent [posts(:jonathan_sky), posts(:sam_flowers)], Post.find_tagged_with(['Very good', 'Nature'], :match_all => true, :include => :tags) | ||
| 37 | end | ||
| 38 | |||
| 39 | def test_find_tagged_with_conditions | ||
| 40 | assert_equal [], Post.find_tagged_with('"Very good", Nature', :conditions => '1=0') | ||
| 41 | end | ||
| 42 | |||
| 43 | def test_find_tagged_with_duplicates_options_hash | ||
| 44 | options = { :conditions => '1=1' }.freeze | ||
| 45 | assert_nothing_raised { Post.find_tagged_with("Nature", options) } | ||
| 46 | end | ||
| 47 | |||
| 48 | def test_find_tagged_with_exclusions | ||
| 49 | assert_equivalent [photos(:jonathan_questioning_dog), photos(:jonathan_bad_cat)], Photo.find_tagged_with("Nature", :exclude => true) | ||
| 50 | assert_equivalent [posts(:jonathan_grass), posts(:jonathan_rain), posts(:jonathan_cloudy), posts(:jonathan_still_cloudy)], Post.find_tagged_with("'Very good', Bad", :exclude => true) | ||
| 51 | end | ||
| 52 | |||
| 53 | def test_find_options_for_find_tagged_with_no_tags_returns_empty_hash | ||
| 54 | assert_equal Hash.new, Post.find_options_for_find_tagged_with("") | ||
| 55 | assert_equal Hash.new, Post.find_options_for_find_tagged_with([nil]) | ||
| 56 | end | ||
| 57 | |||
| 58 | def test_find_options_for_find_tagged_with_leaves_arguments_unchanged | ||
| 59 | original_tags = photos(:jonathan_questioning_dog).tags.dup | ||
| 60 | Photo.find_options_for_find_tagged_with(photos(:jonathan_questioning_dog).tags) | ||
| 61 | assert_equal original_tags, photos(:jonathan_questioning_dog).tags | ||
| 62 | end | ||
| 63 | |||
| 64 | def test_find_options_for_find_tagged_with_respects_custom_table_name | ||
| 65 | Tagging.table_name = "categorisations" | ||
| 66 | Tag.table_name = "categories" | ||
| 67 | |||
| 68 | options = Photo.find_options_for_find_tagged_with("Hello") | ||
| 69 | |||
| 70 | assert_no_match(/ taggings /, options[:joins]) | ||
| 71 | assert_no_match(/ tags /, options[:joins]) | ||
| 72 | |||
| 73 | assert_match(/ categorisations /, options[:joins]) | ||
| 74 | assert_match(/ categories /, options[:joins]) | ||
| 75 | ensure | ||
| 76 | Tagging.table_name = "taggings" | ||
| 77 | Tag.table_name = "tags" | ||
| 78 | end | ||
| 79 | |||
| 80 | def test_include_tags_on_find_tagged_with | ||
| 81 | assert_nothing_raised do | ||
| 82 | Photo.find_tagged_with('Nature', :include => :tags) | ||
| 83 | Photo.find_tagged_with("Nature", :include => { :taggings => :tag }) | ||
| 84 | end | ||
| 85 | end | ||
| 86 | |||
| 87 | def test_basic_tag_counts_on_class | ||
| 88 | assert_tag_counts Post.tag_counts, :good => 2, :nature => 7, :question => 1, :bad => 1 | ||
| 89 | assert_tag_counts Photo.tag_counts, :good => 1, :nature => 3, :question => 1, :bad => 1, :animal => 3 | ||
| 90 | end | ||
| 91 | |||
| 92 | def test_tag_counts_on_class_with_date_conditions | ||
| 93 | assert_tag_counts Post.tag_counts(:start_at => Date.new(2006, 8, 4)), :good => 1, :nature => 5, :question => 1, :bad => 1 | ||
| 94 | assert_tag_counts Post.tag_counts(:end_at => Date.new(2006, 8, 6)), :good => 1, :nature => 4, :question => 1 | ||
| 95 | 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 | ||
| 96 | |||
| 97 | 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 | ||
| 98 | end | ||
| 99 | |||
| 100 | def test_tag_counts_on_class_with_frequencies | ||
| 101 | assert_tag_counts Photo.tag_counts(:at_least => 2), :nature => 3, :animal => 3 | ||
| 102 | assert_tag_counts Photo.tag_counts(:at_most => 2), :good => 1, :question => 1, :bad => 1 | ||
| 103 | end | ||
| 104 | |||
| 105 | def test_tag_counts_on_class_with_frequencies_and_conditions | ||
| 106 | assert_tag_counts Photo.tag_counts(:at_least => 2, :conditions => '1=1'), :nature => 3, :animal => 3 | ||
| 107 | end | ||
| 108 | |||
| 109 | def test_tag_counts_duplicates_options_hash | ||
| 110 | options = { :at_least => 2, :conditions => '1=1' }.freeze | ||
| 111 | assert_nothing_raised { Photo.tag_counts(options) } | ||
| 112 | end | ||
| 113 | |||
| 114 | def test_tag_counts_with_limit | ||
| 115 | assert_equal 2, Photo.tag_counts(:limit => 2).size | ||
| 116 | assert_equal 1, Post.tag_counts(:at_least => 4, :limit => 2).size | ||
| 117 | end | ||
| 118 | |||
| 119 | def test_tag_counts_with_limit_and_order | ||
| 120 | assert_equal [tags(:nature), tags(:good)], Post.tag_counts(:order => 'count desc', :limit => 2) | ||
| 121 | end | ||
| 122 | |||
| 123 | def test_tag_counts_on_association | ||
| 124 | assert_tag_counts users(:jonathan).posts.tag_counts, :good => 1, :nature => 5, :question => 1 | ||
| 125 | assert_tag_counts users(:sam).posts.tag_counts, :good => 1, :nature => 2, :bad => 1 | ||
| 126 | |||
| 127 | assert_tag_counts users(:jonathan).photos.tag_counts, :animal => 3, :nature => 1, :question => 1, :bad => 1 | ||
| 128 | assert_tag_counts users(:sam).photos.tag_counts, :nature => 2, :good => 1 | ||
| 129 | end | ||
| 130 | |||
| 131 | def test_tag_counts_on_association_with_options | ||
| 132 | assert_equal [], users(:jonathan).posts.tag_counts(:conditions => '1=0') | ||
| 133 | assert_tag_counts users(:jonathan).posts.tag_counts(:at_most => 2), :good => 1, :question => 1 | ||
| 134 | end | ||
| 135 | |||
| 136 | def test_tag_counts_on_has_many_through | ||
| 137 | assert_tag_counts users(:jonathan).magazines.tag_counts, :good => 1 | ||
| 138 | end | ||
| 139 | |||
| 140 | def test_tag_counts_respects_custom_table_names | ||
| 141 | Tagging.table_name = "categorisations" | ||
| 142 | Tag.table_name = "categories" | ||
| 143 | |||
| 144 | options = Photo.find_options_for_tag_counts(:start_at => 2.weeks.ago, :end_at => Date.today) | ||
| 145 | sql = options.values.join(' ') | ||
| 146 | |||
| 147 | assert_no_match /taggings/, sql | ||
| 148 | assert_no_match /tags/, sql | ||
| 149 | |||
| 150 | assert_match /categorisations/, sql | ||
| 151 | assert_match /categories/, sql | ||
| 152 | ensure | ||
| 153 | Tagging.table_name = "taggings" | ||
| 154 | Tag.table_name = "tags" | ||
| 155 | end | ||
| 156 | |||
| 157 | def test_tag_list_reader | ||
| 158 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 159 | assert_equivalent ["Bad", "Crazy animal"], photos(:jonathan_bad_cat).tag_list | ||
| 160 | end | ||
| 161 | |||
| 162 | def test_reassign_tag_list | ||
| 163 | assert_equivalent ["Nature", "Question"], posts(:jonathan_rain).tag_list | ||
| 164 | posts(:jonathan_rain).taggings.reload | ||
| 165 | |||
| 166 | # Only an update of the posts table should be executed | ||
| 167 | assert_queries 1 do | ||
| 168 | posts(:jonathan_rain).update_attributes!(:tag_list => posts(:jonathan_rain).tag_list.to_s) | ||
| 169 | end | ||
| 170 | |||
| 171 | assert_equivalent ["Nature", "Question"], posts(:jonathan_rain).tag_list | ||
| 172 | end | ||
| 173 | |||
| 174 | def test_new_tags | ||
| 175 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 176 | posts(:jonathan_sky).update_attributes!(:tag_list => "#{posts(:jonathan_sky).tag_list}, One, Two") | ||
| 177 | assert_equivalent ["Very good", "Nature", "One", "Two"], posts(:jonathan_sky).tag_list | ||
| 178 | end | ||
| 179 | |||
| 180 | def test_remove_tag | ||
| 181 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 182 | posts(:jonathan_sky).update_attributes!(:tag_list => "Nature") | ||
| 183 | assert_equivalent ["Nature"], posts(:jonathan_sky).tag_list | ||
| 184 | end | ||
| 185 | |||
| 186 | def test_change_case_of_tags | ||
| 187 | original_tag_names = photos(:jonathan_questioning_dog).tag_list | ||
| 188 | photos(:jonathan_questioning_dog).update_attributes!(:tag_list => photos(:jonathan_questioning_dog).tag_list.to_s.upcase) | ||
| 189 | |||
| 190 | # The new tag list is not uppercase becuase the AR finders are not case-sensitive | ||
| 191 | # and find the old tags when re-tagging with the uppercase tags. | ||
| 192 | assert_equivalent original_tag_names, photos(:jonathan_questioning_dog).reload.tag_list | ||
| 193 | end | ||
| 194 | |||
| 195 | def test_remove_and_add_tag | ||
| 196 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 197 | posts(:jonathan_sky).update_attributes!(:tag_list => "Nature, Beautiful") | ||
| 198 | assert_equivalent ["Nature", "Beautiful"], posts(:jonathan_sky).tag_list | ||
| 199 | end | ||
| 200 | |||
| 201 | def test_tags_not_saved_if_validation_fails | ||
| 202 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 203 | assert !posts(:jonathan_sky).update_attributes(:tag_list => "One, Two", :text => "") | ||
| 204 | assert_equivalent ["Very good", "Nature"], Post.find(posts(:jonathan_sky).id).tag_list | ||
| 205 | end | ||
| 206 | |||
| 207 | def test_tag_list_accessors_on_new_record | ||
| 208 | p = Post.new(:text => 'Test') | ||
| 209 | |||
| 210 | assert p.tag_list.blank? | ||
| 211 | p.tag_list = "One, Two" | ||
| 212 | assert_equal "One, Two", p.tag_list.to_s | ||
| 213 | end | ||
| 214 | |||
| 215 | def test_clear_tag_list_with_nil | ||
| 216 | p = photos(:jonathan_questioning_dog) | ||
| 217 | |||
| 218 | assert !p.tag_list.blank? | ||
| 219 | assert p.update_attributes(:tag_list => nil) | ||
| 220 | assert p.tag_list.blank? | ||
| 221 | |||
| 222 | assert p.reload.tag_list.blank? | ||
| 223 | end | ||
| 224 | |||
| 225 | def test_clear_tag_list_with_string | ||
| 226 | p = photos(:jonathan_questioning_dog) | ||
| 227 | |||
| 228 | assert !p.tag_list.blank? | ||
| 229 | assert p.update_attributes(:tag_list => ' ') | ||
| 230 | assert p.tag_list.blank? | ||
| 231 | |||
| 232 | assert p.reload.tag_list.blank? | ||
| 233 | end | ||
| 234 | |||
| 235 | def test_tag_list_reset_on_reload | ||
| 236 | p = photos(:jonathan_questioning_dog) | ||
| 237 | assert !p.tag_list.blank? | ||
| 238 | p.tag_list = nil | ||
| 239 | assert p.tag_list.blank? | ||
| 240 | assert !p.reload.tag_list.blank? | ||
| 241 | end | ||
| 242 | |||
| 243 | def test_instance_tag_counts | ||
| 244 | assert_tag_counts posts(:jonathan_sky).tag_counts, :good => 2, :nature => 7 | ||
| 245 | end | ||
| 246 | |||
| 247 | def test_tag_list_populated_when_cache_nil | ||
| 248 | assert_nil posts(:jonathan_sky).cached_tag_list | ||
| 249 | posts(:jonathan_sky).save! | ||
| 250 | assert_equal posts(:jonathan_sky).tag_list.to_s, posts(:jonathan_sky).cached_tag_list | ||
| 251 | end | ||
| 252 | |||
| 253 | def test_cached_tag_list_used | ||
| 254 | posts(:jonathan_sky).save! | ||
| 255 | posts(:jonathan_sky).reload | ||
| 256 | |||
| 257 | assert_no_queries do | ||
| 258 | assert_equivalent ["Very good", "Nature"], posts(:jonathan_sky).tag_list | ||
| 259 | end | ||
| 260 | end | ||
| 261 | |||
| 262 | def test_cached_tag_list_not_used | ||
| 263 | # Load fixture and column information | ||
| 264 | posts(:jonathan_sky).taggings(:reload) | ||
| 265 | |||
| 266 | assert_queries 1 do | ||
| 267 | # Tags association will be loaded | ||
| 268 | posts(:jonathan_sky).tag_list | ||
| 269 | end | ||
| 270 | end | ||
| 271 | |||
| 272 | def test_cached_tag_list_updated | ||
| 273 | assert_nil posts(:jonathan_sky).cached_tag_list | ||
| 274 | posts(:jonathan_sky).save! | ||
| 275 | assert_equivalent ["Very good", "Nature"], TagList.from(posts(:jonathan_sky).cached_tag_list) | ||
| 276 | posts(:jonathan_sky).update_attributes!(:tag_list => "None") | ||
| 277 | |||
| 278 | assert_equal 'None', posts(:jonathan_sky).cached_tag_list | ||
| 279 | assert_equal 'None', posts(:jonathan_sky).reload.cached_tag_list | ||
| 280 | end | ||
| 281 | |||
| 282 | def test_clearing_cached_tag_list | ||
| 283 | # Generate the cached tag list | ||
| 284 | posts(:jonathan_sky).save! | ||
| 285 | |||
| 286 | posts(:jonathan_sky).update_attributes!(:tag_list => "") | ||
| 287 | assert_equal "", posts(:jonathan_sky).cached_tag_list | ||
| 288 | end | ||
| 289 | |||
| 290 | def test_find_tagged_with_using_sti | ||
| 291 | special_post = SpecialPost.create!(:text => "Test", :tag_list => "Random") | ||
| 292 | |||
| 293 | assert_equal [special_post], SpecialPost.find_tagged_with("Random") | ||
| 294 | assert Post.find_tagged_with("Random").include?(special_post) | ||
| 295 | end | ||
| 296 | |||
| 297 | def test_tag_counts_using_sti | ||
| 298 | SpecialPost.create!(:text => "Test", :tag_list => "Nature") | ||
| 299 | |||
| 300 | assert_tag_counts SpecialPost.tag_counts, :nature => 1 | ||
| 301 | end | ||
| 302 | |||
| 303 | def test_case_insensitivity | ||
| 304 | assert_difference "Tag.count", 1 do | ||
| 305 | Post.create!(:text => "Test", :tag_list => "one") | ||
| 306 | Post.create!(:text => "Test", :tag_list => "One") | ||
| 307 | end | ||
| 308 | |||
| 309 | assert_equal Post.find_tagged_with("Nature"), Post.find_tagged_with("nature") | ||
| 310 | end | ||
| 311 | |||
| 312 | def test_tag_not_destroyed_when_unused | ||
| 313 | posts(:jonathan_sky).tag_list.add("Random") | ||
| 314 | posts(:jonathan_sky).save! | ||
| 315 | |||
| 316 | assert_no_difference 'Tag.count' do | ||
| 317 | posts(:jonathan_sky).tag_list.remove("Random") | ||
| 318 | posts(:jonathan_sky).save! | ||
| 319 | end | ||
| 320 | end | ||
| 321 | |||
| 322 | def test_tag_destroyed_when_unused | ||
| 323 | Tag.destroy_unused = true | ||
| 324 | |||
| 325 | posts(:jonathan_sky).tag_list.add("Random") | ||
| 326 | posts(:jonathan_sky).save! | ||
| 327 | |||
| 328 | assert_difference 'Tag.count', -1 do | ||
| 329 | posts(:jonathan_sky).tag_list.remove("Random") | ||
| 330 | posts(:jonathan_sky).save! | ||
| 331 | end | ||
| 332 | ensure | ||
| 333 | Tag.destroy_unused = false | ||
| 334 | end | ||
| 335 | end | ||
| 336 | |||
| 337 | class ActsAsTaggableOnSteroidsFormTest < Test::Unit::TestCase | ||
| 338 | fixtures :tags, :taggings, :posts, :users, :photos | ||
| 339 | |||
| 340 | include ActionView::Helpers::FormHelper | ||
| 341 | |||
| 342 | def test_tag_list_contents | ||
| 343 | fields_for :post, posts(:jonathan_sky) do |f| | ||
| 344 | assert_match /Very good, Nature/, f.text_field(:tag_list) | ||
| 345 | end | ||
| 346 | end | ||
| 347 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazine.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazine.rb new file mode 100644 index 0000000..554afe4 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazine.rb | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | class Magazine < ActiveRecord::Base | ||
| 2 | acts_as_taggable | ||
| 3 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazines.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazines.yml new file mode 100644 index 0000000..044ce6d --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/magazines.yml | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | ruby: | ||
| 2 | id: 1 | ||
| 3 | name: Ruby | ||
| 4 | |||
| 5 | rails: | ||
| 6 | id: 2 | ||
| 7 | name: Rails \ No newline at end of file | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photo.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photo.rb new file mode 100644 index 0000000..224957f --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photo.rb | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | class Photo < ActiveRecord::Base | ||
| 2 | acts_as_taggable | ||
| 3 | |||
| 4 | belongs_to :user | ||
| 5 | end | ||
| 6 | |||
| 7 | class SpecialPhoto < Photo | ||
| 8 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photos.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photos.yml new file mode 100644 index 0000000..25a4118 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/photos.yml | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | jonathan_dog: | ||
| 2 | id: 1 | ||
| 3 | user_id: 1 | ||
| 4 | title: A small dog | ||
| 5 | |||
| 6 | jonathan_questioning_dog: | ||
| 7 | id: 2 | ||
| 8 | user_id: 1 | ||
| 9 | title: What does this dog want? | ||
| 10 | |||
| 11 | jonathan_bad_cat: | ||
| 12 | id: 3 | ||
| 13 | user_id: 1 | ||
| 14 | title: Bad cat | ||
| 15 | |||
| 16 | sam_flower: | ||
| 17 | id: 4 | ||
| 18 | user_id: 2 | ||
| 19 | title: Flower | ||
| 20 | |||
| 21 | sam_sky: | ||
| 22 | id: 5 | ||
| 23 | user_id: 2 | ||
| 24 | title: Sky | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/post.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/post.rb new file mode 100644 index 0000000..bee100a --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/post.rb | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | class Post < ActiveRecord::Base | ||
| 2 | acts_as_taggable | ||
| 3 | |||
| 4 | belongs_to :user | ||
| 5 | |||
| 6 | validates_presence_of :text | ||
| 7 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/posts.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/posts.yml new file mode 100644 index 0000000..79f50f5 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/posts.yml | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | jonathan_sky: | ||
| 2 | id: 1 | ||
| 3 | user_id: 1 | ||
| 4 | text: The sky is particularly blue today | ||
| 5 | |||
| 6 | jonathan_grass: | ||
| 7 | id: 2 | ||
| 8 | user_id: 1 | ||
| 9 | text: The grass seems very green | ||
| 10 | |||
| 11 | jonathan_rain: | ||
| 12 | id: 3 | ||
| 13 | user_id: 1 | ||
| 14 | text: Why does the rain fall? | ||
| 15 | |||
| 16 | jonathan_cloudy: | ||
| 17 | id: 4 | ||
| 18 | user_id: 1 | ||
| 19 | text: Is it cloudy? | ||
| 20 | |||
| 21 | jonathan_still_cloudy: | ||
| 22 | id: 5 | ||
| 23 | user_id: 1 | ||
| 24 | text: Is it still cloudy? | ||
| 25 | |||
| 26 | sam_ground: | ||
| 27 | id: 6 | ||
| 28 | user_id: 2 | ||
| 29 | text: The ground is looking too brown | ||
| 30 | |||
| 31 | sam_flowers: | ||
| 32 | id: 7 | ||
| 33 | user_id: 2 | ||
| 34 | text: Why are the flowers dead? \ No newline at end of file | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/special_post.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/special_post.rb new file mode 100644 index 0000000..366a0d5 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/special_post.rb | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | class SpecialPost < Post | ||
| 2 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscription.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscription.rb new file mode 100644 index 0000000..e975cb7 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscription.rb | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | class Subscription < ActiveRecord::Base | ||
| 2 | belongs_to :user | ||
| 3 | belongs_to :magazine | ||
| 4 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscriptions.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscriptions.yml new file mode 100644 index 0000000..1b5e68a --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/subscriptions.yml | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | jonathan_rails: | ||
| 2 | user_id: 1 | ||
| 3 | magazine_id: 1 \ No newline at end of file | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/taggings.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/taggings.yml new file mode 100644 index 0000000..01e599b --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/taggings.yml | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | # Posts | ||
| 2 | jonathan_sky_good: | ||
| 3 | id: 1 | ||
| 4 | tag_id: 1 | ||
| 5 | taggable_id: 1 | ||
| 6 | taggable_type: Post | ||
| 7 | created_at: 2006-08-01 | ||
| 8 | |||
| 9 | jonathan_sky_nature: | ||
| 10 | id: 2 | ||
| 11 | tag_id: 3 | ||
| 12 | taggable_id: 1 | ||
| 13 | taggable_type: Post | ||
| 14 | created_at: 2006-08-02 | ||
| 15 | |||
| 16 | jonathan_grass_nature: | ||
| 17 | id: 3 | ||
| 18 | tag_id: 3 | ||
| 19 | taggable_id: 2 | ||
| 20 | taggable_type: Post | ||
| 21 | created_at: 2006-08-03 | ||
| 22 | |||
| 23 | jonathan_rain_question: | ||
| 24 | id: 4 | ||
| 25 | tag_id: 4 | ||
| 26 | taggable_id: 3 | ||
| 27 | taggable_type: Post | ||
| 28 | created_at: 2006-08-04 | ||
| 29 | |||
| 30 | jonathan_rain_nature: | ||
| 31 | id: 5 | ||
| 32 | tag_id: 3 | ||
| 33 | taggable_id: 3 | ||
| 34 | taggable_type: Post | ||
| 35 | created_at: 2006-08-05 | ||
| 36 | |||
| 37 | jonathan_cloudy_nature: | ||
| 38 | id: 6 | ||
| 39 | tag_id: 3 | ||
| 40 | taggable_id: 4 | ||
| 41 | taggable_type: Post | ||
| 42 | created_at: 2006-08-06 | ||
| 43 | |||
| 44 | jonathan_still_cloudy_nature: | ||
| 45 | id: 7 | ||
| 46 | tag_id: 3 | ||
| 47 | taggable_id: 5 | ||
| 48 | taggable_type: Post | ||
| 49 | created_at: 2006-08-07 | ||
| 50 | |||
| 51 | sam_ground_nature: | ||
| 52 | id: 8 | ||
| 53 | tag_id: 3 | ||
| 54 | taggable_id: 6 | ||
| 55 | taggable_type: Post | ||
| 56 | created_at: 2006-08-08 | ||
| 57 | |||
| 58 | sam_ground_bad: | ||
| 59 | id: 9 | ||
| 60 | tag_id: 2 | ||
| 61 | taggable_id: 6 | ||
| 62 | taggable_type: Post | ||
| 63 | created_at: 2006-08-09 | ||
| 64 | |||
| 65 | sam_flowers_good: | ||
| 66 | id: 10 | ||
| 67 | tag_id: 1 | ||
| 68 | taggable_id: 7 | ||
| 69 | taggable_type: Post | ||
| 70 | created_at: 2006-08-10 | ||
| 71 | |||
| 72 | sam_flowers_nature: | ||
| 73 | id: 11 | ||
| 74 | tag_id: 3 | ||
| 75 | taggable_id: 7 | ||
| 76 | taggable_type: Post | ||
| 77 | created_at: 2006-08-11 | ||
| 78 | |||
| 79 | # Photos | ||
| 80 | jonathan_dog_animal: | ||
| 81 | id: 12 | ||
| 82 | tag_id: 5 | ||
| 83 | taggable_id: 1 | ||
| 84 | taggable_type: Photo | ||
| 85 | created_at: 2006-08-12 | ||
| 86 | |||
| 87 | jonathan_dog_nature: | ||
| 88 | id: 13 | ||
| 89 | tag_id: 3 | ||
| 90 | taggable_id: 1 | ||
| 91 | taggable_type: Photo | ||
| 92 | created_at: 2006-08-13 | ||
| 93 | |||
| 94 | jonathan_questioning_dog_animal: | ||
| 95 | id: 14 | ||
| 96 | tag_id: 5 | ||
| 97 | taggable_id: 2 | ||
| 98 | taggable_type: Photo | ||
| 99 | created_at: 2006-08-14 | ||
| 100 | |||
| 101 | jonathan_questioning_dog_question: | ||
| 102 | id: 15 | ||
| 103 | tag_id: 4 | ||
| 104 | taggable_id: 2 | ||
| 105 | taggable_type: Photo | ||
| 106 | created_at: 2006-08-15 | ||
| 107 | |||
| 108 | jonathan_bad_cat_bad: | ||
| 109 | id: 16 | ||
| 110 | tag_id: 2 | ||
| 111 | taggable_id: 3 | ||
| 112 | taggable_type: Photo | ||
| 113 | created_at: 2006-08-16 | ||
| 114 | |||
| 115 | jonathan_bad_cat_animal: | ||
| 116 | id: 17 | ||
| 117 | tag_id: 5 | ||
| 118 | taggable_id: 3 | ||
| 119 | taggable_type: Photo | ||
| 120 | created_at: 2006-08-17 | ||
| 121 | |||
| 122 | sam_flower_nature: | ||
| 123 | id: 18 | ||
| 124 | tag_id: 3 | ||
| 125 | taggable_id: 4 | ||
| 126 | taggable_type: Photo | ||
| 127 | created_at: 2006-08-18 | ||
| 128 | |||
| 129 | sam_flower_good: | ||
| 130 | id: 19 | ||
| 131 | tag_id: 1 | ||
| 132 | taggable_id: 4 | ||
| 133 | taggable_type: Photo | ||
| 134 | created_at: 2006-08-19 | ||
| 135 | |||
| 136 | sam_sky_nature: | ||
| 137 | id: 20 | ||
| 138 | tag_id: 3 | ||
| 139 | taggable_id: 5 | ||
| 140 | taggable_type: Photo | ||
| 141 | created_at: 2006-08-20 | ||
| 142 | |||
| 143 | # Magazines | ||
| 144 | ruby_good: | ||
| 145 | id: 50 | ||
| 146 | tag_id: 1 | ||
| 147 | taggable_id: 1 | ||
| 148 | taggable_type: Magazine | ||
| 149 | created_at: 2007-08-25 | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/tags.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/tags.yml new file mode 100644 index 0000000..b8f8367 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/tags.yml | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | good: | ||
| 2 | id: 1 | ||
| 3 | name: Very good | ||
| 4 | |||
| 5 | bad: | ||
| 6 | id: 2 | ||
| 7 | name: Bad | ||
| 8 | |||
| 9 | nature: | ||
| 10 | id: 3 | ||
| 11 | name: Nature | ||
| 12 | |||
| 13 | question: | ||
| 14 | id: 4 | ||
| 15 | name: Question | ||
| 16 | |||
| 17 | animal: | ||
| 18 | id: 5 | ||
| 19 | name: Crazy animal \ No newline at end of file | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/user.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/user.rb new file mode 100644 index 0000000..8c0f787 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/user.rb | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | class User < ActiveRecord::Base | ||
| 2 | has_many :posts | ||
| 3 | has_many :photos | ||
| 4 | |||
| 5 | has_many :subscriptions | ||
| 6 | has_many :magazines, :through => :subscriptions | ||
| 7 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/users.yml b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/users.yml new file mode 100644 index 0000000..da94fea --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/fixtures/users.yml | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | jonathan: | ||
| 2 | id: 1 | ||
| 3 | name: Jonathan | ||
| 4 | |||
| 5 | sam: | ||
| 6 | id: 2 | ||
| 7 | name: Sam | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/tag_list_test.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/tag_list_test.rb new file mode 100644 index 0000000..d0d135c --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/tag_list_test.rb | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | require File.dirname(__FILE__) + '/abstract_unit' | ||
| 2 | |||
| 3 | class TagListTest < Test::Unit::TestCase | ||
| 4 | def test_from_leaves_string_unchanged | ||
| 5 | tags = '"One ", Two' | ||
| 6 | original = tags.dup | ||
| 7 | TagList.from(tags) | ||
| 8 | assert_equal tags, original | ||
| 9 | end | ||
| 10 | |||
| 11 | def test_from_single_name | ||
| 12 | assert_equal %w(Fun), TagList.from("Fun") | ||
| 13 | assert_equal %w(Fun), TagList.from('"Fun"') | ||
| 14 | end | ||
| 15 | |||
| 16 | def test_from_blank | ||
| 17 | assert_equal [], TagList.from(nil) | ||
| 18 | assert_equal [], TagList.from("") | ||
| 19 | end | ||
| 20 | |||
| 21 | def test_from_single_quoted_tag | ||
| 22 | assert_equal ['with, comma'], TagList.from('"with, comma"') | ||
| 23 | end | ||
| 24 | |||
| 25 | def test_spaces_do_not_delineate | ||
| 26 | assert_equal ['A B', 'C'], TagList.from('A B, C') | ||
| 27 | end | ||
| 28 | |||
| 29 | def test_from_multiple_tags | ||
| 30 | assert_equivalent %w(Alpha Beta Delta Gamma), TagList.from("Alpha, Beta, Delta, Gamma") | ||
| 31 | end | ||
| 32 | |||
| 33 | def test_from_multiple_tags_with_quotes | ||
| 34 | assert_equivalent %w(Alpha Beta Delta Gamma), TagList.from('Alpha, "Beta", Gamma , "Delta"') | ||
| 35 | end | ||
| 36 | |||
| 37 | def test_from_with_single_quotes | ||
| 38 | assert_equivalent ['A B', 'C'], TagList.from("'A B', C") | ||
| 39 | end | ||
| 40 | |||
| 41 | def test_from_multiple_tags_with_quote_and_commas | ||
| 42 | assert_equivalent ['Alpha, Beta', 'Delta', 'Gamma, something'], TagList.from('"Alpha, Beta", Delta, "Gamma, something"') | ||
| 43 | end | ||
| 44 | |||
| 45 | def test_from_removes_white_space | ||
| 46 | assert_equivalent %w(Alpha Beta), TagList.from('" Alpha ", "Beta "') | ||
| 47 | assert_equivalent %w(Alpha Beta), TagList.from(' Alpha, Beta ') | ||
| 48 | end | ||
| 49 | |||
| 50 | def test_from_removes_dots | ||
| 51 | assert_equivalent %w(Alpha Beta), TagList.from('Alpha., Beta') | ||
| 52 | assert_equivalent %w(Alpha Beta), TagList.from('Alpha, Be.ta') | ||
| 53 | end | ||
| 54 | |||
| 55 | def test_alternative_delimiter | ||
| 56 | TagList.delimiter = " " | ||
| 57 | |||
| 58 | assert_equal %w(One Two), TagList.from("One Two") | ||
| 59 | assert_equal ['One two', 'three', 'four'], TagList.from('"One two" three four') | ||
| 60 | ensure | ||
| 61 | TagList.delimiter = "," | ||
| 62 | end | ||
| 63 | |||
| 64 | def test_duplicate_tags_removed | ||
| 65 | assert_equal %w(One), TagList.from("One, One") | ||
| 66 | end | ||
| 67 | |||
| 68 | def test_to_s_with_commas | ||
| 69 | assert_equal "Question, Crazy Animal", TagList.new("Question", "Crazy Animal").to_s | ||
| 70 | end | ||
| 71 | |||
| 72 | def test_to_s_with_alternative_delimiter | ||
| 73 | TagList.delimiter = " " | ||
| 74 | |||
| 75 | assert_equal '"Crazy Animal" Question', TagList.new("Crazy Animal", "Question").to_s | ||
| 76 | ensure | ||
| 77 | TagList.delimiter = "," | ||
| 78 | end | ||
| 79 | |||
| 80 | def test_add | ||
| 81 | tag_list = TagList.new("One") | ||
| 82 | assert_equal %w(One), tag_list | ||
| 83 | |||
| 84 | assert_equal %w(One Two), tag_list.add("Two") | ||
| 85 | assert_equal %w(One Two Three), tag_list.add(["Three"]) | ||
| 86 | end | ||
| 87 | |||
| 88 | def test_remove | ||
| 89 | tag_list = TagList.new("One", "Two") | ||
| 90 | assert_equal %w(Two), tag_list.remove("One") | ||
| 91 | assert_equal %w(), tag_list.remove(["Two"]) | ||
| 92 | end | ||
| 93 | |||
| 94 | def test_new_with_parsing | ||
| 95 | assert_equal %w(One Two), TagList.new("One, Two", :parse => true) | ||
| 96 | end | ||
| 97 | |||
| 98 | def test_add_with_parsing | ||
| 99 | assert_equal %w(One Two), TagList.new.add("One, Two", :parse => true) | ||
| 100 | end | ||
| 101 | |||
| 102 | def test_remove_with_parsing | ||
| 103 | tag_list = TagList.from("Three, Four, Five") | ||
| 104 | assert_equal %w(Four), tag_list.remove("Three, Five", :parse => true) | ||
| 105 | end | ||
| 106 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/tag_test.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/tag_test.rb new file mode 100644 index 0000000..4ca577d --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/tag_test.rb | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | require File.dirname(__FILE__) + '/abstract_unit' | ||
| 2 | |||
| 3 | class TagTest < Test::Unit::TestCase | ||
| 4 | fixtures :tags, :taggings, :users, :photos, :posts | ||
| 5 | |||
| 6 | def test_name_required | ||
| 7 | t = Tag.create | ||
| 8 | assert_match /blank/, t.errors[:name].to_s | ||
| 9 | end | ||
| 10 | |||
| 11 | def test_name_unique | ||
| 12 | t = Tag.create!(:name => "My tag") | ||
| 13 | duplicate = t.clone | ||
| 14 | |||
| 15 | assert !duplicate.save | ||
| 16 | assert_match /taken/, duplicate.errors[:name].to_s | ||
| 17 | end | ||
| 18 | |||
| 19 | def test_taggings | ||
| 20 | assert_equivalent [taggings(:jonathan_sky_good), taggings(:sam_flowers_good), taggings(:sam_flower_good), taggings(:ruby_good)], tags(:good).taggings | ||
| 21 | assert_equivalent [taggings(:sam_ground_bad), taggings(:jonathan_bad_cat_bad)], tags(:bad).taggings | ||
| 22 | end | ||
| 23 | |||
| 24 | def test_to_s | ||
| 25 | assert_equal tags(:good).name, tags(:good).to_s | ||
| 26 | end | ||
| 27 | |||
| 28 | def test_equality | ||
| 29 | assert_equal tags(:good), tags(:good) | ||
| 30 | assert_equal Tag.find(1), Tag.find(1) | ||
| 31 | assert_equal Tag.new(:name => 'A'), Tag.new(:name => 'A') | ||
| 32 | assert_not_equal Tag.new(:name => 'A'), Tag.new(:name => 'B') | ||
| 33 | end | ||
| 34 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/tagging_test.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/tagging_test.rb new file mode 100644 index 0000000..172b8e2 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/tagging_test.rb | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | require File.dirname(__FILE__) + '/abstract_unit' | ||
| 2 | |||
| 3 | class TaggingTest < Test::Unit::TestCase | ||
| 4 | fixtures :tags, :taggings, :posts | ||
| 5 | |||
| 6 | def test_tag | ||
| 7 | assert_equal tags(:good), taggings(:jonathan_sky_good).tag | ||
| 8 | end | ||
| 9 | |||
| 10 | def test_taggable | ||
| 11 | assert_equal posts(:jonathan_sky), taggings(:jonathan_sky_good).taggable | ||
| 12 | end | ||
| 13 | end | ||
diff --git a/vendor/plugins/acts_as_taggable_on_steroids/test/tags_helper_test.rb b/vendor/plugins/acts_as_taggable_on_steroids/test/tags_helper_test.rb new file mode 100644 index 0000000..9c3ce53 --- /dev/null +++ b/vendor/plugins/acts_as_taggable_on_steroids/test/tags_helper_test.rb | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | require File.dirname(__FILE__) + '/abstract_unit' | ||
| 2 | |||
| 3 | class TagsHelperTest < Test::Unit::TestCase | ||
| 4 | fixtures :tags, :taggings, :posts | ||
| 5 | |||
| 6 | include TagsHelper | ||
| 7 | |||
| 8 | def test_tag_cloud | ||
| 9 | cloud_elements = [] | ||
| 10 | |||
| 11 | tag_cloud Post.tag_counts, %w(css1 css2 css3 css4) do |tag, css_class| | ||
| 12 | cloud_elements << [tag, css_class] | ||
| 13 | end | ||
| 14 | |||
| 15 | assert_equal [ | ||
| 16 | [tags(:good), "css2"], | ||
| 17 | [tags(:bad), "css1"], | ||
| 18 | [tags(:nature), "css4"], | ||
| 19 | [tags(:question), "css1"] | ||
| 20 | ], cloud_elements | ||
| 21 | end | ||
| 22 | |||
| 23 | def test_tag_cloud_when_no_tags | ||
| 24 | tag_cloud SpecialPost.tag_counts, %w(css1) do | ||
| 25 | assert false, "tag_cloud should not yield" | ||
| 26 | end | ||
| 27 | end | ||
| 28 | end | ||
