acts-as-taggable-on 3.2.3 → 3.3.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -7
  3. data/Appraisals +0 -4
  4. data/Gemfile +0 -1
  5. data/README.md +1 -1
  6. data/acts-as-taggable-on.gemspec +6 -8
  7. data/db/migrate/4_add_missing_taggable_index.rb +9 -0
  8. data/gemfiles/activerecord_3.2.gemfile +0 -2
  9. data/gemfiles/activerecord_4.0.gemfile +0 -2
  10. data/gemfiles/activerecord_4.1.gemfile +0 -2
  11. data/gemfiles/activerecord_edge.gemfile +0 -2
  12. data/lib/acts-as-taggable-on.rb +28 -20
  13. data/lib/acts_as_taggable_on/tag_list.rb +13 -77
  14. data/lib/acts_as_taggable_on/tag_list_parser.rb +78 -0
  15. data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/core.rb +46 -23
  16. data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/ownership.rb +1 -1
  17. data/lib/acts_as_taggable_on/taggable.rb +7 -6
  18. data/lib/acts_as_taggable_on/tagging.rb +1 -1
  19. data/lib/acts_as_taggable_on/tags_helper.rb +2 -2
  20. data/lib/acts_as_taggable_on/utils.rb +2 -26
  21. data/lib/acts_as_taggable_on/version.rb +1 -1
  22. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +1 -1
  23. data/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +1 -0
  24. data/spec/acts_as_taggable_on/caching_spec.rb +1 -0
  25. data/spec/acts_as_taggable_on/related_spec.rb +1 -0
  26. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +1 -0
  27. data/spec/acts_as_taggable_on/tag_list_parser_spec.rb +46 -0
  28. data/spec/acts_as_taggable_on/tag_list_spec.rb +3 -40
  29. data/spec/acts_as_taggable_on/tag_spec.rb +29 -35
  30. data/spec/acts_as_taggable_on/taggable/dirty_spec.rb +127 -0
  31. data/spec/acts_as_taggable_on/taggable_spec.rb +76 -163
  32. data/spec/acts_as_taggable_on/tagger_spec.rb +1 -1
  33. data/spec/acts_as_taggable_on/tagging_spec.rb +13 -1
  34. data/spec/acts_as_taggable_on/tags_helper_spec.rb +1 -0
  35. data/spec/acts_as_taggable_on/utils_spec.rb +1 -0
  36. data/spec/internal/app/models/cached_model_with_array.rb +1 -1
  37. data/spec/internal/app/models/models.rb +2 -2
  38. data/spec/internal/db/schema.rb +2 -2
  39. data/spec/spec_helper.rb +0 -1
  40. data/spec/support/0-helpers.rb +32 -0
  41. metadata +39 -67
  42. data/spec/schema.rb +0 -82
  43. /data/lib/acts_as_taggable_on/{acts_as_taggable_on/compatibility.rb → compatibility.rb} +0 -0
  44. /data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/cache.rb +0 -0
  45. /data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/collection.rb +0 -0
  46. /data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/dirty.rb +0 -0
  47. /data/lib/acts_as_taggable_on/{acts_as_taggable_on → taggable}/related.rb +0 -0
@@ -4,10 +4,10 @@ module ActsAsTaggableOn
4
4
  def tag_cloud(tags, classes)
5
5
  return [] if tags.empty?
6
6
 
7
- max_count = tags.sort_by(&:count).last.count.to_f
7
+ max_count = tags.sort_by(&:taggings_count).last.taggings_count.to_f
8
8
 
9
9
  tags.each do |tag|
10
- index = ((tag.count / max_count) * (classes.size - 1))
10
+ index = ((tag.taggings_count / max_count) * (classes.size - 1))
11
11
  yield tag, classes[index.nan? ? 0 : index.round]
12
12
  end
13
13
  end
@@ -1,3 +1,5 @@
1
+ # This module is deprecated and will be removed in the incoming versions
2
+
1
3
  module ActsAsTaggableOn
2
4
  module Utils
3
5
  class << self
@@ -10,33 +12,11 @@ module ActsAsTaggableOn
10
12
  connection && connection.adapter_name == 'PostgreSQL'
11
13
  end
12
14
 
13
- def postgresql_version
14
- if using_postgresql?
15
- connection.execute('SHOW SERVER_VERSION').first['server_version'].to_f
16
- end
17
- end
18
-
19
- def postgresql_support_json?
20
- postgresql_version >= 9.2
21
- end
22
-
23
- def using_sqlite?
24
- connection && connection.adapter_name == 'SQLite'
25
- end
26
-
27
15
  def using_mysql?
28
16
  #We should probably use regex for mysql to support prehistoric adapters
29
17
  connection && connection.adapter_name == 'Mysql2'
30
18
  end
31
19
 
32
- def using_case_insensitive_collation?
33
- using_mysql? && connection.collation =~ /_ci\Z/
34
- end
35
-
36
- def supports_concurrency?
37
- !using_sqlite?
38
- end
39
-
40
20
  def sha_prefix(string)
41
21
  Digest::SHA1.hexdigest("#{string}#{rand}")[0..6]
42
22
  end
@@ -45,10 +25,6 @@ module ActsAsTaggableOn
45
25
  ::ActiveRecord::VERSION::MAJOR == 4
46
26
  end
47
27
 
48
- def active_record42?
49
- active_record4? && ::ActiveRecord::VERSION::MINOR >= 2
50
- end
51
-
52
28
  def like_operator
53
29
  using_postgresql? ? 'ILIKE' : 'LIKE'
54
30
  end
@@ -1,4 +1,4 @@
1
1
  module ActsAsTaggableOn
2
- VERSION = '3.2.3'
2
+ VERSION = '3.3.0'
3
3
  end
4
4
 
@@ -1,4 +1,4 @@
1
- # coding: utf-8
1
+ # -*- encoding : utf-8 -*-
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'Acts As Taggable On' do
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe 'acts_as_tagger' do
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe 'Acts As Taggable On' do
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe 'Acts As Taggable On' do
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe 'Single Table Inheritance' do
@@ -0,0 +1,46 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe ActsAsTaggableOn::TagListParser do
5
+ it '#parse should return empty array if empty array is passed' do
6
+ expect(ActsAsTaggableOn::TagListParser.parse([])).to be_empty
7
+ end
8
+
9
+ describe 'Multiple Delimiter' do
10
+ before do
11
+ @old_delimiter = ActsAsTaggableOn.delimiter
12
+ end
13
+
14
+ after do
15
+ ActsAsTaggableOn.delimiter = @old_delimiter
16
+ end
17
+
18
+ it 'should separate tags by delimiters' do
19
+ ActsAsTaggableOn.delimiter = [',', ' ', '\|']
20
+ tag_list = ActsAsTaggableOn::TagListParser.parse('cool, data|I have')
21
+ expect(tag_list.to_s).to eq('cool, data, I, have')
22
+ end
23
+
24
+ it 'should escape quote' do
25
+ ActsAsTaggableOn.delimiter = [',', ' ', '\|']
26
+ tag_list = ActsAsTaggableOn::TagListParser.parse "'I have'|cool, data"
27
+ expect(tag_list.to_s).to eq('"I have", cool, data')
28
+
29
+ tag_list = ActsAsTaggableOn::TagListParser.parse '"I, have"|cool, data'
30
+ expect(tag_list.to_s).to eq('"I, have", cool, data')
31
+ end
32
+
33
+ it 'should work for utf8 delimiter and long delimiter' do
34
+ ActsAsTaggableOn.delimiter = [',', '的', '可能是']
35
+ tag_list = ActsAsTaggableOn::TagListParser.parse('我的东西可能是不见了,还好有备份')
36
+ expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
37
+ end
38
+
39
+ it 'should work for multiple quoted tags' do
40
+ ActsAsTaggableOn.delimiter = [',']
41
+ tag_list = ActsAsTaggableOn::TagListParser.parse('"Ruby Monsters","eat Katzenzungen"')
42
+ expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
43
+ end
44
+ end
45
+
46
+ end
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # -*- encoding : utf-8 -*-
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe ActsAsTaggableOn::TagList do
@@ -7,9 +8,7 @@ describe ActsAsTaggableOn::TagList do
7
8
 
8
9
  it { should be_kind_of Array }
9
10
 
10
- it '#from should return empty array if empty array is passed' do
11
- expect(ActsAsTaggableOn::TagList.from([])).to be_empty
12
- end
11
+
13
12
 
14
13
  describe '#add' do
15
14
  it 'should be able to be add a new tag word' do
@@ -118,41 +117,5 @@ describe ActsAsTaggableOn::TagList do
118
117
 
119
118
  end
120
119
 
121
- describe 'Multiple Delimiter' do
122
- before do
123
- @old_delimiter = ActsAsTaggableOn.delimiter
124
- end
125
-
126
- after do
127
- ActsAsTaggableOn.delimiter = @old_delimiter
128
- end
129
-
130
- it 'should separate tags by delimiters' do
131
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
132
- tag_list = ActsAsTaggableOn::TagList.from 'cool, data|I have'
133
- expect(tag_list.to_s).to eq('cool, data, I, have')
134
- end
135
-
136
- it 'should escape quote' do
137
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
138
- tag_list = ActsAsTaggableOn::TagList.from "'I have'|cool, data"
139
- expect(tag_list.to_s).to eq('"I have", cool, data')
140
-
141
- tag_list = ActsAsTaggableOn::TagList.from '"I, have"|cool, data'
142
- expect(tag_list.to_s).to eq('"I, have", cool, data')
143
- end
144
-
145
- it 'should work for utf8 delimiter and long delimiter' do
146
- ActsAsTaggableOn.delimiter = [',', '的', '可能是']
147
- tag_list = ActsAsTaggableOn::TagList.from '我的东西可能是不见了,还好有备份'
148
- expect(tag_list.to_s).to eq('我, 东西, 不见了, 还好有备份')
149
- end
150
-
151
- it 'should work for multiple quoted tags' do
152
- ActsAsTaggableOn.delimiter = [',']
153
- tag_list = ActsAsTaggableOn::TagList.from '"Ruby Monsters","eat Katzenzungen"'
154
- expect(tag_list.to_s).to eq('Ruby Monsters, eat Katzenzungen')
155
- end
156
- end
157
120
 
158
121
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # -*- encoding : utf-8 -*-
2
2
  require 'spec_helper'
3
3
  require 'db/migrate/2_add_missing_unique_indices.rb'
4
4
 
@@ -18,21 +18,19 @@ describe ActsAsTaggableOn::Tag do
18
18
 
19
19
 
20
20
  describe 'named like any' do
21
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
22
- context 'case insensitive collation and unique index on tag name' do
23
- before(:each) do
24
- ActsAsTaggableOn::Tag.create(name: 'Awesome')
25
- ActsAsTaggableOn::Tag.create(name: 'epic')
26
- end
27
-
28
- it 'should find both tags' do
29
- expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(2)
30
- end
21
+ context 'case insensitive collation and unique index on tag name', if: using_case_insensitive_collation? do
22
+ before(:each) do
23
+ ActsAsTaggableOn::Tag.create(name: 'Awesome')
24
+ ActsAsTaggableOn::Tag.create(name: 'epic')
25
+ end
26
+
27
+ it 'should find both tags' do
28
+ expect(ActsAsTaggableOn::Tag.named_like_any(%w(awesome epic)).count).to eq(2)
31
29
  end
32
30
  end
33
31
 
34
32
  context 'case insensitive collation without indexes or case sensitive collation with indexes' do
35
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
33
+ if using_case_insensitive_collation?
36
34
  include_context 'without unique index'
37
35
  end
38
36
 
@@ -69,28 +67,24 @@ describe ActsAsTaggableOn::Tag do
69
67
  end
70
68
  end
71
69
 
72
- unless ActsAsTaggableOn::Utils.using_sqlite?
73
- describe 'find or create by unicode name' do
74
- before(:each) do
75
- @tag.name = 'привет'
76
- @tag.save
77
- end
70
+ describe 'find or create by unicode name', unless: using_sqlite? do
71
+ before(:each) do
72
+ @tag.name = 'привет'
73
+ @tag.save
74
+ end
78
75
 
79
- it 'should find by name' do
80
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('привет')).to eq(@tag)
81
- end
76
+ it 'should find by name' do
77
+ expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('привет')).to eq(@tag)
78
+ end
82
79
 
83
- it 'should find by name case insensitive' do
84
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('ПРИВЕТ')).to eq(@tag)
85
- end
80
+ it 'should find by name case insensitive' do
81
+ expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('ПРИВЕТ')).to eq(@tag)
82
+ end
86
83
 
87
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
88
- it 'should find by name accent insensitive' do
89
- @tag.name = 'inupiat'
90
- @tag.save
91
- expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('Iñupiat')).to eq(@tag)
92
- end
93
- end
84
+ it 'should find by name accent insensitive', if: using_case_insensitive_collation? do
85
+ @tag.name = 'inupiat'
86
+ @tag.save
87
+ expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('Iñupiat')).to eq(@tag)
94
88
  end
95
89
  end
96
90
 
@@ -109,7 +103,7 @@ describe ActsAsTaggableOn::Tag do
109
103
  end
110
104
 
111
105
  context 'case sensitive' do
112
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
106
+ if using_case_insensitive_collation?
113
107
  include_context 'without unique index'
114
108
  end
115
109
 
@@ -128,7 +122,7 @@ describe ActsAsTaggableOn::Tag do
128
122
  end
129
123
 
130
124
  context 'case sensitive' do
131
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
125
+ if using_case_insensitive_collation?
132
126
  include_context 'without unique index'
133
127
  end
134
128
 
@@ -228,7 +222,7 @@ describe ActsAsTaggableOn::Tag do
228
222
  end
229
223
 
230
224
  context 'case sensitive' do
231
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
225
+ if using_case_insensitive_collation?
232
226
  include_context 'without unique index'
233
227
  end
234
228
 
@@ -242,7 +236,7 @@ describe ActsAsTaggableOn::Tag do
242
236
  end
243
237
 
244
238
  context 'case sensitive' do
245
- if ActsAsTaggableOn::Utils.using_case_insensitive_collation?
239
+ if using_case_insensitive_collation?
246
240
  include_context 'without unique index'
247
241
  end
248
242
 
@@ -0,0 +1,127 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe ActsAsTaggableOn::Taggable::Dirty do
5
+ context 'with un-contexted tags' do
6
+ before(:each) do
7
+ @taggable = TaggableModel.create(tag_list: 'awesome, epic')
8
+ end
9
+
10
+ context 'when tag_list changed' do
11
+ before(:each) do
12
+ expect(@taggable.changes).to be_empty
13
+ @taggable.tag_list = 'one'
14
+ end
15
+
16
+ it 'should show changes of dirty object' do
17
+ expect(@taggable.changes).to eq({'tag_list' => ['awesome, epic', ['one']]})
18
+ end
19
+
20
+ it 'flags tag_list as changed' do
21
+ expect(@taggable.tag_list_changed?).to be_truthy
22
+ end
23
+
24
+ it 'preserves original value' do
25
+ expect(@taggable.tag_list_was).to eq('awesome, epic')
26
+ end
27
+
28
+ it 'shows what the change was' do
29
+ expect(@taggable.tag_list_change).to eq(['awesome, epic', ['one']])
30
+ end
31
+
32
+ context 'without order' do
33
+ it 'should not mark attribute if order change ' do
34
+ taggable = TaggableModel.create(name: 'Dirty Harry', tag_list: %w(d c b a))
35
+ taggable.tag_list = %w(a b c d)
36
+ expect(taggable.tag_list_changed?).to be_falsey
37
+ end
38
+ end
39
+
40
+ context 'with order' do
41
+ it 'should mark attribute if order change' do
42
+ taggable = OrderedTaggableModel.create(name: 'Clean Harry', tag_list: 'd,c,b,a')
43
+ taggable.save
44
+ taggable.tag_list = %w(a b c d)
45
+ expect(taggable.tag_list_changed?).to be_truthy
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'when tag_list is the same' do
51
+ before(:each) do
52
+ @taggable.tag_list = 'awesome, epic'
53
+ end
54
+
55
+ it 'is not flagged as changed' do
56
+ expect(@taggable.tag_list_changed?).to be_falsy
57
+ end
58
+
59
+ it 'does not show any changes to the taggable item' do
60
+ expect(@taggable.changes).to be_empty
61
+ end
62
+
63
+ context "and using a delimiter different from a ','" do
64
+ before do
65
+ @old_delimiter = ActsAsTaggableOn.delimiter
66
+ ActsAsTaggableOn.delimiter = ';'
67
+ end
68
+
69
+ after do
70
+ ActsAsTaggableOn.delimiter = @old_delimiter
71
+ end
72
+
73
+ it 'does not show any changes to the taggable item when using array assignments' do
74
+ @taggable.tag_list = %w(awesome epic)
75
+ expect(@taggable.changes).to be_empty
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'with context tags' do
82
+ before(:each) do
83
+ @taggable = TaggableModel.create('language_list' => 'awesome, epic')
84
+ end
85
+
86
+ context 'when language_list changed' do
87
+ before(:each) do
88
+ expect(@taggable.changes).to be_empty
89
+ @taggable.language_list = 'one'
90
+ end
91
+
92
+ it 'should show changes of dirty object' do
93
+ expect(@taggable.changes).to eq({'language_list' => ['awesome, epic', ['one']]})
94
+ end
95
+
96
+ it 'flags language_list as changed' do
97
+ expect(@taggable.language_list_changed?).to be_truthy
98
+ end
99
+
100
+ it 'preserves original value' do
101
+ expect(@taggable.language_list_was).to eq('awesome, epic')
102
+ end
103
+
104
+ it 'shows what the change was' do
105
+ expect(@taggable.language_list_change).to eq(['awesome, epic', ['one']])
106
+ end
107
+
108
+ it 'shows what the changes were' do
109
+ expect(@taggable.language_list_changes).to eq(['awesome, epic', ['one']])
110
+ end
111
+ end
112
+
113
+ context 'when language_list is the same' do
114
+ before(:each) do
115
+ @taggable.language_list = 'awesome, epic'
116
+ end
117
+
118
+ it 'is not flagged as changed' do
119
+ expect(@taggable.language_list_changed?).to be_falsy
120
+ end
121
+
122
+ it 'does not show any changes to the taggable item' do
123
+ expect(@taggable.changes).to be_empty
124
+ end
125
+ end
126
+ end
127
+ end