acts_as_taggable_on 3.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +9 -0
  5. data/Appraisals +7 -0
  6. data/Gemfile +5 -0
  7. data/Guardfile +5 -0
  8. data/LICENSE.md +20 -0
  9. data/README.md +309 -0
  10. data/Rakefile +13 -0
  11. data/UPGRADING +7 -0
  12. data/acts_as_taggable_on.gemspec +35 -0
  13. data/db/migrate/1_acts_as_taggable_on_migration.rb +30 -0
  14. data/db/migrate/2_add_missing_unique_indices.rb +21 -0
  15. data/gemfiles/rails_3.gemfile +8 -0
  16. data/gemfiles/rails_4.gemfile +8 -0
  17. data/lib/acts_as_taggable_on.rb +61 -0
  18. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +82 -0
  19. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +187 -0
  20. data/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb +34 -0
  21. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +394 -0
  22. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +37 -0
  23. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +135 -0
  24. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +84 -0
  25. data/lib/acts_as_taggable_on/engine.rb +6 -0
  26. data/lib/acts_as_taggable_on/tag.rb +119 -0
  27. data/lib/acts_as_taggable_on/tag_list.rb +101 -0
  28. data/lib/acts_as_taggable_on/taggable.rb +105 -0
  29. data/lib/acts_as_taggable_on/tagger.rb +76 -0
  30. data/lib/acts_as_taggable_on/tagging.rb +34 -0
  31. data/lib/acts_as_taggable_on/tags_helper.rb +15 -0
  32. data/lib/acts_as_taggable_on/utils.rb +34 -0
  33. data/lib/acts_as_taggable_on/version.rb +4 -0
  34. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +265 -0
  35. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +114 -0
  36. data/spec/acts_as_taggable_on/caching_spec.rb +77 -0
  37. data/spec/acts_as_taggable_on/related_spec.rb +143 -0
  38. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +187 -0
  39. data/spec/acts_as_taggable_on/tag_list_spec.rb +126 -0
  40. data/spec/acts_as_taggable_on/tag_spec.rb +211 -0
  41. data/spec/acts_as_taggable_on/taggable_spec.rb +623 -0
  42. data/spec/acts_as_taggable_on/tagger_spec.rb +137 -0
  43. data/spec/acts_as_taggable_on/tagging_spec.rb +28 -0
  44. data/spec/acts_as_taggable_on/tags_helper_spec.rb +44 -0
  45. data/spec/acts_as_taggable_on/utils_spec.rb +21 -0
  46. data/spec/bm.rb +52 -0
  47. data/spec/database.yml.sample +19 -0
  48. data/spec/models.rb +58 -0
  49. data/spec/schema.rb +65 -0
  50. data/spec/spec_helper.rb +87 -0
  51. metadata +248 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzM5YzBmZjg5YWM2NTg1YzM3YWFkNTExYjQwMGY2YTc3ZmRkYmU4Yg==
5
+ data.tar.gz: !binary |-
6
+ YmEzMjhkODU3MmQyN2NhNzk4MTBmYzdmMGI0NmY1N2FkOWQ4NWE4NQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NDMxNWQyMWNiN2FmMDU0Yzk1NTg2Y2E1NmU1ZWU1NTI4YjQ0YmMwNTdjZTcw
10
+ Y2U0YWVlM2IxZmMwYzUzNmY0MWZjNGM1OTkwNDhkNjIyMGY4YzNmNjM2MmMz
11
+ ODQzYzljZTk2MTA3YWIxNWI4OTkyNjVjMjZiOTMwNWJlN2M1MWE=
12
+ data.tar.gz: !binary |-
13
+ MTE1MTcxNzIxMmQ2ZTY5OTAxYmM5NzJmN2Y0ZTQ5MjM4NDY2NzU3NjYxYjI5
14
+ NjIwODI5YjM4ZDI5YWJiMzk0OGYzZjM2OTlkNmU0ZjlmOWRlZDRlOTZkYWU0
15
+ MmNmYWJiYTA0ZjQzZjIwNmI3NWE5ZjQ4YmZjZDNiMjc3ZjU2N2I=
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.log
2
+ *.sqlite3
3
+ /pkg/*
4
+ .bundle
5
+ .ruby-version
6
+ spec/database.yml
7
+ tmp*.sw?
8
+ *.sw?
9
+ tmp
10
+ *.gem
11
+ *.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --backtrace
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ script: "cp spec/database.yml.sample spec/database.yml && bundle install && bundle exec rake"
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ env:
6
+ - DB=sqlite3
7
+ - DB=mysql
8
+ - DB=postgresql
9
+ cache: bundler
data/Appraisals ADDED
@@ -0,0 +1,7 @@
1
+ appraise "rails-3" do
2
+ gem "rails", "3.2.13"
3
+ end
4
+
5
+ appraise "rails-4" do
6
+ gem "rails", "4.0.0.beta1"
7
+ end
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'appraisal'
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb})
3
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ __Copyright (c) 2007 Michael Bleigh and Intridea Inc.__
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.md ADDED
@@ -0,0 +1,309 @@
1
+ # ActsAsTaggableOn
2
+ [![Build Status](https://secure.travis-ci.org/mbleigh/acts-as-taggable-on.png)](http://travis-ci.org/mbleigh/acts-as-taggable-on)
3
+ [![Code Climate](https://codeclimate.com/github/mbleigh/acts-as-taggable-on.png)](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
4
+
5
+ This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
6
+ It has evolved substantially since that point, but all credit goes to him for the
7
+ initial tagging functionality that so many people have used.
8
+
9
+ For instance, in a social network, a user might have tags that are called skills,
10
+ interests, sports, and more. There is no real way to differentiate between tags and
11
+ so an implementation of this type is not possible with acts as taggable on steroids.
12
+
13
+ Enter Acts as Taggable On. Rather than tying functionality to a specific keyword
14
+ (namely `tags`), acts as taggable on allows you to specify an arbitrary number of
15
+ tag "contexts" that can be used locally or in combination in the same way steroids
16
+ was used.
17
+
18
+ ## Compatibility
19
+
20
+ Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
21
+
22
+ Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
23
+
24
+ Versions 3.x (currently unreleased) are compatible with Ruby 1.9.3+ and Rails 3 and 4.
25
+
26
+ For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/issues/milestones
27
+
28
+ ## Installation
29
+
30
+ To use it, add it to your Gemfile:
31
+
32
+ ```ruby
33
+ gem 'acts_as_taggable_on'
34
+ ```
35
+
36
+ and bundle:
37
+
38
+ ```ruby
39
+ bundle
40
+ ```
41
+
42
+ #### Post Installation
43
+
44
+ ```shell
45
+ rails generate acts_as_taggable_on:migration
46
+ rake db:migrate
47
+ ```
48
+
49
+ #### Upgrading
50
+
51
+ see [UPGRADING](UPGRADING)
52
+
53
+ ## Testing
54
+
55
+ Acts As Taggable On uses RSpec for its test coverage. Inside the gem
56
+ directory, you can run the specs with:
57
+
58
+ ```shell
59
+ bundle
60
+ cp spec/database.yml{.sample,}
61
+ rake spec
62
+ ```
63
+
64
+ If you want, add a `.ruby-version` file in the project root (and use rbenv or RVM) to work on a specific version of Ruby.
65
+
66
+ ## Usage
67
+
68
+ ```ruby
69
+ class User < ActiveRecord::Base
70
+ # Alias for acts_as_taggable_on :tags
71
+ acts_as_taggable
72
+ acts_as_taggable_on :skills, :interests
73
+ end
74
+
75
+ @user = User.new(:name => "Bobby")
76
+ @user.tag_list = "awesome, slick, hefty" # this should be familiar
77
+ @user.skill_list = "joking, clowning, boxing" # but you can do it for any context!
78
+
79
+ @user.tags # => [<Tag name:"awesome">,<Tag name:"slick">,<Tag name:"hefty">]
80
+ @user.skills # => [<Tag name:"joking">,<Tag name:"clowning">,<Tag name:"boxing">]
81
+ @user.skill_list # => ["joking","clowning","boxing"] as TagList
82
+
83
+ @user.tag_list.remove("awesome") # remove a single tag
84
+ @user.tag_list.remove("awesome, slick") # works with arrays too
85
+ @user.tag_list.add("awesomer") # add a single tag. alias for <<
86
+ @user.tag_list.add("awesomer, slicker") # also works with arrays
87
+
88
+ User.skill_counts # => [<Tag name="joking" count=2>,<Tag name="clowning" count=1>...]
89
+ ```
90
+
91
+ To preserve the order in which tags are created use `acts_as_ordered_taggable`:
92
+
93
+ ```ruby
94
+ class User < ActiveRecord::Base
95
+ # Alias for acts_as_ordered_taggable_on :tags
96
+ acts_as_ordered_taggable
97
+ acts_as_ordered_taggable_on :skills, :interests
98
+ end
99
+
100
+ @user = User.new(:name => "Bobby")
101
+ @user.tag_list = "east, south"
102
+ @user.save
103
+
104
+ @user.tag_list = "north, east, south, west"
105
+ @user.save
106
+
107
+ @user.reload
108
+ @user.tag_list # => ["north", "east", "south", "west"]
109
+ ```
110
+
111
+ ### Finding Tagged Objects
112
+
113
+ Acts As Taggable On uses scopes to create an association for tags.
114
+ This way you can mix and match to filter down your results.
115
+
116
+ ```ruby
117
+ class User < ActiveRecord::Base
118
+ acts_as_taggable_on :tags, :skills
119
+ scope :by_join_date, order("created_at DESC")
120
+ end
121
+
122
+ User.tagged_with("awesome").by_join_date
123
+ User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
124
+
125
+ # Find a user with matching all tags, not just one
126
+ User.tagged_with(["awesome", "cool"], :match_all => true)
127
+
128
+ # Find a user with any of the tags:
129
+ User.tagged_with(["awesome", "cool"], :any => true)
130
+
131
+ # Find a user that not tags with awesome or cool:
132
+ User.tagged_with(["awesome", "cool"], :exclude => true)
133
+
134
+ # Find a user with any of tags based on context:
135
+ User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
136
+ ```
137
+
138
+ You can also use `:wild => true` option along with `:any` or `:exclude` option. It will looking for `%awesome%` and `%cool%` in sql.
139
+
140
+ __Tip:__ `User.tagged_with([])` or '' will return `[]`, but not all records.
141
+
142
+ ### Relationships
143
+
144
+ You can find objects of the same type based on similar tags on certain contexts.
145
+ Also, objects will be returned in descending order based on the total number of
146
+ matched tags.
147
+
148
+ ```ruby
149
+ @bobby = User.find_by_name("Bobby")
150
+ @bobby.skill_list # => ["jogging", "diving"]
151
+
152
+ @frankie = User.find_by_name("Frankie")
153
+ @frankie.skill_list # => ["hacking"]
154
+
155
+ @tom = User.find_by_name("Tom")
156
+ @tom.skill_list # => ["hacking", "jogging", "diving"]
157
+
158
+ @tom.find_related_skills # => [<User name="Bobby">,<User name="Frankie">]
159
+ @bobby.find_related_skills # => [<User name="Tom">]
160
+ @frankie.find_related_skills # => [<User name="Tom">]
161
+ ```
162
+
163
+ ### Dynamic Tag Contexts
164
+
165
+ In addition to the generated tag contexts in the definition, it is also possible
166
+ to allow for dynamic tag contexts (this could be user generated tag contexts!)
167
+
168
+ ```ruby
169
+ @user = User.new(:name => "Bobby")
170
+ @user.set_tag_list_on(:customs, "same, as, tag, list")
171
+ @user.tag_list_on(:customs) # => ["same","as","tag","list"]
172
+ @user.save
173
+ @user.tags_on(:customs) # => [<Tag name='same'>,...]
174
+ @user.tag_counts_on(:customs)
175
+ User.tagged_with("same", :on => :customs) # => [@user]
176
+ ```
177
+
178
+ ### Tag Ownership
179
+
180
+ Tags can have owners:
181
+
182
+ ```ruby
183
+ class User < ActiveRecord::Base
184
+ acts_as_tagger
185
+ end
186
+
187
+ class Photo < ActiveRecord::Base
188
+ acts_as_taggable_on :locations
189
+ end
190
+
191
+ @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
192
+ @some_user.owned_taggings
193
+ @some_user.owned_tags
194
+ Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
195
+ @some_photo.locations_from(@some_user) # => ["paris", "normandy"]
196
+ @some_photo.owner_tags_on(@some_user, :locations) # => [#<ActsAsTaggableOn::Tag id: 1, name: "paris">...]
197
+ @some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
198
+ @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
199
+ ```
200
+
201
+ ### Dirty objects
202
+
203
+ ```ruby
204
+ @bobby = User.find_by_name("Bobby")
205
+ @bobby.skill_list # => ["jogging", "diving"]
206
+
207
+ @bobby.skill_list_changed? #=> false
208
+ @bobby.changes #=> {}
209
+
210
+ @bobby.skill_list = "swimming"
211
+ @bobby.changes.should == {"skill_list"=>["jogging, diving", ["swimming"]]}
212
+ @bobby.skill_list_changed? #=> true
213
+
214
+ @bobby.skill_list_change.should == ["jogging, diving", ["swimming"]]
215
+ ```
216
+
217
+ ### Tag cloud calculations
218
+
219
+ To construct tag clouds, the frequency of each tag needs to be calculated.
220
+ Because we specified `acts_as_taggable_on` on the `User` class, we can
221
+ get a calculation of all the tag counts by using `User.tag_counts_on(:customs)`. But what if we wanted a tag count for
222
+ an single user's posts? To achieve this we call tag_counts on the association:
223
+
224
+ ```ruby
225
+ User.find(:first).posts.tag_counts_on(:tags)
226
+ ```
227
+
228
+ A helper is included to assist with generating tag clouds.
229
+
230
+ Here is an example that generates a tag cloud.
231
+
232
+ Helper:
233
+
234
+ ```ruby
235
+ module PostsHelper
236
+ include ActsAsTaggableOn::TagsHelper
237
+ end
238
+ ```
239
+
240
+ Controller:
241
+
242
+ ```ruby
243
+ class PostController < ApplicationController
244
+ def tag_cloud
245
+ @tags = Post.tag_counts_on(:tags)
246
+ end
247
+ end
248
+ ```
249
+
250
+ View:
251
+
252
+ ```erb
253
+ <% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
254
+ <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
255
+ <% end %>
256
+ ```
257
+
258
+ CSS:
259
+
260
+ ```css
261
+ .css1 { font-size: 1.0em; }
262
+ .css2 { font-size: 1.2em; }
263
+ .css3 { font-size: 1.4em; }
264
+ .css4 { font-size: 1.6em; }
265
+ ```
266
+
267
+ ## Configuration
268
+
269
+ If you would like to remove unused tag objects after removing taggings, add:
270
+
271
+ ```ruby
272
+ ActsAsTaggableOn.remove_unused_tags = true
273
+ ```
274
+
275
+ If you want force tags to be saved downcased:
276
+
277
+ ```ruby
278
+ ActsAsTaggableOn.force_lowercase = true
279
+ ```
280
+
281
+ If you want tags to be saved parametrized (you can redefine to_param as well):
282
+
283
+ ```ruby
284
+ ActsAsTaggableOn.force_parameterize = true
285
+ ```
286
+
287
+ If you would like tags to be case-sensitive and not use LIKE queries for creation:
288
+
289
+ ```ruby
290
+ ActsAsTaggableOn.strict_case_match = true
291
+ ```
292
+
293
+ If you want to change the default delimiter (it defaults to ','). You can also pass in an array of delimiters such as ([',', '|']):
294
+
295
+ ```ruby
296
+ ActsAsTaggableOn.delimiter = ','
297
+ ```
298
+
299
+ ## Contributors
300
+
301
+ We have a long list of valued contributors. [Check them all](https://github.com/mbleigh/acts-as-taggable-on/contributors)
302
+
303
+ ## Maintainer
304
+
305
+ * [Joost Baaij](https://github.com/tilsammans)
306
+
307
+ ## License
308
+
309
+ See [LICENSE](https://github.com/mbleigh/acts-as-taggable-on/blob/master/LICENSE.md)
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'appraisal'
4
+
5
+ desc 'Default: run specs'
6
+ task :default => :spec
7
+
8
+ require 'rspec/core/rake_task'
9
+ RSpec::Core::RakeTask.new do |t|
10
+ t.pattern = "spec/**/*_spec.rb"
11
+ end
12
+
13
+ Bundler::GemHelper.install_tasks
data/UPGRADING ADDED
@@ -0,0 +1,7 @@
1
+ When upgrading
2
+
3
+ Re-run the migrations generator
4
+
5
+ rake railties:install:migrations FROM=acts_as_taggable_on_engine db:migrate
6
+
7
+ It will create any new migrations and skip existing ones
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'acts_as_taggable_on/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "acts_as_taggable_on"
8
+ gem.version = ActsAsTaggableOn::VERSION
9
+ gem.authors = ["Michael Bleigh", "Joost Baaij"]
10
+ gem.email = ["michael@intridea.com", "joost@spacebabies.nl"]
11
+ gem.description = %q{With ActsAsTaggableOn, you can tag a single model on several contexts, such as skills, interests, and awards. It also provides other advanced functionality.}
12
+ gem.summary = "Advanced tagging for Rails."
13
+ gem.homepage = 'https://github.com/mbleigh/acts-as-taggable-on'
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ if File.exists?('UPGRADING')
22
+ gem.post_install_message = File.read('UPGRADING')
23
+ end
24
+
25
+ gem.add_runtime_dependency 'rails', ['>= 3', '< 5']
26
+
27
+ gem.add_development_dependency 'rspec-rails', '2.13.0' # 2.13.1 is broken
28
+ gem.add_development_dependency 'rspec', '~> 2.6'
29
+ gem.add_development_dependency 'ammeter'
30
+ gem.add_development_dependency 'sqlite3'
31
+ gem.add_development_dependency 'mysql2', '~> 0.3.7'
32
+ gem.add_development_dependency 'pg'
33
+ gem.add_development_dependency 'guard'
34
+ gem.add_development_dependency 'guard-rspec'
35
+ end