rotuka-taggable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -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]
data/MIT-LICENSE ADDED
@@ -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.
data/README ADDED
@@ -0,0 +1,146 @@
1
+ = Taggable gem
2
+
3
+ == Instructions
4
+
5
+ This gem is based on acts_as_taggable_on_steroids by Jonathan Viney but includes extras
6
+ such as tests, smarter tag assignment, and tag cloud calculations.
7
+
8
+ == Installation
9
+
10
+ sudo gem install rotuka-taggable --source=http://gems.github.com
11
+
12
+ == Usage
13
+
14
+ In environment.rb add dependencie
15
+ config.gem 'rotuka-taggable', :lib => 'taggable'
16
+
17
+ === Prepare database
18
+
19
+ Generate and apply the migration:
20
+
21
+ ruby script/generate tags
22
+ rake db:migrate
23
+
24
+ === Basic tagging
25
+
26
+ Let's suppose users have many posts and we want those posts to have tags.
27
+ The first step is to add +acts_as_taggable+ to the Post class:
28
+
29
+ class Post < ActiveRecord::Base
30
+ acts_as_taggable
31
+
32
+ belongs_to :user
33
+ end
34
+
35
+ We can now use the tagging methods provided by acts_as_taggable, <tt>#tag_list</tt> and <tt>#tag_list=</tt>. Both these
36
+ methods work like regular attribute accessors.
37
+
38
+ p = Post.find(:first)
39
+ p.tag_list # []
40
+ p.tag_list = "Funny, Silly"
41
+ p.save
42
+ p.tag_list # ["Funny", "Silly"]
43
+
44
+ You can also add or remove arrays of tags.
45
+
46
+ p.tag_list.add("Great", "Awful")
47
+ p.tag_list.remove("Funny")
48
+
49
+ === Finding tagged objects
50
+
51
+ To retrieve objects tagged with a certain tag, use find_tagged_with.
52
+
53
+ Post.find_tagged_with('Funny, Silly')
54
+
55
+ By default, find_tagged_with will find objects that have any of the given tags. To
56
+ find only objects that are tagged with all the given tags, use match_all.
57
+
58
+ Post.find_tagged_with('Funny, Silly', :match_all => true)
59
+
60
+ See <tt>ActiveRecord::Acts::Taggable::InstanceMethods</tt> for more methods and options.
61
+
62
+ === Tag cloud calculations
63
+
64
+ To construct tag clouds, the frequency of each tag needs to be calculated.
65
+ Because we specified +acts_as_taggable+ on the <tt>Post</tt> class, we can
66
+ get a calculation of all the tag counts by using <tt>Post.tag_counts</tt>. But what if we wanted a tag count for
67
+ an single user's posts? To achieve this we call tag_counts on the association:
68
+
69
+ User.find(:first).posts.tag_counts
70
+
71
+ A helper is included to assist with generating tag clouds. Include it in your helper file:
72
+
73
+ module ApplicationHelper
74
+ include TagsHelper
75
+ end
76
+
77
+ Here is an example that generates a tag cloud.
78
+
79
+ Controller:
80
+
81
+ class PostController < ApplicationController
82
+ def tag_cloud
83
+ @tags = Post.tag_counts
84
+ end
85
+ end
86
+
87
+ View:
88
+ <% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %>
89
+ <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
90
+ <% end %>
91
+
92
+ CSS:
93
+
94
+ .css1 { font-size: 1.0em; }
95
+ .css2 { font-size: 1.2em; }
96
+ .css3 { font-size: 1.4em; }
97
+ .css4 { font-size: 1.6em; }
98
+
99
+ === Caching
100
+
101
+ It is useful to cache the list of tags to reduce the number of queries executed. To do this,
102
+ add a column named <tt>cached_tag_list</tt> to the model which is being tagged. The column should be long enough to hold
103
+ the full tag list and must have a default value of null, not an empty string.
104
+
105
+ class CachePostTagList < ActiveRecord::Migration
106
+ def self.up
107
+ add_column :posts, :cached_tag_list, :string
108
+ end
109
+ end
110
+
111
+ class Post < ActiveRecord::Base
112
+ acts_as_taggable
113
+
114
+ # The caching column defaults to cached_tag_list, but can be changed:
115
+ #
116
+ # set_cached_tag_list_column_name "my_caching_column_name"
117
+ end
118
+
119
+ The details of the caching are handled for you. Just continue to use the tag_list accessor as you normally would.
120
+ Note that the cached tag list will not be updated if you directly create Tagging objects or manually append to the
121
+ <tt>tags</tt> or <tt>taggings</tt> associations. To update the cached tag list you should call <tt>save_cached_tag_list</tt> manually.
122
+
123
+ === Delimiter
124
+
125
+ If you want to change the delimiter used to parse and present tags, set TagList.delimiter.
126
+ For example, to use spaces instead of commas, add the following to config/environment.rb:
127
+
128
+ TagList.delimiter = " "
129
+
130
+ You can also use a regexp as delimiter:
131
+
132
+ TagList.delimiter = /,|;/
133
+
134
+ The above code would parse the string and use ',' and ';' as delimiters.
135
+
136
+ === Unused tags
137
+
138
+ Set Tag.destroy_unused to remove tags when they are no longer being
139
+ used to tag any objects. Defaults to false.
140
+
141
+ Tag.destroy_unused = true
142
+
143
+ === Other
144
+
145
+ Problems, comments, and suggestions all welcome.
146
+ me@rotuka.com
data/Rakefile ADDED
@@ -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 taggable gem.'
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 taggable gem.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Taggable'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1 @@
1
+ script/generate tags
@@ -0,0 +1,14 @@
1
+ class TagsGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate'
5
+ m.file "tag.rb", "app/models/tag.rb"
6
+ m.file "tagging.rb", "app/models/tagging.rb"
7
+ m.file "tags_helper.rb", "app/helpers/tags_helper.rb"
8
+ end
9
+ end
10
+
11
+ def file_name
12
+ "acts_as_taggable_migration"
13
+ end
14
+ end
@@ -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
@@ -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
@@ -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