acts-as-taggable-on 5.0.0 → 8.1.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 (64) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/spec.yml +95 -0
  3. data/.gitignore +1 -1
  4. data/Appraisals +11 -3
  5. data/CHANGELOG.md +203 -145
  6. data/Gemfile +3 -2
  7. data/README.md +38 -4
  8. data/acts-as-taggable-on.gemspec +2 -6
  9. data/db/migrate/1_acts_as_taggable_on_migration.rb +8 -7
  10. data/db/migrate/2_add_missing_unique_indices.rb +8 -8
  11. data/db/migrate/3_add_taggings_counter_cache_to_tags.rb +3 -3
  12. data/db/migrate/4_add_missing_taggable_index.rb +2 -2
  13. data/db/migrate/5_change_collation_for_tag_names.rb +1 -1
  14. data/db/migrate/6_add_missing_indexes_on_taggings.rb +9 -9
  15. data/db/migrate/7_add_tenant_to_taggings.rb +16 -0
  16. data/gemfiles/activerecord_5.0.gemfile +9 -3
  17. data/gemfiles/activerecord_5.1.gemfile +9 -3
  18. data/gemfiles/activerecord_5.2.gemfile +21 -0
  19. data/gemfiles/activerecord_6.0.gemfile +21 -0
  20. data/gemfiles/{activerecord_4.2.gemfile → activerecord_6.1.gemfile} +10 -2
  21. data/lib/acts-as-taggable-on.rb +6 -2
  22. data/lib/acts_as_taggable_on/tag.rb +16 -19
  23. data/lib/acts_as_taggable_on/taggable.rb +18 -1
  24. data/lib/acts_as_taggable_on/taggable/cache.rb +38 -34
  25. data/lib/acts_as_taggable_on/taggable/collection.rb +9 -7
  26. data/lib/acts_as_taggable_on/taggable/core.rb +39 -22
  27. data/lib/acts_as_taggable_on/taggable/ownership.rb +1 -1
  28. data/lib/acts_as_taggable_on/taggable/related.rb +1 -1
  29. data/lib/acts_as_taggable_on/taggable/tag_list_type.rb +4 -0
  30. data/lib/acts_as_taggable_on/taggable/tagged_with_query/all_tags_query.rb +2 -4
  31. data/lib/acts_as_taggable_on/taggable/tagged_with_query/any_tags_query.rb +2 -7
  32. data/lib/acts_as_taggable_on/taggable/tagged_with_query/exclude_tags_query.rb +1 -1
  33. data/lib/acts_as_taggable_on/taggable/tagged_with_query/query_base.rb +5 -5
  34. data/lib/acts_as_taggable_on/tagger.rb +1 -1
  35. data/lib/acts_as_taggable_on/tagging.rb +6 -2
  36. data/lib/acts_as_taggable_on/utils.rb +4 -4
  37. data/lib/acts_as_taggable_on/version.rb +1 -2
  38. data/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +4 -12
  39. data/spec/acts_as_taggable_on/caching_spec.rb +16 -10
  40. data/spec/acts_as_taggable_on/{taggable/dirty_spec.rb → dirty_spec.rb} +28 -13
  41. data/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +12 -7
  42. data/spec/acts_as_taggable_on/tag_spec.rb +16 -1
  43. data/spec/acts_as_taggable_on/taggable_spec.rb +21 -14
  44. data/spec/acts_as_taggable_on/tagger_spec.rb +2 -2
  45. data/spec/acts_as_taggable_on/tagging_spec.rb +26 -0
  46. data/spec/internal/app/models/altered_inheriting_taggable_model.rb +2 -0
  47. data/spec/internal/app/models/cached_model_with_array.rb +6 -0
  48. data/spec/internal/app/models/columns_override_model.rb +5 -0
  49. data/spec/internal/app/models/company.rb +1 -1
  50. data/spec/internal/app/models/inheriting_taggable_model.rb +2 -0
  51. data/spec/internal/app/models/market.rb +1 -1
  52. data/spec/internal/app/models/non_standard_id_taggable_model.rb +1 -1
  53. data/spec/internal/app/models/student.rb +2 -0
  54. data/spec/internal/app/models/taggable_model.rb +3 -0
  55. data/spec/internal/app/models/user.rb +1 -1
  56. data/spec/internal/config/database.yml.sample +4 -8
  57. data/spec/internal/db/schema.rb +14 -5
  58. data/spec/spec_helper.rb +0 -1
  59. data/spec/support/database.rb +4 -4
  60. metadata +22 -65
  61. data/.travis.yml +0 -29
  62. data/UPGRADING.md +0 -8
  63. data/lib/acts_as_taggable_on/taggable/dirty.rb +0 -36
  64. data/spec/internal/app/models/models.rb +0 -90
@@ -63,7 +63,7 @@ module ActsAsTaggableOn::Taggable::TaggedWithQuery
63
63
  end
64
64
 
65
65
  if options[:on].present?
66
- on_condition = on_condition.and(tagging_arel_table[:context].lteq(options[:on]))
66
+ on_condition = on_condition.and(tagging_arel_table[:context].eq(options[:on]))
67
67
  end
68
68
 
69
69
  on_condition
@@ -29,9 +29,9 @@ module ActsAsTaggableOn::Taggable::TaggedWithQuery
29
29
  matches_attribute = matches_attribute.lower unless ActsAsTaggableOn.strict_case_match
30
30
 
31
31
  if options[:wild].present?
32
- tag_arel_table[:name].matches("%#{escaped_tag(tag)}%", "!")
32
+ matches_attribute.matches("%#{escaped_tag(tag)}%", "!", ActsAsTaggableOn.strict_case_match)
33
33
  else
34
- tag_arel_table[:name].matches(escaped_tag(tag), "!")
34
+ matches_attribute.matches(escaped_tag(tag), "!", ActsAsTaggableOn.strict_case_match)
35
35
  end
36
36
  end
37
37
 
@@ -40,15 +40,15 @@ module ActsAsTaggableOn::Taggable::TaggedWithQuery
40
40
  matches_attribute = matches_attribute.lower unless ActsAsTaggableOn.strict_case_match
41
41
 
42
42
  if options[:wild].present?
43
- matches_attribute.matches_any(tag_list.map{|tag| "%#{escaped_tag(tag)}%"}, "!")
43
+ matches_attribute.matches_any(tag_list.map{|tag| "%#{escaped_tag(tag)}%"}, "!", ActsAsTaggableOn.strict_case_match)
44
44
  else
45
- matches_attribute.matches_any(tag_list.map{|tag| "#{escaped_tag(tag)}"}, "!")
45
+ matches_attribute.matches_any(tag_list.map{|tag| "#{escaped_tag(tag)}"}, "!", ActsAsTaggableOn.strict_case_match)
46
46
  end
47
47
  end
48
48
 
49
49
  def escaped_tag(tag)
50
50
  tag = tag.downcase unless ActsAsTaggableOn.strict_case_match
51
- tag.gsub(/[!%_]/) { |x| '!' + x }
51
+ ActsAsTaggableOn::Utils.escape_like(tag)
52
52
  end
53
53
 
54
54
  def adjust_taggings_alias(taggings_alias)
@@ -18,7 +18,7 @@ module ActsAsTaggableOn
18
18
  owned_taggings_scope = opts.delete(:scope)
19
19
 
20
20
  has_many :owned_taggings, owned_taggings_scope,
21
- opts.merge(
21
+ **opts.merge(
22
22
  as: :tagger,
23
23
  class_name: '::ActsAsTaggableOn::Tagging',
24
24
  dependent: :destroy
@@ -1,10 +1,12 @@
1
1
  module ActsAsTaggableOn
2
2
  class Tagging < ::ActiveRecord::Base #:nodoc:
3
+ self.table_name = ActsAsTaggableOn.taggings_table
4
+
3
5
  DEFAULT_CONTEXT = 'tags'
4
6
  belongs_to :tag, class_name: '::ActsAsTaggableOn::Tag', counter_cache: ActsAsTaggableOn.tags_counter
5
7
  belongs_to :taggable, polymorphic: true
6
8
 
7
- belongs_to :tagger, {polymorphic: true}.tap {|o| o.merge!(optional: true) if ActsAsTaggableOn::Utils.active_record5? }
9
+ belongs_to :tagger, polymorphic: true, optional: true
8
10
 
9
11
  scope :owned_by, ->(owner) { where(tagger: owner) }
10
12
  scope :not_owned, -> { where(tagger_id: nil, tagger_type: nil) }
@@ -12,6 +14,8 @@ module ActsAsTaggableOn
12
14
  scope :by_contexts, ->(contexts) { where(context: (contexts || DEFAULT_CONTEXT)) }
13
15
  scope :by_context, ->(context = DEFAULT_CONTEXT) { by_contexts(context.to_s) }
14
16
 
17
+ scope :by_tenant, ->(tenant) { where(tenant: tenant) }
18
+
15
19
  validates_presence_of :context
16
20
  validates_presence_of :tag_id
17
21
 
@@ -26,7 +30,7 @@ module ActsAsTaggableOn
26
30
  if ActsAsTaggableOn.tags_counter
27
31
  tag.destroy if tag.reload.taggings_count.zero?
28
32
  else
29
- tag.destroy if tag.reload.taggings.count.zero?
33
+ tag.destroy if tag.reload.taggings.none?
30
34
  end
31
35
  end
32
36
  end
@@ -20,14 +20,14 @@ module ActsAsTaggableOn
20
20
  Digest::SHA1.hexdigest(string)[0..6]
21
21
  end
22
22
 
23
- def active_record5?
24
- ::ActiveRecord::VERSION::MAJOR == 5
25
- end
26
-
27
23
  def like_operator
28
24
  using_postgresql? ? 'ILIKE' : 'LIKE'
29
25
  end
30
26
 
27
+ def legacy_activerecord?
28
+ ActiveRecord.version <= Gem::Version.new('5.3.0')
29
+ end
30
+
31
31
  # escape _ and % characters in strings, since these are wildcards in SQL.
32
32
  def escape_like(str)
33
33
  str.gsub(/[!%_]/) { |x| '!' + x }
@@ -1,4 +1,3 @@
1
1
  module ActsAsTaggableOn
2
- VERSION = '5.0.0'
2
+ VERSION = '8.1.0'
3
3
  end
4
-
@@ -73,14 +73,6 @@ describe 'Acts As Taggable On' do
73
73
  end
74
74
  end
75
75
 
76
- describe 'Reloading' do
77
- it 'should save a model instantiated by Model.find' do
78
- taggable = TaggableModel.create!(name: 'Taggable')
79
- found_taggable = TaggableModel.find(taggable.id)
80
- found_taggable.save
81
- end
82
- end
83
-
84
76
  describe 'Matching Contexts' do
85
77
  it 'should find objects with tags of matching contexts' do
86
78
  taggable1 = TaggableModel.create!(name: 'Taggable 1')
@@ -142,7 +134,7 @@ describe 'Acts As Taggable On' do
142
134
  taggable1.save
143
135
 
144
136
  column = TaggableModel.connection.quote_column_name("context")
145
- offer_alias = TaggableModel.connection.quote_table_name("taggings")
137
+ offer_alias = TaggableModel.connection.quote_table_name(ActsAsTaggableOn.taggings_table)
146
138
  need_alias = TaggableModel.connection.quote_table_name("need_taggings_taggable_models_join")
147
139
 
148
140
  expect(TaggableModel.joins(:offerings, :needs).to_sql).to include "#{offer_alias}.#{column}"
@@ -200,7 +192,7 @@ describe 'Acts As Taggable On' do
200
192
  its(:cached_glass_list) { should be_blank }
201
193
 
202
194
  context 'language taggings cache after update' do
203
- before { @taggable.update_attributes(language_list: 'ruby, .net') }
195
+ before { @taggable.update(language_list: 'ruby, .net') }
204
196
  subject { @taggable }
205
197
 
206
198
  its(:language_list) { should == ['ruby', '.net']}
@@ -209,7 +201,7 @@ describe 'Acts As Taggable On' do
209
201
  end
210
202
 
211
203
  context 'status taggings cache after update' do
212
- before { @taggable.update_attributes(status_list: 'happy, married') }
204
+ before { @taggable.update(status_list: 'happy, married') }
213
205
  subject { @taggable }
214
206
 
215
207
  its(:status_list) { should == ['happy', 'married'] }
@@ -222,7 +214,7 @@ describe 'Acts As Taggable On' do
222
214
 
223
215
  context 'glass taggings cache after update' do
224
216
  before do
225
- @taggable.update_attributes(glass_list: 'rectangle, aviator')
217
+ @taggable.update(glass_list: 'rectangle, aviator')
226
218
  end
227
219
 
228
220
  subject { @taggable }
@@ -31,40 +31,40 @@ describe 'Acts As Taggable On' do
31
31
  end
32
32
 
33
33
  it 'should cache tags' do
34
- @taggable.update_attributes(tag_list: 'awesome, epic')
34
+ @taggable.update(tag_list: 'awesome, epic')
35
35
  expect(@taggable.cached_tag_list).to eq('awesome, epic')
36
36
 
37
- @another_taggable.update_attributes(language_list: 'ruby, .net')
37
+ @another_taggable.update(language_list: 'ruby, .net')
38
38
  expect(@another_taggable.cached_language_list).to eq('ruby, .net')
39
39
  end
40
40
 
41
41
  it 'should keep the cache' do
42
- @taggable.update_attributes(tag_list: 'awesome, epic')
42
+ @taggable.update(tag_list: 'awesome, epic')
43
43
  @taggable = CachedModel.find(@taggable.id)
44
44
  @taggable.save!
45
45
  expect(@taggable.cached_tag_list).to eq('awesome, epic')
46
46
  end
47
47
 
48
48
  it 'should update the cache' do
49
- @taggable.update_attributes(tag_list: 'awesome, epic')
50
- @taggable.update_attributes(tag_list: 'awesome')
49
+ @taggable.update(tag_list: 'awesome, epic')
50
+ @taggable.update(tag_list: 'awesome')
51
51
  expect(@taggable.cached_tag_list).to eq('awesome')
52
52
  end
53
53
 
54
54
  it 'should remove the cache' do
55
- @taggable.update_attributes(tag_list: 'awesome, epic')
56
- @taggable.update_attributes(tag_list: '')
55
+ @taggable.update(tag_list: 'awesome, epic')
56
+ @taggable.update(tag_list: '')
57
57
  expect(@taggable.cached_tag_list).to be_blank
58
58
  end
59
59
 
60
60
  it 'should have a tag list' do
61
- @taggable.update_attributes(tag_list: 'awesome, epic')
61
+ @taggable.update(tag_list: 'awesome, epic')
62
62
  @taggable = CachedModel.find(@taggable.id)
63
63
  expect(@taggable.tag_list.sort).to eq(%w(awesome epic).sort)
64
64
  end
65
65
 
66
66
  it 'should keep the tag list' do
67
- @taggable.update_attributes(tag_list: 'awesome, epic')
67
+ @taggable.update(tag_list: 'awesome, epic')
68
68
  @taggable = CachedModel.find(@taggable.id)
69
69
  @taggable.save!
70
70
  expect(@taggable.tag_list.sort).to eq(%w(awesome epic).sort)
@@ -75,6 +75,12 @@ describe 'Acts As Taggable On' do
75
75
  CachedModel.reset_column_information
76
76
  expect(CachedModel.instance_variable_get(:@acts_as_taggable_on_cache_columns)).to eql(nil)
77
77
  end
78
+
79
+ it 'should not override a user-defined columns method' do
80
+ expect(ColumnsOverrideModel.columns.map(&:name)).not_to include('ignored_column')
81
+ ColumnsOverrideModel.acts_as_taggable
82
+ expect(ColumnsOverrideModel.columns.map(&:name)).not_to include('ignored_column')
83
+ end
78
84
  end
79
85
 
80
86
  describe 'with a custom delimiter' do
@@ -89,7 +95,7 @@ describe 'Acts As Taggable On' do
89
95
  end
90
96
 
91
97
  it 'should cache tags with custom delimiter' do
92
- @taggable.update_attributes(tag_list: 'awesome; epic')
98
+ @taggable.update(tag_list: 'awesome; epic')
93
99
  expect(@taggable.tag_list).to eq(['awesome', 'epic'])
94
100
  expect(@taggable.cached_tag_list).to eq('awesome; epic')
95
101
 
@@ -1,7 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require 'spec_helper'
3
3
 
4
- describe ActsAsTaggableOn::Taggable::Dirty do
4
+ describe 'Dirty behavior of taggable objects' do
5
5
  context 'with un-contexted tags' do
6
6
  before(:each) do
7
7
  @taggable = TaggableModel.create(tag_list: 'awesome, epic')
@@ -14,19 +14,27 @@ describe ActsAsTaggableOn::Taggable::Dirty do
14
14
  end
15
15
 
16
16
  it 'should show changes of dirty object' do
17
- expect(@taggable.changes).to eq({'tag_list' => ['awesome, epic', ['one']]})
17
+ expect(@taggable.changes).to eq({'tag_list' => [['awesome', 'epic'], ['one']]})
18
18
  end
19
19
 
20
- it 'flags tag_list as changed' do
21
- expect(@taggable.tag_list_changed?).to be_truthy
20
+ it 'should show changes of freshly initialized dirty object' do
21
+ taggable = TaggableModel.find(@taggable.id)
22
+ taggable.tag_list = 'one'
23
+ expect(taggable.changes).to eq({'tag_list' => [['awesome', 'epic'], ['one']]})
24
+ end
25
+
26
+ if Rails.version >= "5.1"
27
+ it 'flags tag_list as changed' do
28
+ expect(@taggable.will_save_change_to_tag_list?).to be_truthy
29
+ end
22
30
  end
23
31
 
24
32
  it 'preserves original value' do
25
- expect(@taggable.tag_list_was).to eq('awesome, epic')
33
+ expect(@taggable.tag_list_was).to eq(['awesome', 'epic'])
26
34
  end
27
35
 
28
36
  it 'shows what the change was' do
29
- expect(@taggable.tag_list_change).to eq(['awesome, epic', ['one']])
37
+ expect(@taggable.tag_list_change).to eq([['awesome', 'epic'], ['one']])
30
38
  end
31
39
 
32
40
  context 'without order' do
@@ -90,7 +98,7 @@ describe ActsAsTaggableOn::Taggable::Dirty do
90
98
  end
91
99
 
92
100
  it 'should show changes of dirty object' do
93
- expect(@taggable.changes).to eq({'language_list' => ['awesome, epic', ['one']]})
101
+ expect(@taggable.changes).to eq({'language_list' => [['awesome', 'epic'], ['one']]})
94
102
  end
95
103
 
96
104
  it 'flags language_list as changed' do
@@ -98,15 +106,11 @@ describe ActsAsTaggableOn::Taggable::Dirty do
98
106
  end
99
107
 
100
108
  it 'preserves original value' do
101
- expect(@taggable.language_list_was).to eq('awesome, epic')
109
+ expect(@taggable.language_list_was).to eq(['awesome', 'epic'])
102
110
  end
103
111
 
104
112
  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']])
113
+ expect(@taggable.language_list_change).to eq([['awesome', 'epic'], ['one']])
110
114
  end
111
115
  end
112
116
 
@@ -123,5 +127,16 @@ describe ActsAsTaggableOn::Taggable::Dirty do
123
127
  expect(@taggable.changes).to be_empty
124
128
  end
125
129
  end
130
+
131
+ context 'when language_list changed by association' do
132
+ let(:tag) { ActsAsTaggableOn::Tag.new(name: 'one') }
133
+
134
+ it 'flags language_list as changed' do
135
+ expect(@taggable.changes).to be_empty
136
+ @taggable.languages << tag
137
+ expect(@taggable.language_list_changed?).to be_truthy
138
+ end
139
+ end
140
+
126
141
  end
127
142
  end
@@ -127,9 +127,9 @@ describe 'Single Table Inheritance' do
127
127
  altered_inheriting.tag_list = 'fork, spoon'
128
128
  altered_inheriting.save!
129
129
 
130
- expect(InheritingTaggableModel.tag_counts_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(bob kelso))
131
- expect(AlteredInheritingTaggableModel.tag_counts_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(fork spoon))
132
- expect(TaggableModel.tag_counts_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(bob kelso fork spoon))
130
+ expect(InheritingTaggableModel.tag_counts_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(bob kelso))
131
+ expect(AlteredInheritingTaggableModel.tag_counts_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(fork spoon))
132
+ expect(TaggableModel.tag_counts_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(bob kelso fork spoon))
133
133
  end
134
134
 
135
135
  it 'should have different tags_on for inherited models' do
@@ -138,9 +138,9 @@ describe 'Single Table Inheritance' do
138
138
  altered_inheriting.tag_list = 'fork, spoon'
139
139
  altered_inheriting.save!
140
140
 
141
- expect(InheritingTaggableModel.tags_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(bob kelso))
142
- expect(AlteredInheritingTaggableModel.tags_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(fork spoon))
143
- expect(TaggableModel.tags_on(:tags, order: 'tags.id').map(&:name)).to eq(%w(bob kelso fork spoon))
141
+ expect(InheritingTaggableModel.tags_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(bob kelso))
142
+ expect(AlteredInheritingTaggableModel.tags_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(fork spoon))
143
+ expect(TaggableModel.tags_on(:tags, order: "#{ActsAsTaggableOn.tags_table}.id").map(&:name)).to eq(%w(bob kelso fork spoon))
144
144
  end
145
145
 
146
146
  it 'should store same tag without validation conflict' do
@@ -150,7 +150,12 @@ describe 'Single Table Inheritance' do
150
150
  inheriting_model.tag_list = 'one'
151
151
  inheriting_model.save!
152
152
 
153
- inheriting_model.update_attributes! name: 'foo'
153
+ inheriting_model.update! name: 'foo'
154
+ end
155
+
156
+ it "should only join with taggable's table to check type for inherited models" do
157
+ expect(TaggableModel.tag_counts_on(:tags).to_sql).to_not match /INNER JOIN taggable_models ON/
158
+ expect(InheritingTaggableModel.tag_counts_on(:tags).to_sql).to match /INNER JOIN taggable_models ON/
154
159
  end
155
160
  end
156
161
 
@@ -14,7 +14,7 @@ end
14
14
  describe ActsAsTaggableOn::Tag do
15
15
  before(:each) do
16
16
  @tag = ActsAsTaggableOn::Tag.new
17
- @user = TaggableModel.create(name: 'Pablo')
17
+ @user = TaggableModel.create(name: 'Pablo', tenant_id: 100)
18
18
  end
19
19
 
20
20
 
@@ -70,6 +70,21 @@ describe ActsAsTaggableOn::Tag do
70
70
  end
71
71
  end
72
72
 
73
+ describe 'for tenant' do
74
+ before(:each) do
75
+ @user.skill_list.add('ruby')
76
+ @user.save
77
+ end
78
+
79
+ it 'should return tags for the tenant' do
80
+ expect(ActsAsTaggableOn::Tag.for_tenant('100').pluck(:name)).to include('ruby')
81
+ end
82
+
83
+ it 'should not return tags for other tenants' do
84
+ expect(ActsAsTaggableOn::Tag.for_tenant('200').pluck(:name)).to_not include('ruby')
85
+ end
86
+ end
87
+
73
88
  describe 'find or create by name' do
74
89
  before(:each) do
75
90
  @tag.name = 'awesome'
@@ -109,6 +109,10 @@ describe 'Taggable' do
109
109
  expect(@taggable.tag_types).to eq(TaggableModel.tag_types)
110
110
  end
111
111
 
112
+ it 'should have tenant column' do
113
+ expect(TaggableModel.tenant_column).to eq(:tenant_id)
114
+ end
115
+
112
116
  it 'should have tag_counts_on' do
113
117
  expect(TaggableModel.tag_counts_on(:tags)).to be_empty
114
118
 
@@ -200,8 +204,8 @@ describe 'Taggable' do
200
204
  @taggables[1].skill_list = 'css'
201
205
  @taggables.each { |taggable| taggable.save }
202
206
 
203
- @found_taggables_by_tag = TaggableModel.joins(:tags).where(tags: {name: ['bob']})
204
- @found_taggables_by_skill = TaggableModel.joins(:skills).where(tags: {name: ['ruby']})
207
+ @found_taggables_by_tag = TaggableModel.joins(:tags).where(ActsAsTaggableOn.tags_table => {name: ['bob']})
208
+ @found_taggables_by_skill = TaggableModel.joins(:skills).where(ActsAsTaggableOn.tags_table => {name: ['ruby']})
205
209
 
206
210
  expect(@found_taggables_by_tag).to include @taggables[0]
207
211
  expect(@found_taggables_by_tag).to_not include @taggables[1]
@@ -255,14 +259,17 @@ describe 'Taggable' do
255
259
  end
256
260
 
257
261
  it 'should be able to find by tag with context' do
258
- @taggable.skill_list = 'ruby, rails, css'
259
- @taggable.tag_list = 'bob, charlie'
262
+ @taggable.skill_list = 'ruby, rails, css, julia'
263
+ @taggable.tag_list = 'bob, charlie, julia'
260
264
  @taggable.save
261
265
 
262
266
  expect(TaggableModel.tagged_with('ruby').first).to eq(@taggable)
263
267
  expect(TaggableModel.tagged_with('ruby, css').first).to eq(@taggable)
264
268
  expect(TaggableModel.tagged_with('bob', on: :skills).first).to_not eq(@taggable)
265
269
  expect(TaggableModel.tagged_with('bob', on: :tags).first).to eq(@taggable)
270
+ expect(TaggableModel.tagged_with('julia', on: :skills).size).to eq(1)
271
+ expect(TaggableModel.tagged_with('julia', on: :tags).size).to eq(1)
272
+ expect(TaggableModel.tagged_with('julia', on: nil).size).to eq(2)
266
273
  end
267
274
 
268
275
  it 'should not care about case' do
@@ -335,7 +342,7 @@ describe 'Taggable' do
335
342
  TaggableModel.create(name: 'Charlie', skill_list: 'ruby')
336
343
 
337
344
  expect(TaggableModel.all_tag_counts).to_not be_empty
338
- expect(TaggableModel.all_tag_counts(order: 'tags.id').first.count).to eq(3) # ruby
345
+ expect(TaggableModel.all_tag_counts(order: "#{ActsAsTaggableOn.tags_table}.id").first.count).to eq(3) # ruby
339
346
  end
340
347
 
341
348
  it 'should be able to get all tags on model as whole' do
@@ -344,7 +351,7 @@ describe 'Taggable' do
344
351
  TaggableModel.create(name: 'Charlie', skill_list: 'ruby')
345
352
 
346
353
  expect(TaggableModel.all_tags).to_not be_empty
347
- expect(TaggableModel.all_tags(order: 'tags.id').first.name).to eq('ruby')
354
+ expect(TaggableModel.all_tags(order: "#{ActsAsTaggableOn.tags_table}.id").first.name).to eq('ruby')
348
355
  end
349
356
 
350
357
  it 'should be able to use named scopes to chain tag finds by any tags by context' do
@@ -366,7 +373,7 @@ describe 'Taggable' do
366
373
  TaggableModel.create(name: 'Frank', tag_list: 'ruby, rails')
367
374
  TaggableModel.create(name: 'Charlie', skill_list: 'ruby')
368
375
 
369
- expect(TaggableModel.tagged_with('ruby').tag_counts(order: 'tags.id').first.count).to eq(2) # ruby
376
+ expect(TaggableModel.tagged_with('ruby').tag_counts(order: "#{ActsAsTaggableOn.tags_table}.id").first.count).to eq(2) # ruby
370
377
  expect(TaggableModel.tagged_with('ruby').skill_counts.first.count).to eq(1) # ruby
371
378
  end
372
379
 
@@ -375,7 +382,7 @@ describe 'Taggable' do
375
382
  TaggableModel.create(name: 'Frank', tag_list: 'ruby, rails')
376
383
  TaggableModel.create(name: 'Charlie', skill_list: 'ruby')
377
384
 
378
- expect(TaggableModel.tagged_with('ruby').all_tag_counts(order: 'tags.id').first.count).to eq(3) # ruby
385
+ expect(TaggableModel.tagged_with('ruby').all_tag_counts(order: "#{ActsAsTaggableOn.tags_table}.id").first.count).to eq(3) # ruby
379
386
  end
380
387
 
381
388
  it 'should be able to get all scoped tags' do
@@ -383,7 +390,7 @@ describe 'Taggable' do
383
390
  TaggableModel.create(name: 'Frank', tag_list: 'ruby, rails')
384
391
  TaggableModel.create(name: 'Charlie', skill_list: 'ruby')
385
392
 
386
- expect(TaggableModel.tagged_with('ruby').all_tags(order: 'tags.id').first.name).to eq('ruby')
393
+ expect(TaggableModel.tagged_with('ruby').all_tags(order: "#{ActsAsTaggableOn.tags_table}.id").first.name).to eq('ruby')
387
394
  end
388
395
 
389
396
  it 'should only return tag counts for the available scope' do
@@ -474,7 +481,7 @@ describe 'Taggable' do
474
481
 
475
482
  expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, any: true).to_a.sort_by { |o| o.id }).to eq([bob, frank, steve])
476
483
  expect(TaggableModel.tagged_with(%w(bob tricia), wild: true, exclude: true).to_a).to eq([jim])
477
- expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a =~ [frank, jim])
484
+ expect(TaggableModel.tagged_with('ji', wild: true, any: true).to_a).to match_array([frank, jim])
478
485
  end
479
486
  end
480
487
 
@@ -538,7 +545,7 @@ describe 'Taggable' do
538
545
 
539
546
  it 'should not delete tags if not updated' do
540
547
  model = TaggableModel.create(name: 'foo', tag_list: 'ruby, rails, programming')
541
- model.update_attributes(name: 'bar')
548
+ model.update(name: 'bar')
542
549
  model.reload
543
550
  expect(model.tag_list.sort).to eq(%w(ruby rails programming).sort)
544
551
  end
@@ -669,15 +676,15 @@ describe 'Taggable' do
669
676
  # NOTE: type column supports an STI Tag subclass in the test suite, though
670
677
  # isn't included by default in the migration generator
671
678
  expect(@taggable.grouped_column_names_for(ActsAsTaggableOn::Tag))
672
- .to eq('tags.id, tags.name, tags.taggings_count, tags.type')
679
+ .to eq("#{ActsAsTaggableOn.tags_table}.id, #{ActsAsTaggableOn.tags_table}.name, #{ActsAsTaggableOn.tags_table}.taggings_count, #{ActsAsTaggableOn.tags_table}.type")
673
680
  end
674
681
 
675
682
  it 'should return all column names joined for TaggableModel GROUP clause' do
676
- expect(@taggable.grouped_column_names_for(TaggableModel)).to eq('taggable_models.id, taggable_models.name, taggable_models.type')
683
+ expect(@taggable.grouped_column_names_for(TaggableModel)).to eq('taggable_models.id, taggable_models.name, taggable_models.type, taggable_models.tenant_id')
677
684
  end
678
685
 
679
686
  it 'should return all column names joined for NonStandardIdTaggableModel GROUP clause' do
680
- expect(@taggable.grouped_column_names_for(TaggableModel)).to eq("taggable_models.#{TaggableModel.primary_key}, taggable_models.name, taggable_models.type")
687
+ expect(@taggable.grouped_column_names_for(TaggableModel)).to eq("taggable_models.#{TaggableModel.primary_key}, taggable_models.name, taggable_models.type, taggable_models.tenant_id")
681
688
  end
682
689
  end
683
690