acts-as-taggable-on 3.2.1 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -15
- data/README.md +17 -10
- data/acts-as-taggable-on.gemspec +7 -7
- data/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb +1 -0
- data/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +23 -23
- data/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +5 -5
- data/lib/acts_as_taggable_on/tag_list.rb +2 -1
- data/lib/acts_as_taggable_on/taggable.rb +0 -2
- data/lib/acts_as_taggable_on/utils.rb +44 -44
- data/lib/acts_as_taggable_on/version.rb +1 -1
- data/spec/acts_as_taggable_on/tag_spec.rb +7 -5
- data/spec/acts_as_taggable_on/taggable_spec.rb +25 -24
- data/spec/acts_as_taggable_on/utils_spec.rb +5 -11
- data/spec/internal/db/schema.rb +1 -1
- data/spec/support/database_cleaner.rb +4 -0
- metadata +28 -30
- data/spec/bm.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc40e6d7c5c8b741bfc71aee7ae2406c6f824108
|
4
|
+
data.tar.gz: 3c89e20ed3b39ef33d52724d4bb8b9aa3e5738f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4142af492646d113a10fa0ae4815d91a281f2a55d60fb70b653a96d4ac58e24c56e1e10bcbf9907bbcc06cee2b476b6ec4a568cc25e5247578a140cbf388d85
|
7
|
+
data.tar.gz: eceb8e025f83cdbc9e237405eac982aa3b7c7ef0f54d803fcd80d1ed837b833d4f07fe549f0eb0eaa443edb5cdc84bcad79555a67a886e7fc706b46aa5d37b35
|
data/CHANGELOG.md
CHANGED
@@ -4,21 +4,33 @@ Each change should fall into categories that would affect whether the release is
|
|
4
4
|
|
5
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
6
|
|
7
|
-
### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.
|
8
|
-
|
9
|
-
* Breaking Changes
|
10
|
-
*
|
11
|
-
*
|
12
|
-
* Fixes
|
13
|
-
*
|
14
|
-
*
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
*
|
21
|
-
|
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)
|
22
34
|
|
23
35
|
### [3.1.0 / 2014-03-31](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.0.1...v3.1.0)
|
24
36
|
|
data/README.md
CHANGED
@@ -135,11 +135,13 @@ these methods are added to the model: `skill_list`(and `skill_list.add`, `skill_
|
|
135
135
|
# => ["joking", "clowning", "boxing", "coding"]
|
136
136
|
|
137
137
|
@another_user = User.new(:name => "Alice")
|
138
|
-
@
|
139
|
-
@
|
138
|
+
@another_user.skill_list.add("clowning")
|
139
|
+
@another_user.save
|
140
140
|
|
141
141
|
User.skill_counts
|
142
|
-
=> [#<ActsAsTaggableOn::Tag id: 1, name: "joking", taggings_count:
|
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>]
|
143
145
|
```
|
144
146
|
|
145
147
|
To preserve the order in which tags are created use `acts_as_ordered_taggable`:
|
@@ -176,22 +178,22 @@ end
|
|
176
178
|
User.tagged_with("awesome").by_join_date
|
177
179
|
User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
|
178
180
|
|
179
|
-
# Find
|
181
|
+
# Find users that matches all given tags:
|
180
182
|
User.tagged_with(["awesome", "cool"], :match_all => true)
|
181
183
|
|
182
|
-
# Find
|
184
|
+
# Find users with any of the specified tags:
|
183
185
|
User.tagged_with(["awesome", "cool"], :any => true)
|
184
186
|
|
185
|
-
# Find
|
187
|
+
# Find users that has not been tagged with awesome or cool:
|
186
188
|
User.tagged_with(["awesome", "cool"], :exclude => true)
|
187
189
|
|
188
|
-
# Find
|
190
|
+
# Find users with any of the tags based on context:
|
189
191
|
User.tagged_with(['awesome', 'cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
|
190
192
|
```
|
191
193
|
|
192
|
-
You can also use `:wild => true` option along with `:any` or `:exclude` option. It will looking for `%awesome%` and `%cool%` in
|
194
|
+
You can also use `:wild => true` option along with `:any` or `:exclude` option. It will be looking for `%awesome%` and `%cool%` in SQL.
|
193
195
|
|
194
|
-
__Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`,
|
196
|
+
__Tip:__ `User.tagged_with([])` or `User.tagged_with('')` will return `[]`, an empty set of records.
|
195
197
|
|
196
198
|
### Relationships
|
197
199
|
|
@@ -273,7 +275,7 @@ Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
|
|
273
275
|
To construct tag clouds, the frequency of each tag needs to be calculated.
|
274
276
|
Because we specified `acts_as_taggable_on` on the `User` class, we can
|
275
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
|
276
|
-
|
278
|
+
a single user's posts? To achieve this we call tag_counts on the association:
|
277
279
|
|
278
280
|
```ruby
|
279
281
|
User.find(:first).posts.tag_counts_on(:tags)
|
@@ -360,6 +362,11 @@ We have a long list of valued contributors. [Check them all](https://github.com/
|
|
360
362
|
|
361
363
|
* [Joost Baaij](https://github.com/tilsammans)
|
362
364
|
|
365
|
+
## TODO
|
366
|
+
|
367
|
+
- Write benchmark script
|
368
|
+
- Resolve concurrency issues
|
369
|
+
|
363
370
|
## Testing
|
364
371
|
|
365
372
|
Acts As Taggable On uses RSpec for its test coverage. Inside the gem
|
data/acts-as-taggable-on.gemspec
CHANGED
@@ -26,13 +26,13 @@ Gem::Specification.new do |gem|
|
|
26
26
|
gem.add_runtime_dependency 'actionpack', ['>= 3', '< 5']
|
27
27
|
|
28
28
|
gem.add_development_dependency 'sqlite3'
|
29
|
-
gem.add_development_dependency 'mysql2'
|
29
|
+
gem.add_development_dependency 'mysql2'
|
30
30
|
gem.add_development_dependency 'pg'
|
31
31
|
|
32
|
-
gem.add_development_dependency 'rspec-rails' , '~> 3.0.0.
|
33
|
-
gem.add_development_dependency 'rspec-its'
|
34
|
-
gem.add_development_dependency 'rspec'
|
35
|
-
gem.add_development_dependency 'ammeter'
|
36
|
-
gem.add_development_dependency 'barrier'
|
37
|
-
gem.add_development_dependency 'database_cleaner'
|
32
|
+
gem.add_development_dependency 'rspec-rails' , '~> 3.0.0.beta2'
|
33
|
+
gem.add_development_dependency 'rspec-its', '~> 1.0'
|
34
|
+
gem.add_development_dependency 'rspec', '3.0.0.beta2'
|
35
|
+
gem.add_development_dependency 'ammeter', '~> 1.0'
|
36
|
+
gem.add_development_dependency 'barrier', '~> 1.0'
|
37
|
+
gem.add_development_dependency 'database_cleaner', '~> 1.2'
|
38
38
|
end
|
@@ -31,6 +31,7 @@ module ActsAsTaggableOn::Taggable
|
|
31
31
|
# to mimic the underlying behavior. While processing this first
|
32
32
|
# call to columns, we do the caching column check and dynamically add
|
33
33
|
# the class and instance methods
|
34
|
+
# FIXME: this method cannot compile in rubinius
|
34
35
|
def columns
|
35
36
|
@acts_as_taggable_on_cache_columns ||= begin
|
36
37
|
db_columns = super
|
@@ -24,16 +24,16 @@ module ActsAsTaggableOn::Taggable
|
|
24
24
|
# when preserving tag order, include order option so that for a 'tags' context
|
25
25
|
# the associations tag_taggings & tags are always returned in created order
|
26
26
|
has_many_with_taggable_compatibility context_taggings, as: :taggable,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
dependent: :destroy,
|
28
|
+
class_name: 'ActsAsTaggableOn::Tagging',
|
29
|
+
order: taggings_order,
|
30
|
+
conditions: ["#{ActsAsTaggableOn::Tagging.table_name}.context = (?)", tags_type],
|
31
|
+
include: :tag
|
32
32
|
|
33
33
|
has_many_with_taggable_compatibility context_tags, through: context_taggings,
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
source: :tag,
|
35
|
+
class_name: 'ActsAsTaggableOn::Tag',
|
36
|
+
order: taggings_order
|
37
37
|
|
38
38
|
end
|
39
39
|
|
@@ -130,7 +130,7 @@ module ActsAsTaggableOn::Taggable
|
|
130
130
|
taggings_context = context ? "_#{context}" : ''
|
131
131
|
|
132
132
|
taggings_alias = adjust_taggings_alias(
|
133
|
-
"#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}"
|
133
|
+
"#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{ActsAsTaggableOn::Utils.sha_prefix(tags.map(&:name).join('_'))}"
|
134
134
|
)
|
135
135
|
|
136
136
|
tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" \
|
@@ -145,9 +145,9 @@ module ActsAsTaggableOn::Taggable
|
|
145
145
|
if owned_by
|
146
146
|
tagging_join << ' AND ' +
|
147
147
|
sanitize_sql([
|
148
|
-
|
149
|
-
|
150
|
-
|
148
|
+
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
|
149
|
+
owned_by.id,
|
150
|
+
owned_by.class.base_class.to_s
|
151
151
|
])
|
152
152
|
end
|
153
153
|
|
@@ -159,7 +159,7 @@ module ActsAsTaggableOn::Taggable
|
|
159
159
|
return empty_result unless tags.length == tag_list.length
|
160
160
|
|
161
161
|
tags.each do |tag|
|
162
|
-
taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}")
|
162
|
+
taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{ActsAsTaggableOn::Utils.sha_prefix(tag.name)}")
|
163
163
|
tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" \
|
164
164
|
" ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
|
165
165
|
" AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}" +
|
@@ -170,9 +170,9 @@ module ActsAsTaggableOn::Taggable
|
|
170
170
|
if owned_by
|
171
171
|
tagging_join << ' AND ' +
|
172
172
|
sanitize_sql([
|
173
|
-
|
174
|
-
|
175
|
-
|
173
|
+
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
|
174
|
+
owned_by.id,
|
175
|
+
owned_by.class.base_class.to_s
|
176
176
|
])
|
177
177
|
end
|
178
178
|
|
@@ -202,13 +202,13 @@ module ActsAsTaggableOn::Taggable
|
|
202
202
|
|
203
203
|
order_by << options[:order] if options[:order].present?
|
204
204
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
205
|
+
select(select_clause)
|
206
|
+
.joins(joins.join(' '))
|
207
|
+
.where(conditions.join(' AND '))
|
208
|
+
.group(group)
|
209
|
+
.having(having)
|
210
|
+
.order(order_by.join(', '))
|
211
|
+
.readonly(false)
|
212
212
|
end
|
213
213
|
|
214
214
|
def is_taggable?
|
@@ -61,11 +61,11 @@ module ActsAsTaggableOn::Taggable
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def related_where(klass, conditions)
|
64
|
-
klass.select("#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count")
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
klass.select("#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count")
|
65
|
+
.from("#{klass.table_name}, #{ActsAsTaggableOn::Tag.table_name}, #{ActsAsTaggableOn::Tagging.table_name}")
|
66
|
+
.group(group_columns(klass))
|
67
|
+
.order('count DESC')
|
68
|
+
.where(conditions)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -149,9 +149,10 @@ module ActsAsTaggableOn
|
|
149
149
|
|
150
150
|
private
|
151
151
|
|
152
|
-
#
|
152
|
+
# Convert everything to string, remove whitespace, duplicates, and blanks.
|
153
153
|
def clean!
|
154
154
|
reject!(&:blank?)
|
155
|
+
map!(&:to_s)
|
155
156
|
map!(&:strip)
|
156
157
|
map! { |tag| tag.mb_chars.downcase.to_s } if ActsAsTaggableOn.force_lowercase
|
157
158
|
map!(&:parameterize) if ActsAsTaggableOn.force_parameterize
|
@@ -1,62 +1,62 @@
|
|
1
1
|
module ActsAsTaggableOn
|
2
2
|
module Utils
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
3
|
+
class << self
|
4
|
+
# Use ActsAsTaggableOn::Tag connection
|
5
|
+
def connection
|
6
|
+
ActsAsTaggableOn::Tag.connection
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def using_postgresql?
|
10
|
+
connection && connection.adapter_name == 'PostgreSQL'
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def postgresql_version
|
14
|
+
if using_postgresql?
|
15
|
+
connection.execute('SHOW SERVER_VERSION').first['server_version'].to_f
|
16
|
+
end
|
17
17
|
end
|
18
|
-
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def postgresql_support_json?
|
20
|
+
postgresql_version >= 9.2
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
def using_sqlite?
|
24
|
+
connection && connection.adapter_name == 'SQLite'
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def using_mysql?
|
28
|
+
#We should probably use regex for mysql to support prehistoric adapters
|
29
|
+
connection && connection.adapter_name == 'Mysql2'
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
def using_case_insensitive_collation?
|
33
|
+
using_mysql? && connection.collation =~ /_ci\Z/
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
def supports_concurrency?
|
37
|
+
!using_sqlite?
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
def sha_prefix(string)
|
41
|
+
Digest::SHA1.hexdigest("#{string}#{rand}")[0..6]
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
def active_record4?
|
45
|
+
::ActiveRecord::VERSION::MAJOR == 4
|
46
|
+
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def active_record42?
|
49
|
+
active_record4? && ::ActiveRecord::VERSION::MINOR >= 2
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
def like_operator
|
53
|
+
using_postgresql? ? 'ILIKE' : 'LIKE'
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
# escape _ and % characters in strings, since these are wildcards in SQL.
|
57
|
+
def escape_like(str)
|
58
|
+
str.gsub(/[!%_]/) { |x| '!' + x }
|
59
|
+
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -3,8 +3,11 @@ require 'spec_helper'
|
|
3
3
|
require 'db/migrate/2_add_missing_unique_indices.rb'
|
4
4
|
|
5
5
|
shared_examples_for 'without unique index' do
|
6
|
-
|
7
|
-
|
6
|
+
prepend_before(:all) { AddMissingUniqueIndices.down }
|
7
|
+
append_after(:all) do
|
8
|
+
ActsAsTaggableOn::Tag.delete_all
|
9
|
+
AddMissingUniqueIndices.up
|
10
|
+
end
|
8
11
|
end
|
9
12
|
|
10
13
|
describe ActsAsTaggableOn::Tag do
|
@@ -14,10 +17,9 @@ describe ActsAsTaggableOn::Tag do
|
|
14
17
|
end
|
15
18
|
|
16
19
|
|
17
|
-
|
18
20
|
describe 'named like any' do
|
19
|
-
|
20
|
-
|
21
|
+
if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
|
22
|
+
context 'case insensitive collation and unique index on tag name' do
|
21
23
|
before(:each) do
|
22
24
|
ActsAsTaggableOn::Tag.create(name: 'Awesome')
|
23
25
|
ActsAsTaggableOn::Tag.create(name: 'epic')
|
@@ -621,8 +621,8 @@ describe 'Taggable' do
|
|
621
621
|
it 'should return all column names joined for Tag GROUP clause' do
|
622
622
|
# NOTE: type column supports an STI Tag subclass in the test suite, though
|
623
623
|
# isn't included by default in the migration generator
|
624
|
-
expect(@taggable.grouped_column_names_for(ActsAsTaggableOn::Tag))
|
625
|
-
|
624
|
+
expect(@taggable.grouped_column_names_for(ActsAsTaggableOn::Tag))
|
625
|
+
.to eq('tags.id, tags.name, tags.taggings_count, tags.type')
|
626
626
|
end
|
627
627
|
|
628
628
|
it 'should return all column names joined for TaggableModel GROUP clause' do
|
@@ -847,33 +847,34 @@ describe 'Taggable' do
|
|
847
847
|
end
|
848
848
|
end
|
849
849
|
|
850
|
-
|
851
850
|
if ActsAsTaggableOn::Utils.using_postgresql?
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
851
|
+
if ActsAsTaggableOn::Utils.postgresql_support_json?
|
852
|
+
describe 'Taggable model with json columns' do
|
853
|
+
before(:each) do
|
854
|
+
@taggable = TaggableModelWithJson.new(:name => 'Bob Jones')
|
855
|
+
@taggables = [@taggable, TaggableModelWithJson.new(:name => 'John Doe')]
|
856
|
+
end
|
857
857
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
858
|
+
it 'should be able to find by tag with context' do
|
859
|
+
@taggable.skill_list = 'ruby, rails, css'
|
860
|
+
@taggable.tag_list = 'bob, charlie'
|
861
|
+
@taggable.save
|
862
862
|
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
863
|
+
expect(TaggableModelWithJson.tagged_with('ruby').first).to eq(@taggable)
|
864
|
+
expect(TaggableModelWithJson.tagged_with('ruby, css').first).to eq(@taggable)
|
865
|
+
expect(TaggableModelWithJson.tagged_with('bob', :on => :skills).first).to_not eq(@taggable)
|
866
|
+
expect(TaggableModelWithJson.tagged_with('bob', :on => :tags).first).to eq(@taggable)
|
867
|
+
end
|
868
868
|
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
869
|
+
it 'should be able to find tagged with any tag' do
|
870
|
+
bob = TaggableModelWithJson.create(:name => 'Bob', :tag_list => 'fitter, happier, more productive', :skill_list => 'ruby, rails, css')
|
871
|
+
frank = TaggableModelWithJson.create(:name => 'Frank', :tag_list => 'weaker, depressed, inefficient', :skill_list => 'ruby, rails, css')
|
872
|
+
steve = TaggableModelWithJson.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
|
873
873
|
|
874
|
-
|
875
|
-
|
876
|
-
|
874
|
+
expect(TaggableModelWithJson.tagged_with(%w(ruby java), :order => 'taggable_model_with_jsons.name', :any => true).to_a).to eq([bob, frank, steve])
|
875
|
+
expect(TaggableModelWithJson.tagged_with(%w(c++ fitter), :order => 'taggable_model_with_jsons.name', :any => true).to_a).to eq([bob, steve])
|
876
|
+
expect(TaggableModelWithJson.tagged_with(%w(depressed css), :order => 'taggable_model_with_jsons.name', :any => true).to_a).to eq([bob, frank])
|
877
|
+
end
|
877
878
|
end
|
878
879
|
end
|
879
880
|
end
|
@@ -1,21 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ActsAsTaggableOn::Utils do
|
4
|
-
describe 'like_operator' do
|
5
|
-
before(:each) do
|
6
|
-
TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
|
7
|
-
@taggable = TaggableModel.new(name: 'Bob Jones')
|
8
|
-
end
|
9
|
-
|
10
|
-
|
4
|
+
describe '#like_operator' do
|
11
5
|
it 'should return \'ILIKE\' when the adapter is PostgreSQL' do
|
12
|
-
allow(
|
13
|
-
expect(
|
6
|
+
allow(ActsAsTaggableOn::Utils.connection).to receive(:adapter_name) { 'PostgreSQL' }
|
7
|
+
expect(ActsAsTaggableOn::Utils.like_operator).to eq('ILIKE')
|
14
8
|
end
|
15
9
|
|
16
10
|
it 'should return \'LIKE\' when the adapter is not PostgreSQL' do
|
17
|
-
allow(
|
18
|
-
expect(
|
11
|
+
allow(ActsAsTaggableOn::Utils.connection).to receive(:adapter_name) { 'MySQL' }
|
12
|
+
expect(ActsAsTaggableOn::Utils.like_operator).to eq('LIKE')
|
19
13
|
end
|
20
14
|
end
|
21
15
|
end
|
data/spec/internal/db/schema.rb
CHANGED
@@ -86,7 +86,7 @@ ActiveRecord::Schema.define version: 0 do
|
|
86
86
|
t.column :cached_glass_list, :string, array: true
|
87
87
|
end
|
88
88
|
|
89
|
-
if
|
89
|
+
if ActsAsTaggableOn::Utils.postgresql_support_json?
|
90
90
|
create_table :taggable_model_with_jsons, :force => true do |t|
|
91
91
|
t.column :name, :string
|
92
92
|
t.column :type, :string
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts-as-taggable-on
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bleigh
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
12
|
+
date: 2014-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -69,16 +69,16 @@ dependencies:
|
|
69
69
|
name: mysql2
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- - "
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0
|
74
|
+
version: '0'
|
75
75
|
type: :development
|
76
76
|
prerelease: false
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- - "
|
79
|
+
- - ">="
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: 0
|
81
|
+
version: '0'
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
name: pg
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -99,84 +99,84 @@ dependencies:
|
|
99
99
|
requirements:
|
100
100
|
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version: 3.0.0.
|
102
|
+
version: 3.0.0.beta2
|
103
103
|
type: :development
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 3.0.0.
|
109
|
+
version: 3.0.0.beta2
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
111
|
name: rspec-its
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
|
-
- - "
|
114
|
+
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version: '0'
|
116
|
+
version: '1.0'
|
117
117
|
type: :development
|
118
118
|
prerelease: false
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- - "
|
121
|
+
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: '0'
|
123
|
+
version: '1.0'
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rspec
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
|
-
- -
|
128
|
+
- - '='
|
129
129
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
130
|
+
version: 3.0.0.beta2
|
131
131
|
type: :development
|
132
132
|
prerelease: false
|
133
133
|
version_requirements: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
|
-
- -
|
135
|
+
- - '='
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version:
|
137
|
+
version: 3.0.0.beta2
|
138
138
|
- !ruby/object:Gem::Dependency
|
139
139
|
name: ammeter
|
140
140
|
requirement: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
|
-
- - "
|
142
|
+
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '0'
|
144
|
+
version: '1.0'
|
145
145
|
type: :development
|
146
146
|
prerelease: false
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
148
148
|
requirements:
|
149
|
-
- - "
|
149
|
+
- - "~>"
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: '0'
|
151
|
+
version: '1.0'
|
152
152
|
- !ruby/object:Gem::Dependency
|
153
153
|
name: barrier
|
154
154
|
requirement: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
|
-
- - "
|
156
|
+
- - "~>"
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version: '0'
|
158
|
+
version: '1.0'
|
159
159
|
type: :development
|
160
160
|
prerelease: false
|
161
161
|
version_requirements: !ruby/object:Gem::Requirement
|
162
162
|
requirements:
|
163
|
-
- - "
|
163
|
+
- - "~>"
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: '0'
|
165
|
+
version: '1.0'
|
166
166
|
- !ruby/object:Gem::Dependency
|
167
167
|
name: database_cleaner
|
168
168
|
requirement: !ruby/object:Gem::Requirement
|
169
169
|
requirements:
|
170
|
-
- - "
|
170
|
+
- - "~>"
|
171
171
|
- !ruby/object:Gem::Version
|
172
|
-
version: '
|
172
|
+
version: '1.2'
|
173
173
|
type: :development
|
174
174
|
prerelease: false
|
175
175
|
version_requirements: !ruby/object:Gem::Requirement
|
176
176
|
requirements:
|
177
|
-
- - "
|
177
|
+
- - "~>"
|
178
178
|
- !ruby/object:Gem::Version
|
179
|
-
version: '
|
179
|
+
version: '1.2'
|
180
180
|
description: With ActsAsTaggableOn, you can tag a single model on several contexts,
|
181
181
|
such as skills, interests, and awards. It also provides other advanced functionality.
|
182
182
|
email:
|
@@ -236,7 +236,6 @@ files:
|
|
236
236
|
- spec/acts_as_taggable_on/tagging_spec.rb
|
237
237
|
- spec/acts_as_taggable_on/tags_helper_spec.rb
|
238
238
|
- spec/acts_as_taggable_on/utils_spec.rb
|
239
|
-
- spec/bm.rb
|
240
239
|
- spec/internal/app/models/altered_inheriting_taggable_model.rb
|
241
240
|
- spec/internal/app/models/cached_model.rb
|
242
241
|
- spec/internal/app/models/cached_model_with_array.rb
|
@@ -309,7 +308,6 @@ test_files:
|
|
309
308
|
- spec/acts_as_taggable_on/tagging_spec.rb
|
310
309
|
- spec/acts_as_taggable_on/tags_helper_spec.rb
|
311
310
|
- spec/acts_as_taggable_on/utils_spec.rb
|
312
|
-
- spec/bm.rb
|
313
311
|
- spec/internal/app/models/altered_inheriting_taggable_model.rb
|
314
312
|
- spec/internal/app/models/cached_model.rb
|
315
313
|
- spec/internal/app/models/cached_model_with_array.rb
|
data/spec/bm.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
require 'action_view'
|
3
|
-
require File.expand_path('../../lib/acts-as-taggable-on', __FILE__)
|
4
|
-
|
5
|
-
if defined?(ActiveRecord::Acts::TaggableOn)
|
6
|
-
ActiveRecord::Base.send :include, ActiveRecord::Acts::TaggableOn
|
7
|
-
ActiveRecord::Base.send :include, ActiveRecord::Acts::Tagger
|
8
|
-
ActionView::Base.send :include, TagsHelper if defined?(ActionView::Base)
|
9
|
-
end
|
10
|
-
|
11
|
-
TEST_DATABASE_FILE = File.join(File.dirname(__FILE__), '..', 'test.sqlite3')
|
12
|
-
File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
|
13
|
-
ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => TEST_DATABASE_FILE
|
14
|
-
|
15
|
-
ActiveRecord::Base.silence do
|
16
|
-
ActiveRecord::Migration.verbose = false
|
17
|
-
ActiveRecord::Schema.define :version => 0 do
|
18
|
-
create_table "taggings", :force => true do |t|
|
19
|
-
t.integer "tag_id", :limit => 11
|
20
|
-
t.integer "taggable_id", :limit => 11
|
21
|
-
t.string "taggable_type"
|
22
|
-
t.string "context"
|
23
|
-
t.datetime "created_at"
|
24
|
-
t.integer "tagger_id", :limit => 11
|
25
|
-
t.string "tagger_type"
|
26
|
-
end
|
27
|
-
|
28
|
-
add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
|
29
|
-
add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
|
30
|
-
|
31
|
-
create_table "tags", :force => true do |t|
|
32
|
-
t.string "name"
|
33
|
-
end
|
34
|
-
|
35
|
-
create_table :taggable_models, :force => true do |t|
|
36
|
-
t.column :name, :string
|
37
|
-
t.column :type, :string
|
38
|
-
t.column :cached_tag_list, :string
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class TaggableModel < ActiveRecord::Base
|
43
|
-
acts_as_taggable
|
44
|
-
acts_as_taggable_on :languages
|
45
|
-
acts_as_taggable_on :skills
|
46
|
-
acts_as_taggable_on :needs, :offerings
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
puts Benchmark.measure {
|
51
|
-
1000.times { TaggableModel.create :tag_list => "awesome, epic, neat" }
|
52
|
-
}
|