gutentag 2.1.0 → 2.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +1 -1
- data/app/models/gutentag/tag.rb +2 -6
- data/gutentag.gemspec +7 -6
- data/lib/gutentag.rb +1 -5
- data/lib/gutentag/active_record.rb +50 -3
- data/lib/gutentag/active_record/class_methods.rb +16 -0
- data/lib/gutentag/active_record/{instance_methods.rb → legacy_instance_methods.rb} +2 -1
- data/lib/gutentag/active_record/modern_instance_methods.rb +26 -0
- data/lib/gutentag/dirty.rb +4 -1
- data/lib/gutentag/persistence.rb +0 -2
- data/spec/acceptance/dirty_state_spec.rb +52 -0
- data/spec/acceptance/tag_names_spec.rb +1 -20
- data/spec/spec_helper.rb +13 -2
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6935bb3c51e7b225573d2330a1f95b858bed7cd130f0825177aef98c9f0d175
|
4
|
+
data.tar.gz: 52201a047a523da00bd33cee60fe72ac1901c1273eb8296b4cfa637349991cf2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75251e4214a914b48256c60a97241f0db275fd06441e4eb3def15a8ada9fdebf6150208237b81d6715d63c87eae15d2bbcca208c61cc767961f451be60c8737f
|
7
|
+
data.tar.gz: 2b8f4b94045a63adfae0bb8e762922f788e49d3b0f37e44d5f54f8a2cd5fb0390f453a532106cc6b4da38b4f9c5cd8bf51211f2ba64713b0fb649a35b5b71e5d
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project (at least, from v0.5.0 onwards) will be documented in this file.
|
4
4
|
|
5
|
+
## 2.2.0 - 2018-03-04
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
* Dirty state support for `tag_names` is now available for Rails 4.2 onwards, and is more reliable for Rails 3.2-4.1 (supporting all known methods, such as `tag_names_changed?`, `previous_changes`, etc.)
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
* Switch normalising of tag names from a callback within `Gutentag::Tag` to `#name=` ([Tomasz Ras](https://github.com/RasMachineMan) in [#47](https://github.com/pat/gutentag/pull/47)).
|
14
|
+
|
5
15
|
## 2.1.0 - 2018-02-01
|
6
16
|
|
7
17
|
### Added
|
data/README.md
CHANGED
@@ -80,7 +80,7 @@ These are the versions the test suite runs against. It's possible it may work on
|
|
80
80
|
Get it into your Gemfile - and don't forget the version constraint!
|
81
81
|
|
82
82
|
```Ruby
|
83
|
-
gem 'gutentag', '~> 2.
|
83
|
+
gem 'gutentag', '~> 2.2.0'
|
84
84
|
```
|
85
85
|
|
86
86
|
Next: your tags get persisted to your database, so let's import and run the migrations to get the tables set up:
|
data/app/models/gutentag/tag.rb
CHANGED
@@ -11,8 +11,6 @@ class Gutentag::Tag < ActiveRecord::Base
|
|
11
11
|
|
12
12
|
scope :by_weight, lambda { order("gutentag_tags.taggings_count DESC") }
|
13
13
|
|
14
|
-
before_validation :normalise_name
|
15
|
-
|
16
14
|
def self.find_by_name(name)
|
17
15
|
where(:name => Gutentag.normaliser.call(name)).first
|
18
16
|
end
|
@@ -21,9 +19,7 @@ class Gutentag::Tag < ActiveRecord::Base
|
|
21
19
|
find_by_name(name) || create(:name => name)
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
def normalise_name
|
27
|
-
self.name = Gutentag.normaliser.call name
|
22
|
+
def name=(value)
|
23
|
+
super(Gutentag.normaliser.call(value))
|
28
24
|
end
|
29
25
|
end
|
data/gutentag.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "gutentag"
|
6
|
-
s.version = "2.
|
6
|
+
s.version = "2.2.0"
|
7
7
|
s.authors = ["Pat Allan"]
|
8
8
|
s.email = ["pat@freelancing-gods.com"]
|
9
9
|
s.homepage = "https://github.com/pat/gutentag"
|
@@ -17,10 +17,11 @@ Gem::Specification.new do |s|
|
|
17
17
|
|
18
18
|
s.add_runtime_dependency "activerecord", ">= 3.2.0"
|
19
19
|
|
20
|
-
s.add_development_dependency "appraisal",
|
21
|
-
s.add_development_dependency "bundler",
|
22
|
-
s.add_development_dependency "combustion",
|
20
|
+
s.add_development_dependency "appraisal", "~> 2.1.0"
|
21
|
+
s.add_development_dependency "bundler", ">= 1.7.12"
|
22
|
+
s.add_development_dependency "combustion", "0.8.0"
|
23
|
+
s.add_development_dependency "database_cleaner", "~> 1.6"
|
23
24
|
s.add_development_dependency "rails"
|
24
|
-
s.add_development_dependency "rspec-rails",
|
25
|
-
s.add_development_dependency "rubocop",
|
25
|
+
s.add_development_dependency "rspec-rails", "~> 3.1"
|
26
|
+
s.add_development_dependency "rubocop", "~> 0.52.1"
|
26
27
|
end
|
data/lib/gutentag.rb
CHANGED
@@ -36,11 +36,7 @@ require "gutentag/remove_unused"
|
|
36
36
|
require "gutentag/tag_validations"
|
37
37
|
require "gutentag/tagged_with"
|
38
38
|
|
39
|
-
if ActiveRecord::VERSION::
|
40
|
-
Gutentag.dirtier = Gutentag::Dirty
|
41
|
-
elsif ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR < 2
|
42
|
-
Gutentag.dirtier = Gutentag::Dirty
|
43
|
-
end
|
39
|
+
Gutentag.dirtier = Gutentag::Dirty if ActiveRecord::VERSION::STRING.to_f < 4.2
|
44
40
|
|
45
41
|
require "active_support/lazy_load_hooks"
|
46
42
|
ActiveSupport.on_load(:gutentag) do
|
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
class Gutentag::ActiveRecord
|
4
4
|
def self.call(model)
|
5
|
+
new(model).call
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(model)
|
9
|
+
@model = model
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
add_associations
|
14
|
+
add_callbacks
|
15
|
+
add_methods
|
16
|
+
add_attribute
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :model
|
22
|
+
|
23
|
+
def add_associations
|
5
24
|
model.has_many :taggings,
|
6
25
|
:class_name => "Gutentag::Tagging",
|
7
26
|
:as => :taggable,
|
@@ -9,13 +28,41 @@ class Gutentag::ActiveRecord
|
|
9
28
|
model.has_many :tags,
|
10
29
|
:class_name => "Gutentag::Tag",
|
11
30
|
:through => :taggings
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_attribute
|
34
|
+
if legacy?
|
35
|
+
model.define_attribute_method "tag_names"
|
36
|
+
else
|
37
|
+
model.attribute "tag_names", ActiveRecord::Type::Value.new, :default => []
|
38
|
+
end
|
39
|
+
end
|
12
40
|
|
41
|
+
def add_callbacks
|
13
42
|
model.after_save :persist_tags
|
14
43
|
|
15
|
-
|
16
|
-
|
44
|
+
if legacy?
|
45
|
+
model.after_save :reset_tag_names
|
46
|
+
else
|
47
|
+
model.after_commit :reset_tag_names, :on => %i[ create update ]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_methods
|
52
|
+
model.send :extend, Gutentag::ActiveRecord::ClassMethods
|
53
|
+
|
54
|
+
if legacy?
|
55
|
+
model.send :include, Gutentag::ActiveRecord::LegacyInstanceMethods
|
56
|
+
else
|
57
|
+
model.send :include, Gutentag::ActiveRecord::ModernInstanceMethods
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def legacy?
|
62
|
+
ActiveRecord::VERSION::STRING.to_f < 4.2
|
17
63
|
end
|
18
64
|
end
|
19
65
|
|
20
66
|
require "gutentag/active_record/class_methods"
|
21
|
-
require "gutentag/active_record/
|
67
|
+
require "gutentag/active_record/legacy_instance_methods"
|
68
|
+
require "gutentag/active_record/modern_instance_methods"
|
@@ -4,4 +4,20 @@ module Gutentag::ActiveRecord::ClassMethods
|
|
4
4
|
def tagged_with(options)
|
5
5
|
Gutentag::TaggedWith.call self, options
|
6
6
|
end
|
7
|
+
|
8
|
+
if ActiveRecord::VERSION::STRING.to_f < 4.2
|
9
|
+
def skip_time_zone_conversion_for_attributes
|
10
|
+
super + [:tag_names]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if ActiveRecord::VERSION::STRING.to_f < 4.0
|
15
|
+
def create_time_zone_conversion_attribute?(attr_name, column)
|
16
|
+
attr_name != "tag_names" && super
|
17
|
+
end
|
18
|
+
|
19
|
+
def attribute_cast_code(attr_name)
|
20
|
+
attr_name == "tag_names" ? "v" : super
|
21
|
+
end
|
22
|
+
end
|
7
23
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# For Rails 4.2+
|
4
|
+
module Gutentag::ActiveRecord::ModernInstanceMethods
|
5
|
+
def reset_tag_names
|
6
|
+
self.tag_names = nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def tag_names
|
10
|
+
self.tag_names = tags.pluck(:name) if super.nil?
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def tag_names=(names)
|
16
|
+
Gutentag.dirtier.call self, names if Gutentag.dirtier
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def persist_tags
|
24
|
+
Gutentag::Persistence.new(Gutentag::ChangeState.new(self)).persist
|
25
|
+
end
|
26
|
+
end
|
data/lib/gutentag/dirty.rb
CHANGED
@@ -11,7 +11,10 @@ class Gutentag::Dirty
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def call
|
14
|
-
|
14
|
+
return unless changes.present?
|
15
|
+
|
16
|
+
instance.tag_names_will_change!
|
17
|
+
instance.changed_attributes[:tag_names] = existing
|
15
18
|
end
|
16
19
|
|
17
20
|
private
|
data/lib/gutentag/persistence.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe "Dirty state of tag names" do
|
6
|
+
let(:article) { Article.create! }
|
7
|
+
|
8
|
+
it "knows what tag names will change" do
|
9
|
+
article.tag_names = ["pancakes"]
|
10
|
+
|
11
|
+
expect(article).to be_changed
|
12
|
+
expect(article.tag_names_changed?).to eq(true)
|
13
|
+
expect(article.tag_names_was).to eq([])
|
14
|
+
expect(article.tag_names_change).to eq([[], ["pancakes"]])
|
15
|
+
|
16
|
+
if ActiveRecord::VERSION::STRING.to_f > 4.0
|
17
|
+
expect(article.tag_names_changed?(:from => [], :to => ["pancakes"])).
|
18
|
+
to eq(true)
|
19
|
+
end
|
20
|
+
|
21
|
+
if ActiveRecord::VERSION::STRING.to_f > 5.0
|
22
|
+
expect(article.will_save_change_to_tag_names?).to eq(true)
|
23
|
+
expect(article.tag_names_change_to_be_saved).to eq([[], ["pancakes"]])
|
24
|
+
expect(article.tag_names_in_database).to eq([])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "knows what tag names have changed" do
|
29
|
+
article.tag_names = ["pancakes"]
|
30
|
+
article.save
|
31
|
+
|
32
|
+
expect(article.tag_names).to eq(["pancakes"])
|
33
|
+
|
34
|
+
expect(article).to_not be_changed
|
35
|
+
expect(article.tag_names_changed?).to eq(false)
|
36
|
+
expect(article.previous_changes["tag_names"]).to eq([[], ["pancakes"]])
|
37
|
+
|
38
|
+
if ActiveRecord::VERSION::STRING.to_f >= 5.0
|
39
|
+
expect(article.tag_names_previously_changed?).to eq(true)
|
40
|
+
expect(article.tag_names_previous_change).to eq([[], ["pancakes"]])
|
41
|
+
end
|
42
|
+
|
43
|
+
if ActiveRecord::VERSION::STRING.to_f > 5.0
|
44
|
+
expect(article.saved_change_to_tag_names?).to eq(true)
|
45
|
+
expect(article.saved_change_to_tag_names).to eq([[], ["pancakes"]])
|
46
|
+
expect(article.saved_changes["tag_names"]).to eq([[], ["pancakes"]])
|
47
|
+
expect(article.tag_names_before_last_save).to eq([])
|
48
|
+
expect(article.tag_names_change_to_be_saved).to eq(nil)
|
49
|
+
expect(article.tag_names_in_database).to eq(["pancakes"])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe "Managing tags via names" do
|
6
|
-
let(:article)
|
6
|
+
let(:article) { Article.create }
|
7
7
|
|
8
8
|
it "returns tag names" do
|
9
9
|
melbourne = Gutentag::Tag.create :name => "melbourne"
|
@@ -20,25 +20,6 @@ describe "Managing tags via names" do
|
|
20
20
|
expect(article.tags.collect(&:name)).to eq(["melbourne"])
|
21
21
|
end
|
22
22
|
|
23
|
-
it "makes model dirty when changing through tag_names" do
|
24
|
-
article.tag_names << "melbourne"
|
25
|
-
article.save!
|
26
|
-
|
27
|
-
article.tag_names = ["sydney"]
|
28
|
-
|
29
|
-
expect(article.changed_attributes.stringify_keys).
|
30
|
-
to eq("tag_names" => ["melbourne"])
|
31
|
-
end if Gutentag.dirtier
|
32
|
-
|
33
|
-
it "does not make model dirty when changing through tag_names" do
|
34
|
-
article.tag_names << "melbourne"
|
35
|
-
article.save!
|
36
|
-
|
37
|
-
article.tag_names = ["melbourne"]
|
38
|
-
|
39
|
-
expect(article.changed_attributes).to eq({})
|
40
|
-
end
|
41
|
-
|
42
23
|
it "allows for different tag normalisation" do
|
43
24
|
Gutentag.normaliser = lambda { |name| name.upcase }
|
44
25
|
|
data/spec/spec_helper.rb
CHANGED
@@ -11,8 +11,19 @@ require "rspec/rails"
|
|
11
11
|
|
12
12
|
RSpec.configure do |config|
|
13
13
|
if config.respond_to?(:use_transactional_tests)
|
14
|
-
config.use_transactional_tests =
|
14
|
+
config.use_transactional_tests = false
|
15
15
|
else
|
16
|
-
config.use_transactional_fixtures =
|
16
|
+
config.use_transactional_fixtures = false
|
17
|
+
end
|
18
|
+
|
19
|
+
config.before(:suite) do
|
20
|
+
DatabaseCleaner.strategy = :truncation
|
21
|
+
DatabaseCleaner.clean_with(:truncation)
|
22
|
+
end
|
23
|
+
|
24
|
+
config.around(:each) do |example|
|
25
|
+
DatabaseCleaner.cleaning do
|
26
|
+
example.run
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gutentag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.8.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: database_cleaner
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.6'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rails
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,7 +147,8 @@ files:
|
|
133
147
|
- lib/gutentag.rb
|
134
148
|
- lib/gutentag/active_record.rb
|
135
149
|
- lib/gutentag/active_record/class_methods.rb
|
136
|
-
- lib/gutentag/active_record/
|
150
|
+
- lib/gutentag/active_record/legacy_instance_methods.rb
|
151
|
+
- lib/gutentag/active_record/modern_instance_methods.rb
|
137
152
|
- lib/gutentag/change_state.rb
|
138
153
|
- lib/gutentag/dirty.rb
|
139
154
|
- lib/gutentag/engine.rb
|
@@ -144,6 +159,7 @@ files:
|
|
144
159
|
- lib/gutentag/tagged_with/id_query.rb
|
145
160
|
- lib/gutentag/tagged_with/name_query.rb
|
146
161
|
- lib/gutentag/tagged_with/query.rb
|
162
|
+
- spec/acceptance/dirty_state_spec.rb
|
147
163
|
- spec/acceptance/removing_unused_spec.rb
|
148
164
|
- spec/acceptance/tag_names_spec.rb
|
149
165
|
- spec/acceptance/tags_spec.rb
|
@@ -176,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
192
|
version: '0'
|
177
193
|
requirements: []
|
178
194
|
rubyforge_project:
|
179
|
-
rubygems_version: 2.7.
|
195
|
+
rubygems_version: 2.7.6
|
180
196
|
signing_key:
|
181
197
|
specification_version: 4
|
182
198
|
summary: Good Tags
|