acts-as-taggable-on 3.4.1 → 3.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/Gemfile +1 -0
- data/README.md +2 -1
- data/lib/acts-as-taggable-on.rb +3 -1
- data/lib/acts_as_taggable_on/tag.rb +12 -11
- data/lib/acts_as_taggable_on/taggable/core.rb +20 -19
- data/lib/acts_as_taggable_on/tagging.rb +6 -2
- data/lib/acts_as_taggable_on/version.rb +1 -1
- data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +16 -0
- data/spec/acts_as_taggable_on/tag_spec.rb +15 -1
- data/spec/acts_as_taggable_on/taggable_spec.rb +2 -1
- data/spec/spec_helper.rb +4 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee9d316a00b3742d99175e8535a48fc94bf32f7c
|
4
|
+
data.tar.gz: 0a2890ba670d7df947c9e3a271d81284abc9ef42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3da825d4c0393da92b3eef9b8f94a140c7335ed6d810476bf3ba6ef7ccfa75409b9445713bebf8b13d4890be1b1c4aa3312197eaa57b9aedae713329c6203877
|
7
|
+
data.tar.gz: 0fb39c27169059d20607f33bc649655474a73003e5a210f4f5706ff73416f558cbb7ca4c94b9268c72a89501e3a6003ea9f9593a3678e09efecf953da3c0a4e6
|
data/CHANGELOG.md
CHANGED
@@ -4,7 +4,7 @@ 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.4.
|
7
|
+
### Master [changes](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.2...master)
|
8
8
|
|
9
9
|
* Breaking Changes
|
10
10
|
* Features
|
@@ -12,6 +12,17 @@ As such, a _Feature_ would map to either major or minor. A _bug fix_ to a patch.
|
|
12
12
|
* Performance
|
13
13
|
* Misc
|
14
14
|
|
15
|
+
### [3.4.2 / 2014-09-26](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.1...v3.4.2)
|
16
|
+
|
17
|
+
* Breaking Changes
|
18
|
+
* Features
|
19
|
+
* Fixes
|
20
|
+
* [@stiff fixed tagged_with :any in postgresql](https://github.com/mbleigh/acts-as-taggable-on/pull/570)
|
21
|
+
* [@jerefrer fixed encoding in mysql](https://github.com/mbleigh/acts-as-taggable-on/pull/588)
|
22
|
+
* [@markedmondson Ensure taggings context aliases are maintained when joining multiple taggables](https://github.com/mbleigh/acts-as-taggable-on/pull/589)
|
23
|
+
* Performance
|
24
|
+
* Misc
|
25
|
+
|
15
26
|
### [3.4.1 / 2014-09-01](https://github.com/mbleigh/acts-as-taggable-on/compare/v3.4.0...v3.4.1)
|
16
27
|
* Fixes
|
17
28
|
* [@konukhov fix owned ordered taggable bug]((https://github.com/mbleigh/acts-as-taggable-on/pull/585)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# ActsAsTaggableOn
|
2
|
+
[](http://badge.fury.io/rb/acts-as-taggable-on)
|
2
3
|
[](http://travis-ci.org/mbleigh/acts-as-taggable-on)
|
3
4
|
[](https://codeclimate.com/github/mbleigh/acts-as-taggable-on)
|
4
5
|
[](http://inch-ci.org/github/mbleigh/acts-as-taggable-on)
|
@@ -31,7 +32,7 @@ For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/is
|
|
31
32
|
To use it, add it to your Gemfile:
|
32
33
|
|
33
34
|
```ruby
|
34
|
-
gem 'acts-as-taggable-on'
|
35
|
+
gem 'acts-as-taggable-on', '~> 3.4'
|
35
36
|
```
|
36
37
|
|
37
38
|
and bundle:
|
data/lib/acts-as-taggable-on.rb
CHANGED
@@ -58,7 +58,8 @@ module ActsAsTaggableOn
|
|
58
58
|
|
59
59
|
class Configuration
|
60
60
|
attr_accessor :delimiter, :force_lowercase, :force_parameterize,
|
61
|
-
:strict_case_match, :remove_unused_tags, :default_parser
|
61
|
+
:strict_case_match, :remove_unused_tags, :default_parser,
|
62
|
+
:tags_counter
|
62
63
|
|
63
64
|
def initialize
|
64
65
|
@delimiter = ','
|
@@ -66,6 +67,7 @@ module ActsAsTaggableOn
|
|
66
67
|
@force_parameterize = false
|
67
68
|
@strict_case_match = false
|
68
69
|
@remove_unused_tags = false
|
70
|
+
@tags_counter = true
|
69
71
|
@default_parser = DefaultParser
|
70
72
|
end
|
71
73
|
|
@@ -32,17 +32,10 @@ module ActsAsTaggableOn
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.named_any(list)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
where(clause)
|
40
|
-
else
|
41
|
-
clause = list.map { |tag|
|
42
|
-
sanitize_sql(['LOWER(name) = LOWER(?)', as_8bit_ascii(unicode_downcase(tag))])
|
43
|
-
}.join(' OR ')
|
44
|
-
where(clause)
|
45
|
-
end
|
35
|
+
clause = list.map { |tag|
|
36
|
+
sanitize_sql_for_named_any(tag).force_encoding('BINARY')
|
37
|
+
}.join(' OR ')
|
38
|
+
where(clause)
|
46
39
|
end
|
47
40
|
|
48
41
|
def self.named_like(name)
|
@@ -135,6 +128,14 @@ module ActsAsTaggableOn
|
|
135
128
|
string.to_s.mb_chars
|
136
129
|
end
|
137
130
|
end
|
131
|
+
|
132
|
+
def sanitize_sql_for_named_any(tag)
|
133
|
+
if ActsAsTaggableOn.strict_case_match
|
134
|
+
sanitize_sql(["name = #{binary}?", as_8bit_ascii(tag)])
|
135
|
+
else
|
136
|
+
sanitize_sql(['LOWER(name) = LOWER(?)', as_8bit_ascii(unicode_downcase(tag))])
|
137
|
+
end
|
138
|
+
end
|
138
139
|
end
|
139
140
|
end
|
140
141
|
end
|
@@ -27,7 +27,7 @@ module ActsAsTaggableOn::Taggable
|
|
27
27
|
dependent: :destroy,
|
28
28
|
class_name: 'ActsAsTaggableOn::Tagging',
|
29
29
|
order: taggings_order,
|
30
|
-
conditions:
|
30
|
+
conditions: {context: tags_type},
|
31
31
|
include: :tag
|
32
32
|
|
33
33
|
has_many_with_taggable_compatibility context_tags, through: context_taggings,
|
@@ -100,6 +100,7 @@ module ActsAsTaggableOn::Taggable
|
|
100
100
|
context = options.delete(:on)
|
101
101
|
owned_by = options.delete(:owned_by)
|
102
102
|
alias_base_name = undecorated_table_name.gsub('.', '_')
|
103
|
+
# FIXME use ActiveRecord's connection quote_column_name
|
103
104
|
quote = ActsAsTaggableOn::Utils.using_postgresql? ? '"' : ''
|
104
105
|
|
105
106
|
if options.delete(:exclude)
|
@@ -117,7 +118,7 @@ module ActsAsTaggableOn::Taggable
|
|
117
118
|
" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)}" +
|
118
119
|
" AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{quote_value(owned_by.id, nil)}" +
|
119
120
|
" AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s, nil)}"
|
120
|
-
|
121
|
+
|
121
122
|
joins << " AND " + sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
|
122
123
|
joins << " AND " + sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
|
123
124
|
end
|
@@ -130,7 +131,7 @@ module ActsAsTaggableOn::Taggable
|
|
130
131
|
ActsAsTaggableOn::Tag.named_any(tag_list)
|
131
132
|
end
|
132
133
|
|
133
|
-
return empty_result
|
134
|
+
return empty_result if tags.length == 0
|
134
135
|
|
135
136
|
# setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
|
136
137
|
# avoid ambiguous column name
|
@@ -140,21 +141,22 @@ module ActsAsTaggableOn::Taggable
|
|
140
141
|
"#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{ActsAsTaggableOn::Utils.sha_prefix(tags.map(&:name).join('_'))}"
|
141
142
|
)
|
142
143
|
|
143
|
-
|
144
|
-
"
|
144
|
+
tagging_cond = "#{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
|
145
|
+
" WHERE #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
|
145
146
|
" AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name, nil)}"
|
146
147
|
|
147
|
-
|
148
|
-
|
148
|
+
tagging_cond << " AND " + sanitize_sql(["#{taggings_alias}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
|
149
|
+
tagging_cond << " AND " + sanitize_sql(["#{taggings_alias}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
|
149
150
|
|
150
|
-
|
151
|
+
tagging_cond << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
|
151
152
|
|
152
153
|
# don't need to sanitize sql, map all ids and join with OR logic
|
153
|
-
|
154
|
+
tag_ids = tags.map { |t| quote_value(t.id, nil) }.join(', ')
|
155
|
+
tagging_cond << " AND #{taggings_alias}.tag_id in (#{tag_ids})"
|
154
156
|
select_clause << " #{table_name}.*" unless context and tag_types.one?
|
155
157
|
|
156
158
|
if owned_by
|
157
|
-
|
159
|
+
tagging_cond << ' AND ' +
|
158
160
|
sanitize_sql([
|
159
161
|
"#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
|
160
162
|
owned_by.id,
|
@@ -162,10 +164,9 @@ module ActsAsTaggableOn::Taggable
|
|
162
164
|
])
|
163
165
|
end
|
164
166
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
select_clause << group
|
167
|
+
conditions << "EXISTS (SELECT 1 FROM #{tagging_cond})"
|
168
|
+
if options.delete(:order_by_matching_tag_count)
|
169
|
+
order_by << "(SELECT count(*) FROM #{tagging_cond}) desc"
|
169
170
|
end
|
170
171
|
else
|
171
172
|
tags = ActsAsTaggableOn::Tag.named_any(tag_list)
|
@@ -224,11 +225,11 @@ module ActsAsTaggableOn::Taggable
|
|
224
225
|
query = self
|
225
226
|
query = self.select(select_clause.join(',')) unless select_clause.empty?
|
226
227
|
query.joins(joins.join(' '))
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
228
|
+
.where(conditions.join(' AND '))
|
229
|
+
.group(group)
|
230
|
+
.having(having)
|
231
|
+
.order(order_by.join(', '))
|
232
|
+
.readonly(false)
|
232
233
|
end
|
233
234
|
|
234
235
|
def is_taggable?
|
@@ -11,7 +11,7 @@ module ActsAsTaggableOn
|
|
11
11
|
:tagger_type,
|
12
12
|
:tagger_id if defined?(ActiveModel::MassAssignmentSecurity)
|
13
13
|
|
14
|
-
belongs_to :tag, class_name: 'ActsAsTaggableOn::Tag'
|
14
|
+
belongs_to :tag, class_name: 'ActsAsTaggableOn::Tag', counter_cache: ActsAsTaggableOn.tags_counter
|
15
15
|
belongs_to :taggable, polymorphic: true
|
16
16
|
belongs_to :tagger, polymorphic: true
|
17
17
|
|
@@ -32,7 +32,11 @@ module ActsAsTaggableOn
|
|
32
32
|
|
33
33
|
def remove_unused_tags
|
34
34
|
if ActsAsTaggableOn.remove_unused_tags
|
35
|
-
|
35
|
+
if ActsAsTaggableOn.tags_counter
|
36
|
+
tag.destroy if tag.reload.taggings_count.zero?
|
37
|
+
else
|
38
|
+
tag.destroy if tag.reload.taggings.count.zero?
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
@@ -133,6 +133,22 @@ describe 'Acts As Taggable On' do
|
|
133
133
|
expect(taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs)).to_not include(taggable1)
|
134
134
|
end
|
135
135
|
|
136
|
+
it 'should ensure joins to multiple taggings maintain their contexts when aliasing' do
|
137
|
+
taggable1 = TaggableModel.create!(name: 'Taggable 1')
|
138
|
+
|
139
|
+
taggable1.offering_list = 'one'
|
140
|
+
taggable1.need_list = 'two'
|
141
|
+
|
142
|
+
taggable1.save
|
143
|
+
|
144
|
+
column = TaggableModel.connection.quote_column_name("context")
|
145
|
+
offer_alias = TaggableModel.connection.quote_table_name("taggings")
|
146
|
+
need_alias = TaggableModel.connection.quote_table_name("need_taggings_taggable_models_join")
|
147
|
+
|
148
|
+
expect(TaggableModel.joins(:offerings, :needs).to_sql).to include "#{offer_alias}.#{column}"
|
149
|
+
expect(TaggableModel.joins(:offerings, :needs).to_sql).to include "#{need_alias}.#{column}"
|
150
|
+
end
|
151
|
+
|
136
152
|
end
|
137
153
|
|
138
154
|
describe 'Tagging Contexts' do
|
@@ -46,6 +46,14 @@ describe ActsAsTaggableOn::Tag do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
describe 'named any' do
|
50
|
+
context 'with some special characters combinations', if: using_mysql? do
|
51
|
+
it 'should not raise an invalid encoding exception' do
|
52
|
+
expect{ActsAsTaggableOn::Tag.named_any(["holä", "hol'ä"])}.not_to raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
49
57
|
describe 'find or create by name' do
|
50
58
|
before(:each) do
|
51
59
|
@tag.name = 'awesome'
|
@@ -250,13 +258,19 @@ describe ActsAsTaggableOn::Tag do
|
|
250
258
|
end
|
251
259
|
end
|
252
260
|
|
253
|
-
it 'should not change
|
261
|
+
it 'should not change encoding' do
|
254
262
|
name = "\u3042"
|
255
263
|
original_encoding = name.encoding
|
256
264
|
record = ActsAsTaggableOn::Tag.find_or_create_with_like_by_name(name)
|
257
265
|
record.reload
|
258
266
|
expect(record.name.encoding).to eq(original_encoding)
|
259
267
|
end
|
268
|
+
|
269
|
+
context 'named any with some special characters combinations', if: using_mysql? do
|
270
|
+
it 'should not raise an invalid encoding exception' do
|
271
|
+
expect{ActsAsTaggableOn::Tag.named_any(["holä", "hol'ä"])}.not_to raise_error
|
272
|
+
end
|
273
|
+
end
|
260
274
|
end
|
261
275
|
|
262
276
|
describe 'name uniqeness validation' do
|
@@ -261,7 +261,7 @@ describe 'Taggable' do
|
|
261
261
|
@taggable.tag_list = 'bob, charlie'
|
262
262
|
@taggable.save
|
263
263
|
|
264
|
-
expect(TaggableModel.
|
264
|
+
expect(TaggableModel.tagged_with(['bob', 'css'], :any => true).to_a).to eq([@taggable])
|
265
265
|
|
266
266
|
bob = TaggableModel.create(:name => 'Bob', :tag_list => 'ruby, rails, css')
|
267
267
|
frank = TaggableModel.create(:name => 'Frank', :tag_list => 'ruby, rails')
|
@@ -459,6 +459,7 @@ describe 'Taggable' do
|
|
459
459
|
|
460
460
|
expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, any: true).to_a.sort_by { |o| o.id }).to eq([bob, frank, steve])
|
461
461
|
expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, exclude: true).to_a).to eq([jim])
|
462
|
+
expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a).to eq([frank, jim])
|
462
463
|
end
|
463
464
|
end
|
464
465
|
|
data/spec/spec_helper.rb
CHANGED
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.4.
|
4
|
+
version: 3.4.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-09-
|
12
|
+
date: 2014-09-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -266,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
266
|
version: '0'
|
267
267
|
requirements: []
|
268
268
|
rubyforge_project:
|
269
|
-
rubygems_version: 2.
|
269
|
+
rubygems_version: 2.2.2
|
270
270
|
signing_key:
|
271
271
|
specification_version: 4
|
272
272
|
summary: Advanced tagging for Rails.
|