acts-as-taggable-on 2.0.0 → 3.2.2

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 (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +23 -0
  4. data/Appraisals +20 -0
  5. data/CHANGELOG.md +112 -0
  6. data/CONTRIBUTING.md +44 -0
  7. data/Gemfile +9 -5
  8. data/Guardfile +5 -0
  9. data/{MIT-LICENSE → LICENSE.md} +1 -1
  10. data/README.md +385 -0
  11. data/Rakefile +13 -53
  12. data/UPGRADING.md +13 -0
  13. data/acts-as-taggable-on.gemspec +38 -0
  14. data/{lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb → db/migrate/1_acts_as_taggable_on_migration.rb} +5 -3
  15. data/db/migrate/2_add_missing_unique_indices.rb +19 -0
  16. data/db/migrate/3_add_taggings_counter_cache_to_tags.rb +14 -0
  17. data/gemfiles/activerecord_3.2.gemfile +15 -0
  18. data/gemfiles/activerecord_4.0.gemfile +15 -0
  19. data/gemfiles/activerecord_4.1.gemfile +15 -0
  20. data/gemfiles/activerecord_edge.gemfile +16 -0
  21. data/lib/acts-as-taggable-on.rb +65 -22
  22. data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +53 -24
  23. data/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +120 -42
  24. data/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb +35 -0
  25. data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +309 -124
  26. data/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb +36 -0
  27. data/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb +96 -72
  28. data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +43 -36
  29. data/lib/acts_as_taggable_on/engine.rb +5 -0
  30. data/lib/acts_as_taggable_on/tag.rb +133 -63
  31. data/lib/acts_as_taggable_on/tag_list.rb +162 -81
  32. data/lib/acts_as_taggable_on/taggable.rb +101 -0
  33. data/lib/acts_as_taggable_on/{acts_as_tagger.rb → tagger.rb} +34 -13
  34. data/lib/acts_as_taggable_on/tagging.rb +28 -18
  35. data/lib/acts_as_taggable_on/tags_helper.rb +12 -14
  36. data/lib/acts_as_taggable_on/utils.rb +62 -0
  37. data/lib/acts_as_taggable_on/version.rb +4 -0
  38. data/lib/acts_as_taggable_on.rb +6 -0
  39. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +189 -195
  40. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +78 -81
  41. data/spec/acts_as_taggable_on/caching_spec.rb +76 -0
  42. data/spec/acts_as_taggable_on/related_spec.rb +89 -0
  43. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +210 -0
  44. data/spec/acts_as_taggable_on/tag_list_spec.rb +149 -61
  45. data/spec/acts_as_taggable_on/tag_spec.rb +245 -65
  46. data/spec/acts_as_taggable_on/taggable_spec.rb +776 -187
  47. data/spec/acts_as_taggable_on/tagger_spec.rb +119 -70
  48. data/spec/acts_as_taggable_on/tagging_spec.rb +17 -21
  49. data/spec/acts_as_taggable_on/tags_helper_spec.rb +38 -22
  50. data/spec/acts_as_taggable_on/utils_spec.rb +15 -0
  51. data/spec/internal/app/models/altered_inheriting_taggable_model.rb +3 -0
  52. data/spec/internal/app/models/cached_model.rb +3 -0
  53. data/spec/internal/app/models/cached_model_with_array.rb +5 -0
  54. data/spec/internal/app/models/company.rb +15 -0
  55. data/spec/internal/app/models/inheriting_taggable_model.rb +2 -0
  56. data/spec/internal/app/models/market.rb +2 -0
  57. data/spec/internal/app/models/models.rb +90 -0
  58. data/spec/internal/app/models/non_standard_id_taggable_model.rb +8 -0
  59. data/spec/internal/app/models/ordered_taggable_model.rb +4 -0
  60. data/spec/internal/app/models/other_cached_model.rb +3 -0
  61. data/spec/internal/app/models/other_taggable_model.rb +4 -0
  62. data/spec/internal/app/models/student.rb +2 -0
  63. data/spec/internal/app/models/taggable_model.rb +13 -0
  64. data/spec/internal/app/models/untaggable_model.rb +3 -0
  65. data/spec/internal/app/models/user.rb +3 -0
  66. data/spec/internal/config/database.yml.sample +19 -0
  67. data/spec/internal/db/schema.rb +97 -0
  68. data/spec/schema.rb +57 -18
  69. data/spec/spec_helper.rb +12 -47
  70. data/spec/support/array.rb +9 -0
  71. data/spec/support/database.rb +42 -0
  72. data/spec/support/database_cleaner.rb +21 -0
  73. metadata +286 -63
  74. data/CHANGELOG +0 -25
  75. data/README.rdoc +0 -221
  76. data/VERSION +0 -1
  77. data/generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb +0 -7
  78. data/generators/acts_as_taggable_on_migration/templates/migration.rb +0 -29
  79. data/lib/acts_as_taggable_on/acts_as_taggable_on.rb +0 -53
  80. data/lib/acts_as_taggable_on/compatibility/Gemfile +0 -6
  81. data/lib/acts_as_taggable_on/compatibility/active_record_backports.rb +0 -17
  82. data/lib/generators/acts_as_taggable_on/migration/migration_generator.rb +0 -31
  83. data/rails/init.rb +0 -1
  84. data/spec/bm.rb +0 -52
  85. data/spec/models.rb +0 -30
  86. /data/{spec/spec.opts → .rspec} +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bc40e6d7c5c8b741bfc71aee7ae2406c6f824108
4
+ data.tar.gz: 3c89e20ed3b39ef33d52724d4bb8b9aa3e5738f9
5
+ SHA512:
6
+ metadata.gz: e4142af492646d113a10fa0ae4815d91a281f2a55d60fb70b653a96d4ac58e24c56e1e10bcbf9907bbcc06cee2b476b6ec4a568cc25e5247578a140cbf388d85
7
+ data.tar.gz: eceb8e025f83cdbc9e237405eac982aa3b7c7ef0f54d803fcd80d1ed837b833d4f07fe549f0eb0eaa443edb5cdc84bcad79555a67a886e7fc706b46aa5d37b35
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ *.log
2
+ *.sqlite3
3
+ /pkg/*
4
+ .bundle
5
+ .ruby-version
6
+ spec/internal/config/database.yml
7
+ tmp*.sw?
8
+ *.sw?
9
+ tmp
10
+ *.gem
11
+ *.lock
data/.travis.yml ADDED
@@ -0,0 +1,23 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.1
5
+ - rbx-2
6
+ env:
7
+ - DB=sqlite3
8
+ - DB=mysql
9
+ - DB=postgresql
10
+ gemfile:
11
+ - gemfiles/activerecord_3.2.gemfile
12
+ - gemfiles/activerecord_4.0.gemfile
13
+ - gemfiles/activerecord_4.1.gemfile
14
+ - gemfiles/activerecord_edge.gemfile
15
+ cache: bundler
16
+ script: bundle exec rake
17
+ before_install: gem install bundler
18
+ bundler_args: '--without local_development'
19
+ matrix:
20
+ fast_finish: true
21
+ allow_failures:
22
+ - gemfile: gemfiles/activerecord_edge.gemfile
23
+ - rvm: rbx-2
data/Appraisals ADDED
@@ -0,0 +1,20 @@
1
+ appraise "activerecord-3.2" do
2
+ gem "activerecord", "~> 3.2"
3
+ gem "actionpack", "~> 3.2"
4
+ end
5
+
6
+ appraise "activerecord-4.0" do
7
+ gem "activerecord", "~> 4.0"
8
+ gem "actionpack", "~> 4.0"
9
+ end
10
+
11
+ appraise "activerecord-4.1" do
12
+ gem "activerecord", "~> 4.1"
13
+ gem "actionpack", "~> 4.1"
14
+ end
15
+
16
+ appraise "activerecord-edge" do
17
+ gem "activerecord", github: "rails/rails"
18
+ gem "actionpack", github: "rails/rails"
19
+ gem 'arel', github: 'rails/arel'
20
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,112 @@
1
+ Changes are below categorized as `Features, Fixes, or Misc`.
2
+
3
+ Each change should fall into categories that would affect whether the release is major (breaking changes), minor (new behavior), or patch (bug fix). See [semver](http://semver.org/) and [pessimistic versioning](http://guides.rubygems.org/patterns/#pessimistic_version_constraint)
4
+
5
+ As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch. And _misc_ is either minor or patch, the difference being kind of fuzzy for the purposes of history. Adding tests would be patch level.
6
+
7
+ ### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.2.0...master)
8
+
9
+ * Breaking Changes
10
+ * Taggable models are not extend with ActsAsTaggableOn::Utils anymore
11
+ * Features
12
+ * Fixes
13
+ * Performance
14
+ * Misc
15
+ * Deleted outdated benchmark script
16
+
17
+
18
+ ### [3.2.0 / 2014-05-1](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.1.1...v3.2.0)
19
+
20
+ * Breaking Changes
21
+ * ActsAsTaggableOn::Tag is not extend with ActsAsTaggableOn::Utils anymore
22
+ * Features
23
+ * [@chess #413 Hook to support STI subclasses of Tag in save_tags](https://github.com/mbleigh/acts-as-taggable-on/pull/413)
24
+ * Fixes
25
+ * [@jdelStrother #515 Rename Compatibility methods to reduce chance of conflicts ](https://github.com/mbleigh/acts-as-taggable-on/pull/515)
26
+ * [@seuros #512 fix for << method](https://github.com/mbleigh/acts-as-taggable-on/pull/512)
27
+ * [@sonots #510 fix IN subquery error for mysql](https://github.com/mbleigh/acts-as-taggable-on/pull/510)
28
+ * [@jonseaberg #499 fix for race condition when multiple processes try to add the same tag](https://github.com/mbleigh/acts-as-taggable-on/pull/499)
29
+ * [@leklund #496 Fix for distinct and postgresql json columns errors](https://github.com/mbleigh/acts-as-taggable-on/pull/496)
30
+ * [@thatbettina & @plexus #394 Multiple quoted tags](https://github.com/mbleigh/acts-as-taggable-on/pull/496)
31
+ * Performance
32
+ * Misc
33
+ * [@seuros #511 Rspec 3](https://github.com/mbleigh/acts-as-taggable-on/pull/511)
34
+
35
+ ### [3.1.0 / 2014-03-31](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.0.1...v3.1.0)
36
+
37
+ * Fixes
38
+ * [@mikehale #487 Match_all respects context](https://github.com/mbleigh/acts-as-taggable-on/pull/487)
39
+ * Performance
40
+ * [@dgilperez #390 Add taggings counter cache](https://github.com/mbleigh/acts-as-taggable-on/pull/390)
41
+ * Misc
42
+ * [@jonseaberg Add missing indexes to schema used in specs #474](https://github.com/mbleigh/acts-as-taggable-on/pull/474)
43
+ * [@seuros Specify Ruby >= 1.9.3 required in gemspec](https://github.com/mbleigh/acts-as-taggable-on/pull/502)
44
+ * [@kiasaki Add missing quotes to code example](https://github.com/mbleigh/acts-as-taggable-on/pull/501)
45
+
46
+ ### [3.1.0.rc1 / 2014-02-26](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.0.1...v3.1.0.rc1)
47
+
48
+ * Features
49
+ * [@jamesburke-examtime #467 Add :order_by_matching_tag_count option](https://github.com/mbleigh/acts-as-taggable-on/pull/469)
50
+ * Fixes
51
+ * [@rafael #406 Dirty attributes not correctly derived](https://github.com/mbleigh/acts-as-taggable-on/pull/406)
52
+ * [@bzbnhang #440 Did not respect strict_case_match](https://github.com/mbleigh/acts-as-taggable-on/pull/440)
53
+ * [@znz #456 Fix breaking encoding of tag](https://github.com/mbleigh/acts-as-taggable-on/pull/456)
54
+ * [@rgould #417 Let '.count' work when tagged_with is accompanied by a group clause](https://github.com/mbleigh/acts-as-taggable-on/pull/417)
55
+ * [@developer88 #461 Move 'Distinct' out of select string and use .uniq instead](https://github.com/mbleigh/acts-as-taggable-on/pull/461)
56
+ * [@gerard-leijdekkers #473 Fixed down migration index name](https://github.com/mbleigh/acts-as-taggable-on/pull/473)
57
+ * [@leo-souza #498 Use database's lower function for case-insensitive match](https://github.com/mbleigh/acts-as-taggable-on/pull/498)
58
+ * Misc
59
+ * [@billychan #463 Thread safe support](https://github.com/mbleigh/acts-as-taggable-on/pull/463)
60
+ * [@billychan #386 Add parse:true instructions to README](https://github.com/mbleigh/acts-as-taggable-on/pull/386)
61
+ * [@seuros #449 Improve README/UPGRADING/post install docs](https://github.com/mbleigh/acts-as-taggable-on/pull/449)
62
+ * [@seuros #452 Remove I18n deprecation warning in specs](https://github.com/mbleigh/acts-as-taggable-on/pull/452)
63
+ * [@seuros #453 Test against Ruby 2.1 on Travis CI](https://github.com/mbleigh/acts-as-taggable-on/pull/453)
64
+ * [@takashi #454 Clarify example in docs](https://github.com/mbleigh/acts-as-taggable-on/pull/454)
65
+
66
+ ### [3.0.1 / 2014-01-08](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.0.0...v3.0.1)
67
+
68
+ * Fixes
69
+ * [@rafael #406 Dirty attributes not correctly derived](https://github.com/mbleigh/acts-as-taggable-on/pull/406)
70
+ * [@bzbnhang #440 Did not respect strict_case_match](https://github.com/mbleigh/acts-as-taggable-on/pull/440)
71
+ * [@znz #456 Fix breaking encoding of tag](https://github.com/mbleigh/acts-as-taggable-on/pull/456)
72
+ * Misc
73
+ * [@billychan #386 Add parse:true instructions to README](https://github.com/mbleigh/acts-as-taggable-on/pull/386)
74
+ * [@seuros #449 Improve README/UPGRADING/post install docs](https://github.com/mbleigh/acts-as-taggable-on/pull/449)
75
+ * [@seuros #452 Remove I18n deprecation warning in specs](https://github.com/mbleigh/acts-as-taggable-on/pull/452)
76
+ * [@seuros #453 Test against Ruby 2.1 on Travis CI](https://github.com/mbleigh/acts-as-taggable-on/pull/453)
77
+ * [@takashi #454 Clarify example in docs](https://github.com/mbleigh/acts-as-taggable-on/pull/454)
78
+
79
+ ### [3.0.0 / 2014-01-01](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.1...v3.0.0)
80
+
81
+ * Breaking Changes
82
+ * No longer supports Ruby 1.8.
83
+ * Features
84
+ * Supports Rails 4.1.
85
+ * Misc (TODO: expand)
86
+ * [zquest #359](https://github.com/mbleigh/acts-as-taggable-on/pull/359)
87
+ * [rsl #367](https://github.com/mbleigh/acts-as-taggable-on/pull/367)
88
+ * [ktdreyer #383](https://github.com/mbleigh/acts-as-taggable-on/pull/383)
89
+ * [cwoodcox #346](https://github.com/mbleigh/acts-as-taggable-on/pull/346)
90
+ * [mrb #421](https://github.com/mbleigh/acts-as-taggable-on/pull/421)
91
+ * [bf4 #430](https://github.com/mbleigh/acts-as-taggable-on/pull/430)
92
+ * [sanemat #368](https://github.com/mbleigh/acts-as-taggable-on/pull/368)
93
+ * [bf4 #343](https://github.com/mbleigh/acts-as-taggable-on/pull/343)
94
+ * [marclennox #429](https://github.com/mbleigh/acts-as-taggable-on/pull/429)
95
+ * [shekibobo #403](https://github.com/mbleigh/acts-as-taggable-on/pull/403)
96
+ * [ches ktdreyer #410](https://github.com/mbleigh/acts-as-taggable-on/pull/410)
97
+ * [makaroni4 #371](https://github.com/mbleigh/acts-as-taggable-on/pull/371)
98
+ * [kenzai dstosik awt #431](https://github.com/mbleigh/acts-as-taggable-on/pull/431)
99
+ * [bf4 joelcogen shekibobo aaronchi #438](https://github.com/mbleigh/acts-as-taggable-on/pull/438)
100
+ * [seuros #442](https://github.com/mbleigh/acts-as-taggable-on/pull/442)
101
+ * [bf4 #445](https://github.com/mbleigh/acts-as-taggable-on/pull/445)
102
+ * [eaglemt #446](https://github.com/mbleigh/acts-as-taggable-on/pull/446)
103
+
104
+ ### 3.0.0.rc2 [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/fork-v3.0.0.rc1...fork-v3.0.0.rc2)
105
+
106
+ ### 3.0.0.rc1 [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.1...fork-v3.0.0.rc1)
107
+
108
+ ### [2.4.1 / 2013-05-07](https://github.com/mbleigh/acts-as-taggable-on/compare/v2.4.0...v2.4.1)
109
+
110
+ * Features
111
+ * Fixes
112
+ * Misc
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,44 @@
1
+ # How to contribute:
2
+
3
+ ## Bug reports / Issues
4
+
5
+ * Is something broken or not working as expected? Check for an existing issue or [create a new one](https://github.com/mbleigh/acts-as-taggable-on/issues/new)
6
+ * IMPORTANT: Include the version of the gem, if you've install from git, what Ruby and Rails you are running, etc.
7
+
8
+ ## Code
9
+
10
+ 1. [Fork and clone the repo](https://help.github.com/articles/fork-a-repo)
11
+ 2. Install the gem dependencies: `bundle install`
12
+ 3. Make the changes you want and back them up with tests.
13
+ * [Run the tests](https://github.com/mbleigh/acts-as-taggable-on#testing) (`bundle exec rake spec`)
14
+ 4. Update the CHANGELOG.md file with your changes and give yourself credit
15
+ 5. Commit and create a pull request with details as to what has been changed and why
16
+ * Use well-described, small (atomic) commits.
17
+ * Include links to any relevant github issues.
18
+ * *Don't* change the VERSION file.
19
+ 6. Extra Credit: [Confirm it runs and tests pass on the rubies specified in the travis config](.travis.yml). I will otherwise confirm it runs on these.
20
+
21
+ How I handle pull requests:
22
+
23
+ * If the tests pass and the pull request looks good, I will merge it.
24
+ * If the pull request needs to be changed,
25
+ * you can change it by updating the branch you generated the pull request from
26
+ * either by adding more commits, or
27
+ * by force pushing to it
28
+ * I can make any changes myself and manually merge the code in.
29
+
30
+ ### Commit Messages
31
+
32
+ * [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
33
+ * [http://stopwritingramblingcommitmessages.com/](http://stopwritingramblingcommitmessages.com/)
34
+ * [ThoughtBot style guide](https://github.com/thoughtbot/guides/tree/master/style#git)
35
+
36
+ ### About Pull Requests (PR's)
37
+
38
+ * [All Your Open Source Code Are Belong To Us](http://www.benjaminfleischer.com/2013/07/30/all-your-open-source-code-are-belong-to-us/)
39
+ * [Using Pull Requests](https://help.github.com/articles/using-pull-requests)
40
+ * [Github pull requests made easy](http://www.element84.com/github-pull-requests-made-easy.html)
41
+
42
+ ## Documentation
43
+
44
+ * Update the wiki
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
- source :gemcutter
1
+ source 'https://rubygems.org'
2
2
 
3
- # Rails 3.0
4
- gem 'rails', '3.0.0.beta'
5
- gem 'rspec', '2.0.0.beta.1'
6
- gem 'sqlite3-ruby', '1.2.5', :require => 'sqlite3'
3
+ gemspec
4
+
5
+ group :local_development do
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'appraisal'
9
+ gem 'rake'
10
+ end
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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007 Michael Bleigh and Intridea Inc.
1
+ __Copyright (c) 2007 Michael Bleigh and Intridea Inc.__
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,385 @@
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
+ [![Inline docs](http://inch-pages.github.io/github/mbleigh/acts-as-taggable-on.png)](http://inch-pages.github.io/github/mbleigh/acts-as-taggable-on)
5
+
6
+ This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
7
+ It has evolved substantially since that point, but all credit goes to him for the
8
+ initial tagging functionality that so many people have used.
9
+
10
+ For instance, in a social network, a user might have tags that are called skills,
11
+ interests, sports, and more. There is no real way to differentiate between tags and
12
+ so an implementation of this type is not possible with acts as taggable on steroids.
13
+
14
+ Enter Acts as Taggable On. Rather than tying functionality to a specific keyword
15
+ (namely `tags`), acts as taggable on allows you to specify an arbitrary number of
16
+ tag "contexts" that can be used locally or in combination in the same way steroids
17
+ was used.
18
+
19
+ ## Compatibility
20
+
21
+ Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
22
+
23
+ Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
24
+
25
+ Versions >= 3.x are compatible with Ruby 1.9.3+ and Rails 3 and 4.
26
+
27
+ For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/issues/milestones
28
+
29
+ ## Installation
30
+
31
+ To use it, add it to your Gemfile:
32
+
33
+ ```ruby
34
+ gem 'acts-as-taggable-on'
35
+ ```
36
+
37
+ and bundle:
38
+
39
+ ```shell
40
+ bundle
41
+ ```
42
+
43
+ #### Post Installation
44
+
45
+ Install migrations
46
+
47
+ ```shell
48
+ # For the latest versions :
49
+ rake acts_as_taggable_on_engine:install:migrations
50
+ # For versions 2.4.1 and earlier :
51
+ rails generate acts_as_taggable_on:migration
52
+ ```
53
+
54
+ Review the generated migrations then migrate :
55
+ ```shell
56
+ rake db:migrate
57
+ ```
58
+
59
+ #### Upgrading
60
+
61
+ see [UPGRADING](UPGRADING.md)
62
+
63
+ ## Usage
64
+
65
+ Setup
66
+
67
+ ```ruby
68
+ class User < ActiveRecord::Base
69
+ acts_as_taggable # Alias for acts_as_taggable_on :tags
70
+ acts_as_taggable_on :skills, :interests
71
+ end
72
+
73
+ @user = User.new(:name => "Bobby")
74
+ ```
75
+
76
+ Add and remove a single tag
77
+
78
+ ```ruby
79
+ @user.tag_list.add("awesome") # add a single tag. alias for <<
80
+ @user.tag_list.remove("awesome") # remove a single tag
81
+ ```
82
+
83
+ Add and remove multiple tags in an array
84
+
85
+ ```ruby
86
+ @user.tag_list.add("awesome", "slick")
87
+ @user.tag_list.remove("awesome", "slick")
88
+ ```
89
+
90
+ You can also add and remove tags in format of String. This would
91
+ be convenient in some cases such as handling tag input param in a String.
92
+
93
+ Pay attention you need to add `parse: true` as option in this case.
94
+
95
+ You may also want to take a look at delimiter in the string. The default
96
+ is comma `,` so you don't need to do anything here. However, if you made
97
+ a change on delimiter setting, make sure the string will match. See
98
+ [configuration](#configuration) for more about delimiter.
99
+
100
+ ```ruby
101
+ @user.tag_list.add("awesome, slick", parse: true)
102
+ @user.tag_list.remove("awesome, slick", parse: true)
103
+ ```
104
+
105
+ You can also add and remove tags by direct assignment. Note this will
106
+ remove existing tags so use it with attention.
107
+
108
+ ```ruby
109
+ @user.tag_list = "awesome, slick, hefty"
110
+ @user.save
111
+ @user.reload
112
+ @user.tags
113
+ => [#<ActsAsTaggableOn::Tag id: 1, name: "awesome", taggings_count: 1>,
114
+ #<ActsAsTaggableOn::Tag id: 2, name: "slick", taggings_count: 1>,
115
+ #<ActsAsTaggableOn::Tag id: 3, name: "hefty", taggings_count: 1>]
116
+ ```
117
+
118
+ With the defined context in model, you have multiple new methods at disposal
119
+ to manage and view the tags in the context. For example, with `:skill` context
120
+ these methods are added to the model: `skill_list`(and `skill_list.add`, `skill_list.remove`
121
+ `skill_list=`), `skills`(plural), `skill_counts`.
122
+
123
+ ```ruby
124
+ @user.skill_list = "joking, clowning, boxing"
125
+ @user.save
126
+ @user.reload
127
+ @user.skills
128
+ => [#<ActsAsTaggableOn::Tag id: 1, name: "joking", taggings_count: 1>,
129
+ #<ActsAsTaggableOn::Tag id: 2, name: "clowning", taggings_count: 1>,
130
+ #<ActsAsTaggableOn::Tag id: 3, name: "boxing", taggings_count: 1>]
131
+
132
+ @user.skill_list.add("coding")
133
+
134
+ @user.skill_list
135
+ # => ["joking", "clowning", "boxing", "coding"]
136
+
137
+ @another_user = User.new(:name => "Alice")
138
+ @another_user.skill_list.add("clowning")
139
+ @another_user.save
140
+
141
+ User.skill_counts
142
+ => [#<ActsAsTaggableOn::Tag id: 1, name: "joking", taggings_count: 1>,
143
+ #<ActsAsTaggableOn::Tag id: 2, name: "clowning", taggings_count: 2>,
144
+ #<ActsAsTaggableOn::Tag id: 3, name: "boxing", taggings_count: 1>]
145
+ ```
146
+
147
+ To preserve the order in which tags are created use `acts_as_ordered_taggable`:
148
+
149
+ ```ruby
150
+ class User < ActiveRecord::Base
151
+ # Alias for acts_as_ordered_taggable_on :tags
152
+ acts_as_ordered_taggable
153
+ acts_as_ordered_taggable_on :skills, :interests
154
+ end
155
+
156
+ @user = User.new(:name => "Bobby")
157
+ @user.tag_list = "east, south"
158
+ @user.save
159
+
160
+ @user.tag_list = "north, east, south, west"
161
+ @user.save
162
+
163
+ @user.reload
164
+ @user.tag_list # => ["north", "east", "south", "west"]
165
+ ```
166
+
167
+ ### Finding Tagged Objects
168
+
169
+ Acts As Taggable On uses scopes to create an association for tags.
170
+ This way you can mix and match to filter down your results.
171
+
172
+ ```ruby
173
+ class User < ActiveRecord::Base
174
+ acts_as_taggable_on :tags, :skills
175
+ scope :by_join_date, order("created_at DESC")
176
+ end
177
+
178
+ User.tagged_with("awesome").by_join_date
179
+ User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
180
+
181
+ # Find users that matches all given tags:
182
+ User.tagged_with(["awesome", "cool"], :match_all => true)
183
+
184
+ # Find users with any of the specified tags:
185
+ User.tagged_with(["awesome", "cool"], :any => true)
186
+
187
+ # Find users that has not been tagged with awesome or cool:
188
+ User.tagged_with(["awesome", "cool"], :exclude => true)
189
+
190
+ # Find users with any of the tags based on context:
191
+ User.tagged_with(['awesome', 'cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
192
+ ```
193
+
194
+ You can also use `:wild => true` option along with `:any` or `:exclude` option. It will be looking for `%awesome%` and `%cool%` in SQL.
195
+
196
+ __Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`, an empty set of records.
197
+
198
+ ### Relationships
199
+
200
+ You can find objects of the same type based on similar tags on certain contexts.
201
+ Also, objects will be returned in descending order based on the total number of
202
+ matched tags.
203
+
204
+ ```ruby
205
+ @bobby = User.find_by_name("Bobby")
206
+ @bobby.skill_list # => ["jogging", "diving"]
207
+
208
+ @frankie = User.find_by_name("Frankie")
209
+ @frankie.skill_list # => ["hacking"]
210
+
211
+ @tom = User.find_by_name("Tom")
212
+ @tom.skill_list # => ["hacking", "jogging", "diving"]
213
+
214
+ @tom.find_related_skills # => [<User name="Bobby">, <User name="Frankie">]
215
+ @bobby.find_related_skills # => [<User name="Tom">]
216
+ @frankie.find_related_skills # => [<User name="Tom">]
217
+ ```
218
+
219
+ ### Dynamic Tag Contexts
220
+
221
+ In addition to the generated tag contexts in the definition, it is also possible
222
+ to allow for dynamic tag contexts (this could be user generated tag contexts!)
223
+
224
+ ```ruby
225
+ @user = User.new(:name => "Bobby")
226
+ @user.set_tag_list_on(:customs, "same, as, tag, list")
227
+ @user.tag_list_on(:customs) # => ["same", "as", "tag", "list"]
228
+ @user.save
229
+ @user.tags_on(:customs) # => [<Tag name='same'>,...]
230
+ @user.tag_counts_on(:customs)
231
+ User.tagged_with("same", :on => :customs) # => [@user]
232
+ ```
233
+
234
+ ### Tag Ownership
235
+
236
+ Tags can have owners:
237
+
238
+ ```ruby
239
+ class User < ActiveRecord::Base
240
+ acts_as_tagger
241
+ end
242
+
243
+ class Photo < ActiveRecord::Base
244
+ acts_as_taggable_on :locations
245
+ end
246
+
247
+ @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
248
+ @some_user.owned_taggings
249
+ @some_user.owned_tags
250
+ Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
251
+ @some_photo.locations_from(@some_user) # => ["paris", "normandy"]
252
+ @some_photo.owner_tags_on(@some_user, :locations) # => [#<ActsAsTaggableOn::Tag id: 1, name: "paris">...]
253
+ @some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
254
+ @some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
255
+ ```
256
+
257
+ ### Dirty objects
258
+
259
+ ```ruby
260
+ @bobby = User.find_by_name("Bobby")
261
+ @bobby.skill_list # => ["jogging", "diving"]
262
+
263
+ @bobby.skill_list_changed? #=> false
264
+ @bobby.changes #=> {}
265
+
266
+ @bobby.skill_list = "swimming"
267
+ @bobby.changes.should == {"skill_list"=>["jogging, diving", ["swimming"]]}
268
+ @bobby.skill_list_changed? #=> true
269
+
270
+ @bobby.skill_list_change.should == ["jogging, diving", ["swimming"]]
271
+ ```
272
+
273
+ ### Tag cloud calculations
274
+
275
+ To construct tag clouds, the frequency of each tag needs to be calculated.
276
+ Because we specified `acts_as_taggable_on` on the `User` class, we can
277
+ get a calculation of all the tag counts by using `User.tag_counts_on(:customs)`. But what if we wanted a tag count for
278
+ a single user's posts? To achieve this we call tag_counts on the association:
279
+
280
+ ```ruby
281
+ User.find(:first).posts.tag_counts_on(:tags)
282
+ ```
283
+
284
+ A helper is included to assist with generating tag clouds.
285
+
286
+ Here is an example that generates a tag cloud.
287
+
288
+ Helper:
289
+
290
+ ```ruby
291
+ module PostsHelper
292
+ include ActsAsTaggableOn::TagsHelper
293
+ end
294
+ ```
295
+
296
+ Controller:
297
+
298
+ ```ruby
299
+ class PostController < ApplicationController
300
+ def tag_cloud
301
+ @tags = Post.tag_counts_on(:tags)
302
+ end
303
+ end
304
+ ```
305
+
306
+ View:
307
+
308
+ ```erb
309
+ <% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
310
+ <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
311
+ <% end %>
312
+ ```
313
+
314
+ CSS:
315
+
316
+ ```css
317
+ .css1 { font-size: 1.0em; }
318
+ .css2 { font-size: 1.2em; }
319
+ .css3 { font-size: 1.4em; }
320
+ .css4 { font-size: 1.6em; }
321
+ ```
322
+
323
+ ## Configuration
324
+
325
+ If you would like to remove unused tag objects after removing taggings, add:
326
+
327
+ ```ruby
328
+ ActsAsTaggableOn.remove_unused_tags = true
329
+ ```
330
+
331
+ If you want force tags to be saved downcased:
332
+
333
+ ```ruby
334
+ ActsAsTaggableOn.force_lowercase = true
335
+ ```
336
+
337
+ If you want tags to be saved parametrized (you can redefine to_param as well):
338
+
339
+ ```ruby
340
+ ActsAsTaggableOn.force_parameterize = true
341
+ ```
342
+
343
+ If you would like tags to be case-sensitive and not use LIKE queries for creation:
344
+
345
+ ```ruby
346
+ ActsAsTaggableOn.strict_case_match = true
347
+ ```
348
+
349
+ If you want to change the default delimiter (it defaults to ','). You can also pass in an array of delimiters such as ([',', '|']):
350
+
351
+ ```ruby
352
+ ActsAsTaggableOn.delimiter = ','
353
+ ```
354
+
355
+ *NOTE: SQLite by default can't upcase or downcase multibyte characters, resulting in unwanted behavior. Load the SQLite ICU extension for proper handle of such characters. [See docs](http://www.sqlite.org/src/artifact?ci=trunk&filename=ext/icu/README.txt)*
356
+
357
+ ## Contributors
358
+
359
+ We have a long list of valued contributors. [Check them all](https://github.com/mbleigh/acts-as-taggable-on/contributors)
360
+
361
+ ## Maintainer
362
+
363
+ * [Joost Baaij](https://github.com/tilsammans)
364
+
365
+ ## TODO
366
+
367
+ - Write benchmark script
368
+ - Resolve concurrency issues
369
+
370
+ ## Testing
371
+
372
+ Acts As Taggable On uses RSpec for its test coverage. Inside the gem
373
+ directory, you can run the specs with:
374
+
375
+ ```shell
376
+ bundle
377
+ rake spec
378
+ ```
379
+
380
+ You can run all the tests across all the Rails versions by running `rake appraise`. If you'd also like to [run the tests across all rubies and databases as configured for Travis CI, install and run `wwtd`](https://github.com/grosser/wwtd).
381
+
382
+
383
+ ## License
384
+
385
+ See [LICENSE](https://github.com/mbleigh/acts-as-taggable-on/blob/master/LICENSE.md)