gutentag 0.9.0 → 1.0.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +21 -0
  4. data/.travis.yml +6 -5
  5. data/Appraisals +20 -26
  6. data/Gemfile +13 -8
  7. data/README.md +5 -1
  8. data/Rakefile +9 -5
  9. data/app/models/gutentag/tag.rb +7 -4
  10. data/app/models/gutentag/tagging.rb +5 -3
  11. data/bin/literals +9 -0
  12. data/db/migrate/1_gutentag_tables.rb +5 -3
  13. data/db/migrate/2_gutentag_cache_counter.rb +2 -0
  14. data/db/migrate/3_no_null_counters.rb +8 -4
  15. data/gutentag.gemspec +18 -18
  16. data/lib/gutentag.rb +13 -13
  17. data/lib/gutentag/active_record.rb +11 -6
  18. data/lib/gutentag/active_record/class_methods.rb +4 -16
  19. data/lib/gutentag/active_record/instance_methods.rb +3 -1
  20. data/lib/gutentag/change_state.rb +32 -0
  21. data/lib/gutentag/dirty.rb +4 -1
  22. data/lib/gutentag/engine.rb +2 -4
  23. data/lib/gutentag/persistence.rb +13 -16
  24. data/lib/gutentag/tag_validations.rb +4 -1
  25. data/lib/gutentag/tagged_with.rb +5 -3
  26. data/lib/gutentag/tagged_with/id_query.rb +2 -0
  27. data/lib/gutentag/tagged_with/name_query.rb +2 -0
  28. data/lib/gutentag/tagged_with/query.rb +2 -0
  29. data/spec/acceptance/tag_names_spec.rb +40 -38
  30. data/spec/acceptance/tags_spec.rb +8 -6
  31. data/spec/gutentag/active_record_spec.rb +69 -112
  32. data/spec/gutentag_spec.rb +5 -3
  33. data/spec/internal/app/models/article.rb +2 -0
  34. data/spec/internal/db/schema.rb +2 -0
  35. data/spec/models/gutentag/tag_spec.rb +24 -22
  36. data/spec/models/gutentag/tagging_spec.rb +5 -3
  37. data/spec/spec_helper.rb +4 -2
  38. metadata +11 -43
  39. data/gemfiles/rails_3_2.gemfile +0 -11
  40. data/gemfiles/rails_4_0.gemfile +0 -11
  41. data/gemfiles/rails_4_1.gemfile +0 -11
  42. data/gemfiles/rails_4_2.gemfile +0 -10
  43. data/gemfiles/rails_5_0.gemfile +0 -8
  44. data/gemfiles/rails_5_1.gemfile +0 -8
  45. data/lib/gutentag/has_many_tags.rb +0 -10
@@ -1,10 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::Dirty
2
4
  def self.call(instance, tag_names)
3
5
  new(instance, tag_names).call
4
6
  end
5
7
 
6
8
  def initialize(instance, tag_names)
7
- @instance, @tag_names = instance, tag_names
9
+ @instance = instance
10
+ @tag_names = tag_names
8
11
  end
9
12
 
10
13
  def call
@@ -1,7 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::Engine < Rails::Engine
2
4
  engine_name :gutentag
3
-
4
- ActiveSupport.on_load :active_record do
5
- extend Gutentag::HasManyTags
6
- end
7
5
  end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
1
5
  class Gutentag::Persistence
6
+ extend Forwardable
2
7
 
3
- attr_writer :tagger, :normaliser
8
+ attr_writer :tagger
4
9
 
5
- def initialize(taggable)
6
- @taggable = taggable
7
- @existing = normalised taggable.tags.collect(&:name)
8
- @changes = normalised taggable.tag_names
10
+ def initialize(change_state)
11
+ @change_state = change_state
9
12
  end
10
13
 
11
14
  def persist
@@ -17,20 +20,18 @@ class Gutentag::Persistence
17
20
 
18
21
  private
19
22
 
20
- attr_reader :taggable, :existing, :changes
23
+ attr_reader :change_state
24
+
25
+ def_delegators :change_state, :taggable, :added, :removed
21
26
 
22
27
  def add_new
23
- (changes - existing).each do |name|
28
+ added.each do |name|
24
29
  taggable.tags << tagger.find_or_create(name)
25
30
  end
26
31
  end
27
32
 
28
- def normalised(names)
29
- names.collect { |name| normaliser.call(name) }.uniq
30
- end
31
-
32
33
  def remove_old
33
- (existing - changes).each do |name|
34
+ removed.each do |name|
34
35
  taggable.tags.delete tagger.find_by_name(name)
35
36
  end
36
37
  end
@@ -38,8 +39,4 @@ class Gutentag::Persistence
38
39
  def tagger
39
40
  @tagger ||= Gutentag::Tag
40
41
  end
41
-
42
- def normaliser
43
- @normaliser ||= Proc.new { |name| Gutentag.normaliser.call(name) }
44
- end
45
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::TagValidations
2
4
  def self.call(klass)
3
5
  new(klass).call
@@ -8,7 +10,8 @@ class Gutentag::TagValidations
8
10
  end
9
11
 
10
12
  def call
11
- klass.validates :name, :presence => true,
13
+ klass.validates :name,
14
+ :presence => true,
12
15
  :uniqueness => {:case_sensitive => false}
13
16
  end
14
17
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::TaggedWith
2
4
  def self.call(model, options)
3
5
  new(model, options).call
@@ -33,6 +35,6 @@ class Gutentag::TaggedWith
33
35
  end
34
36
  end
35
37
 
36
- require 'gutentag/tagged_with/query'
37
- require 'gutentag/tagged_with/id_query'
38
- require 'gutentag/tagged_with/name_query'
38
+ require "gutentag/tagged_with/query"
39
+ require "gutentag/tagged_with/id_query"
40
+ require "gutentag/tagged_with/name_query"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::TaggedWith::IDQuery < Gutentag::TaggedWith::Query
2
4
  private
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::TaggedWith::NameQuery < Gutentag::TaggedWith::Query
2
4
  def initialize(model, values, match)
3
5
  super
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::TaggedWith::Query
2
4
  def initialize(model, values, match)
3
5
  @model = model
@@ -1,38 +1,40 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe "Managing tags via names" do
4
6
  let(:article) { Article.create }
5
7
 
6
8
  it "returns tag names" do
7
- melbourne = Gutentag::Tag.create :name => 'melbourne'
9
+ melbourne = Gutentag::Tag.create :name => "melbourne"
8
10
 
9
11
  article.tags << melbourne
10
12
 
11
- expect(article.tag_names).to eq(['melbourne'])
13
+ expect(article.tag_names).to eq(["melbourne"])
12
14
  end
13
15
 
14
16
  it "adds tags via their names" do
15
- article.tag_names << 'melbourne'
17
+ article.tag_names << "melbourne"
16
18
  article.save!
17
19
 
18
- expect(article.tags.collect(&:name)).to eq(['melbourne'])
20
+ expect(article.tags.collect(&:name)).to eq(["melbourne"])
19
21
  end
20
22
 
21
23
  it "makes model dirty when changing through tag_names" do
22
- article.tag_names << 'melbourne'
24
+ article.tag_names << "melbourne"
23
25
  article.save!
24
26
 
25
- article.tag_names = ['sydney']
27
+ article.tag_names = ["sydney"]
26
28
 
27
29
  expect(article.changed_attributes.stringify_keys).
28
- to eq('tag_names' => ['melbourne'])
30
+ to eq("tag_names" => ["melbourne"])
29
31
  end if Gutentag.dirtier
30
32
 
31
33
  it "does not make model dirty when changing through tag_names" do
32
- article.tag_names << 'melbourne'
34
+ article.tag_names << "melbourne"
33
35
  article.save!
34
36
 
35
- article.tag_names = ['melbourne']
37
+ article.tag_names = ["melbourne"]
36
38
 
37
39
  expect(article.changed_attributes).to eq({})
38
40
  end
@@ -40,87 +42,87 @@ describe "Managing tags via names" do
40
42
  it "allows for different tag normalisation" do
41
43
  Gutentag.normaliser = lambda { |name| name.upcase }
42
44
 
43
- tag = Gutentag::Tag.create(:name => 'melbourne')
44
- expect(tag.name).to eq('MELBOURNE')
45
+ tag = Gutentag::Tag.create(:name => "melbourne")
46
+ expect(tag.name).to eq("MELBOURNE")
45
47
 
46
48
  Gutentag.normaliser = nil
47
49
  end
48
50
 
49
51
  it "doesn't complain when adding an existing tag" do
50
- article.tag_names << 'melbourne'
51
- article.tag_names << 'melbourne'
52
+ article.tag_names << "melbourne"
53
+ article.tag_names << "melbourne"
52
54
  article.save!
53
55
 
54
- expect(article.tags.collect(&:name)).to eq(['melbourne'])
56
+ expect(article.tags.collect(&:name)).to eq(["melbourne"])
55
57
  end
56
58
 
57
59
  it "accepts a completely new set of tags" do
58
- article.tag_names = ['portland', 'oregon']
60
+ article.tag_names = %w[ portland oregon ]
59
61
  article.save!
60
62
 
61
- expect(article.tags.collect(&:name)).to eq(['portland', 'oregon'])
63
+ expect(article.tags.collect(&:name)).to eq(%w[ portland oregon ])
62
64
  end
63
65
 
64
66
  it "does not allow duplication of tags" do
65
67
  existing = Article.create
66
- existing.tags << Gutentag::Tag.create(:name => 'portland')
68
+ existing.tags << Gutentag::Tag.create(:name => "portland")
67
69
 
68
- article.tag_names = ['portland']
70
+ article.tag_names = %w[ portland ]
69
71
  article.save!
70
72
 
71
73
  expect(existing.tag_ids).to eq(article.tag_ids)
72
74
  end
73
75
 
74
76
  it "appends tag names" do
75
- article.tag_names = ['portland']
76
- article.tag_names += ['oregon', 'ruby']
77
+ article.tag_names = %w[ portland ]
78
+ article.tag_names += %w[ oregon ruby ]
77
79
  article.save!
78
80
 
79
- expect(article.tags.collect(&:name)).to eq(['portland', 'oregon', 'ruby'])
81
+ expect(article.tags.collect(&:name)).to eq(%w[ portland oregon ruby ])
80
82
  end
81
83
 
82
84
  it "does not repeat appended names that already exist" do
83
- article.tag_names = ['portland', 'oregon']
84
- article.tag_names += ['oregon', 'ruby']
85
+ article.tag_names = %w[ portland oregon ]
86
+ article.tag_names += %w[ oregon ruby ]
85
87
  article.save!
86
88
 
87
- expect(article.tags.collect(&:name)).to eq(['portland', 'oregon', 'ruby'])
89
+ expect(article.tags.collect(&:name)).to eq(%w[ portland oregon ruby ])
88
90
  end
89
91
 
90
92
  it "removes a single tag name" do
91
- article.tag_names = ['portland', 'oregon']
92
- article.tag_names.delete 'oregon'
93
+ article.tag_names = %w[ portland oregon ]
94
+ article.tag_names.delete "oregon"
93
95
  article.save!
94
96
 
95
- expect(article.tags.collect(&:name)).to eq(['portland'])
97
+ expect(article.tags.collect(&:name)).to eq(%w[ portland ])
96
98
  end
97
99
 
98
100
  it "removes tag names" do
99
- article.tag_names = ['portland', 'oregon', 'ruby']
100
- article.tag_names -= ['oregon', 'ruby']
101
+ article.tag_names = %w[ portland oregon ruby ]
102
+ article.tag_names -= %w[ oregon ruby ]
101
103
  article.save!
102
104
 
103
- expect(article.tags.collect(&:name)).to eq(['portland'])
105
+ expect(article.tags.collect(&:name)).to eq(%w[ portland ])
104
106
  end
105
107
 
106
108
  it "matches tag names ignoring case" do
107
- article.tag_names = ['portland']
108
- article.tag_names += ['Portland']
109
+ article.tag_names = %w[ portland ]
110
+ article.tag_names += %w[ Portland ]
109
111
  article.save!
110
112
 
111
- expect(article.tags.collect(&:name)).to eq(['portland'])
113
+ expect(article.tags.collect(&:name)).to eq(%w[ portland ])
112
114
 
113
- article.tag_names << 'Portland'
115
+ article.tag_names << "Portland"
114
116
  article.save!
115
117
 
116
- expect(article.tags.collect(&:name)).to eq(['portland'])
118
+ expect(article.tags.collect(&:name)).to eq(%w[ portland ])
117
119
  end
118
120
 
119
121
  it "allows setting of tag names on unpersisted objects" do
120
- article = Article.new :tag_names => ['melbourne', 'pancakes']
122
+ article = Article.new :tag_names => %w[ melbourne pancakes ]
121
123
  article.save!
122
124
 
123
- expect(article.tag_names).to eq(['melbourne', 'pancakes'])
125
+ expect(article.tag_names).to eq(%w[ melbourne pancakes ])
124
126
  end
125
127
 
126
128
  it "allows overriding of tag_names=" do
@@ -1,8 +1,10 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'Adding and removing tags' do
3
+ require "spec_helper"
4
+
5
+ describe "Adding and removing tags" do
4
6
  let(:article) { Article.create }
5
- let(:pancakes) { Gutentag::Tag.create :name => 'pancakes' }
7
+ let(:pancakes) { Gutentag::Tag.create :name => "pancakes" }
6
8
 
7
9
  it "stores new tags" do
8
10
  article.tags << pancakes
@@ -24,7 +26,7 @@ describe 'Adding and removing tags' do
24
26
  article.destroy
25
27
 
26
28
  expect(Gutentag::Tagging.where(
27
- :taggable_type => 'Article', :taggable_id => article.id
29
+ :taggable_type => "Article", :taggable_id => article.id
28
30
  ).count).to be_zero
29
31
  end
30
32
 
@@ -36,8 +38,8 @@ describe 'Adding and removing tags' do
36
38
  expect(Gutentag::Tagging.where(:tag_id => pancakes.id).count).to be_zero
37
39
  end
38
40
 
39
- it 'should have a mean tag cloud' do
40
- gorillas = Gutentag::Tag.create(:name => 'gorillas')
41
+ it "should have a mean tag cloud" do
42
+ gorillas = Gutentag::Tag.create(:name => "gorillas")
41
43
  another_article = Article.create
42
44
 
43
45
  article.tags << pancakes
@@ -1,37 +1,39 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe Gutentag::ActiveRecord do
4
- describe '.tagged_with' do
6
+ describe ".tagged_with" do
5
7
  let!(:melbourne_article) do
6
- article = Article.create :title => 'Overview'
7
- article.tag_names << 'melbourne'
8
+ article = Article.create :title => "Overview"
9
+ article.tag_names << "melbourne"
8
10
  article.save!
9
11
  article
10
12
  end
11
13
 
12
14
  let!(:oregon_article) do
13
15
  article = Article.create
14
- article.tag_names << 'oregon'
16
+ article.tag_names << "oregon"
15
17
  article.save!
16
18
  article
17
19
  end
18
20
 
19
21
  let!(:melbourne_oregon_article) do
20
22
  article = Article.create
21
- article.tag_names = %w(oregon melbourne)
23
+ article.tag_names = %w[ oregon melbourne ]
22
24
  article.save!
23
25
  article
24
26
  end
25
27
 
26
- context 'given a single tag name' do
27
- subject { Article.tagged_with(:names => 'melbourne') }
28
+ context "given a single tag name" do
29
+ subject { Article.tagged_with(:names => "melbourne") }
28
30
 
29
31
  it { expect(subject.count).to eq 2 }
30
32
  it { is_expected.to include melbourne_article, melbourne_oregon_article }
31
33
  it { is_expected.not_to include oregon_article }
32
34
  end
33
35
 
34
- context 'given a single tag name[symbol]' do
36
+ context "given a single tag name[symbol]" do
35
37
  subject { Article.tagged_with(:names => :melbourne) }
36
38
 
37
39
  it { expect(subject.count).to eq 2 }
@@ -39,7 +41,7 @@ describe Gutentag::ActiveRecord do
39
41
  it { is_expected.not_to include oregon_article }
40
42
  end
41
43
 
42
- context 'given a denormalized tag name' do
44
+ context "given a denormalized tag name" do
43
45
  subject { Article.tagged_with(:names => "MelbournE") }
44
46
 
45
47
  it { expect(subject.count).to eq 2 }
@@ -47,160 +49,115 @@ describe Gutentag::ActiveRecord do
47
49
  it { is_expected.not_to include oregon_article }
48
50
  end
49
51
 
50
- context 'given multiple tag names' do
51
- subject { Article.tagged_with(:names => ['melbourne', 'oregon']) }
52
+ context "given multiple tag names" do
53
+ subject { Article.tagged_with(:names => %w[ melbourne oregon ]) }
52
54
 
53
55
  it { expect(subject.count).to eq 3 }
54
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
56
+ it do
57
+ is_expected.to include(
58
+ melbourne_article, oregon_article, melbourne_oregon_article
59
+ )
60
+ end
55
61
  end
56
62
 
57
- context 'given an array of tag names' do
58
- subject { Article.tagged_with(:names => %w(melbourne oregon)) }
63
+ context "given an array of tag names" do
64
+ subject { Article.tagged_with(:names => %w[ melbourne oregon ]) }
59
65
 
60
66
  it { expect(subject.count).to eq 3 }
61
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
67
+ it do
68
+ is_expected.to include(
69
+ melbourne_article, oregon_article, melbourne_oregon_article
70
+ )
71
+ end
62
72
  end
63
73
 
64
- context 'given a single tag instance' do
65
- subject { Article.tagged_with(:tags => Gutentag::Tag.find_by_name!('melbourne')) }
74
+ context "given a single tag instance" do
75
+ subject do
76
+ Article.tagged_with(:tags => Gutentag::Tag.find_by_name!("melbourne"))
77
+ end
66
78
 
67
79
  it { expect(subject.count).to eq 2 }
68
80
  it { is_expected.to include melbourne_article, melbourne_oregon_article }
69
81
  it { is_expected.not_to include oregon_article }
70
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
82
+ it { expect(subject.to_sql).not_to include "gutentag_tags" }
71
83
  end
72
84
 
73
- context 'given a single tag id' do
74
- subject { Article.tagged_with(:ids => Gutentag::Tag.find_by_name!('melbourne').id) }
85
+ context "given a single tag id" do
86
+ subject do
87
+ Article.tagged_with(:ids => Gutentag::Tag.find_by_name!("melbourne").id)
88
+ end
75
89
 
76
90
  it { expect(subject.count).to eq 2 }
77
91
  it { is_expected.to include melbourne_article, melbourne_oregon_article }
78
92
  it { is_expected.not_to include oregon_article }
79
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
93
+ it { expect(subject.to_sql).not_to include "gutentag_tags" }
80
94
  end
81
95
 
82
- context 'given multiple tag objects' do
83
- subject { Article.tagged_with(:tags => Gutentag::Tag.where(name: %w(melbourne oregon))) }
96
+ context "given multiple tag objects" do
97
+ subject do
98
+ Article.tagged_with(
99
+ :tags => Gutentag::Tag.where(:name => %w[ melbourne oregon ])
100
+ )
101
+ end
84
102
 
85
103
  it { expect(subject.count).to eq 3 }
86
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
87
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
104
+ it do
105
+ is_expected.to include(
106
+ melbourne_article, oregon_article, melbourne_oregon_article
107
+ )
108
+ end
109
+ it { expect(subject.to_sql).not_to include "gutentag_tags" }
88
110
  end
89
111
 
90
- context 'chaining where clause' do
91
- subject { Article.tagged_with(:names => %w(melbourne oregon)).where(title: 'Overview') }
112
+ context "chaining where clause" do
113
+ subject do
114
+ Article.tagged_with(:names => %w[ melbourne oregon ]).
115
+ where(:title => "Overview")
116
+ end
92
117
 
93
118
  it { expect(subject.count).to eq 1 }
94
119
  it { is_expected.to include melbourne_article }
95
120
  it { is_expected.not_to include oregon_article, melbourne_oregon_article }
96
121
  end
97
122
 
98
- context 'appended onto a relation' do
99
- subject { Article.where(title: 'Overview').tagged_with(:names => %w(melbourne oregon)) }
123
+ context "appended onto a relation" do
124
+ subject do
125
+ Article.where(:title => "Overview").
126
+ tagged_with(:names => %w[ melbourne oregon ])
127
+ end
100
128
 
101
129
  it { expect(subject.count).to eq 1 }
102
130
  it { is_expected.to include melbourne_article }
103
131
  it { is_expected.not_to include oregon_article, melbourne_oregon_article }
104
132
  end
105
133
 
106
- context 'matching against all tags' do
107
- subject { Article.tagged_with(:names => %w(melbourne oregon), :match => :all) }
134
+ context "matching against all tags" do
135
+ subject do
136
+ Article.tagged_with(:names => %w[ melbourne oregon ], :match => :all)
137
+ end
108
138
 
109
139
  it { expect(subject.count).to eq 1 }
110
140
  it { is_expected.to include melbourne_oregon_article }
111
141
  it { is_expected.not_to include oregon_article, melbourne_article }
112
142
  end
113
143
 
114
- context 'matching against all tag ids' do
115
- subject { Article.tagged_with(:ids => Gutentag::Tag.where(:name => %w(melbourne oregon)).pluck(:id), :match => :all) }
144
+ context "matching against all tag ids" do
145
+ let(:tag_ids) do
146
+ Gutentag::Tag.where(:name => %w[ melbourne oregon ]).pluck(:id)
147
+ end
148
+ subject { Article.tagged_with(:ids => tag_ids, :match => :all) }
116
149
 
117
150
  it { expect(subject.count).to eq 1 }
118
151
  it { is_expected.to include melbourne_oregon_article }
119
152
  it { is_expected.not_to include oregon_article, melbourne_article }
120
153
  end
121
154
 
122
- context 'matching against all one tag is the same as any' do
123
- subject { Article.tagged_with(:names => %w(melbourne), :match => :all) }
155
+ context "matching against all one tag is the same as any" do
156
+ subject { Article.tagged_with(:names => %w[ melbourne ], :match => :all) }
124
157
 
125
158
  it { expect(subject.count).to eq 2 }
126
159
  it { is_expected.to include melbourne_article, melbourne_oregon_article }
127
160
  it { is_expected.not_to include oregon_article }
128
161
  end
129
-
130
- context "deprecated" do
131
- before { expect(ActiveSupport::Deprecation).to receive(:warn) }
132
-
133
- context 'given a single tag name' do
134
- subject { Article.tagged_with('melbourne') }
135
-
136
- it { expect(subject.count).to eq 2 }
137
- it { is_expected.to include melbourne_article, melbourne_oregon_article }
138
- it { is_expected.not_to include oregon_article }
139
- end
140
-
141
- context 'given a single tag name[symbol]' do
142
- subject { Article.tagged_with(:melbourne) }
143
-
144
- it { expect(subject.count).to eq 2 }
145
- it { is_expected.to include melbourne_article, melbourne_oregon_article }
146
- it { is_expected.not_to include oregon_article }
147
- end
148
-
149
- context 'given a denormalized tag name' do
150
- subject { Article.tagged_with("MelbournE") }
151
-
152
- it { expect(subject.count).to eq 2 }
153
- it { is_expected.to include melbourne_article, melbourne_oregon_article }
154
- it { is_expected.not_to include oregon_article }
155
- end
156
-
157
- context 'given multiple tag names' do
158
- subject { Article.tagged_with('melbourne', 'oregon') }
159
-
160
- it { expect(subject.count).to eq 3 }
161
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
162
- end
163
-
164
- context 'given an array of tag names' do
165
- subject { Article.tagged_with(%w(melbourne oregon)) }
166
-
167
- it { expect(subject.count).to eq 3 }
168
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
169
- end
170
-
171
- context 'given a single tag instance' do
172
- subject { Article.tagged_with(Gutentag::Tag.find_by_name!('melbourne')) }
173
-
174
- it { expect(subject.count).to eq 2 }
175
- it { is_expected.to include melbourne_article, melbourne_oregon_article }
176
- it { is_expected.not_to include oregon_article }
177
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
178
- end
179
-
180
- context 'given a single tag id' do
181
- subject { Article.tagged_with(Gutentag::Tag.find_by_name!('melbourne').id) }
182
-
183
- it { expect(subject.count).to eq 2 }
184
- it { is_expected.to include melbourne_article, melbourne_oregon_article }
185
- it { is_expected.not_to include oregon_article }
186
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
187
- end
188
-
189
- context 'given multiple tag objects' do
190
- subject { Article.tagged_with(Gutentag::Tag.where(name: %w(melbourne oregon))) }
191
-
192
- it { expect(subject.count).to eq 3 }
193
- it { is_expected.to include melbourne_article, oregon_article, melbourne_oregon_article }
194
- it { expect(subject.to_sql).not_to include 'gutentag_tags' }
195
- end
196
-
197
- context 'chaining where clause' do
198
- subject { Article.tagged_with(%w(melbourne oregon)).where(title: 'Overview') }
199
-
200
- it { expect(subject.count).to eq 1 }
201
- it { is_expected.to include melbourne_article }
202
- it { is_expected.not_to include oregon_article, melbourne_oregon_article }
203
- end
204
- end
205
162
  end
206
163
  end