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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +21 -0
- data/.travis.yml +6 -5
- data/Appraisals +20 -26
- data/Gemfile +13 -8
- data/README.md +5 -1
- data/Rakefile +9 -5
- data/app/models/gutentag/tag.rb +7 -4
- data/app/models/gutentag/tagging.rb +5 -3
- data/bin/literals +9 -0
- data/db/migrate/1_gutentag_tables.rb +5 -3
- data/db/migrate/2_gutentag_cache_counter.rb +2 -0
- data/db/migrate/3_no_null_counters.rb +8 -4
- data/gutentag.gemspec +18 -18
- data/lib/gutentag.rb +13 -13
- data/lib/gutentag/active_record.rb +11 -6
- data/lib/gutentag/active_record/class_methods.rb +4 -16
- data/lib/gutentag/active_record/instance_methods.rb +3 -1
- data/lib/gutentag/change_state.rb +32 -0
- data/lib/gutentag/dirty.rb +4 -1
- data/lib/gutentag/engine.rb +2 -4
- data/lib/gutentag/persistence.rb +13 -16
- data/lib/gutentag/tag_validations.rb +4 -1
- data/lib/gutentag/tagged_with.rb +5 -3
- data/lib/gutentag/tagged_with/id_query.rb +2 -0
- data/lib/gutentag/tagged_with/name_query.rb +2 -0
- data/lib/gutentag/tagged_with/query.rb +2 -0
- data/spec/acceptance/tag_names_spec.rb +40 -38
- data/spec/acceptance/tags_spec.rb +8 -6
- data/spec/gutentag/active_record_spec.rb +69 -112
- data/spec/gutentag_spec.rb +5 -3
- data/spec/internal/app/models/article.rb +2 -0
- data/spec/internal/db/schema.rb +2 -0
- data/spec/models/gutentag/tag_spec.rb +24 -22
- data/spec/models/gutentag/tagging_spec.rb +5 -3
- data/spec/spec_helper.rb +4 -2
- metadata +11 -43
- data/gemfiles/rails_3_2.gemfile +0 -11
- data/gemfiles/rails_4_0.gemfile +0 -11
- data/gemfiles/rails_4_1.gemfile +0 -11
- data/gemfiles/rails_4_2.gemfile +0 -10
- data/gemfiles/rails_5_0.gemfile +0 -8
- data/gemfiles/rails_5_1.gemfile +0 -8
- data/lib/gutentag/has_many_tags.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e38980a4454dabe309f3c203ddd7b918f82c5193
|
4
|
+
data.tar.gz: 8b50af89daa6b099ae1cca584478758d11ab6b0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31686ed82181198d188ea9e6f323b3e47e9dbb69e53d9458a2d1adbcbd75d17cc2baf6a563428caabe9dcca0552c22b1efb785e5834312baadefa59f2eeb9a4c
|
7
|
+
data.tar.gz: d9c469b2df3bc48d991700f0e062aa626efeca3c2d15fd813f0f108705ad471d4d833814fbf61af29d577a276e1936cc418746c8e37ce19e448bbfd12a51978c
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
inherit_from:
|
2
|
+
- https://gist.githubusercontent.com/pat/ba3b8ffb1901bfe5439b460943b6b019/raw/.rubocop.yml
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
TargetRubyVersion: 2.2
|
6
|
+
|
7
|
+
Metrics/MethodLength:
|
8
|
+
Exclude:
|
9
|
+
- db/migrate/1_gutentag_tables.rb
|
10
|
+
|
11
|
+
Style/MultilineIfModifier:
|
12
|
+
Exclude:
|
13
|
+
- Appraisals
|
14
|
+
- spec/acceptance/tag_names_spec.rb
|
15
|
+
|
16
|
+
Style/MultilineTernaryOperator:
|
17
|
+
Exclude:
|
18
|
+
- db/migrate/*.rb
|
19
|
+
|
20
|
+
Style/SafeNavigation:
|
21
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
language: ruby
|
2
|
-
script: bundle exec appraisal
|
2
|
+
script: bundle exec appraisal rake
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
- 2.
|
6
|
-
- 2.
|
7
|
-
-
|
4
|
+
- 2.2.8
|
5
|
+
- 2.3.5
|
6
|
+
- 2.4.2
|
7
|
+
- jruby-9.1.13.0
|
8
8
|
before_install:
|
9
9
|
- gem install bundler
|
10
10
|
before_script:
|
11
11
|
- bundle exec appraisal install
|
12
|
+
- ./bin/literals
|
12
13
|
env:
|
13
14
|
- DATABASE=postgres
|
14
15
|
- DATABASE=mysql
|
data/Appraisals
CHANGED
@@ -1,34 +1,28 @@
|
|
1
|
-
|
2
|
-
gem 'rails', '~> 3.2.22.5'
|
3
|
-
gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
|
4
|
-
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
5
|
-
gem 'mysql2', '~> 0.3.10'
|
6
|
-
end if RUBY_VERSION.to_f < 2.2
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
appraise
|
9
|
-
gem
|
10
|
-
gem
|
11
|
-
|
12
|
-
|
3
|
+
appraise "rails_3_2" do
|
4
|
+
gem "rails", "~> 3.2.22.5"
|
5
|
+
gem "mysql2", "~> 0.3.10", :platform => :ruby
|
6
|
+
end if RUBY_VERSION.to_f <= 2.2
|
7
|
+
|
8
|
+
appraise "rails_4_0" do
|
9
|
+
gem "rails", "~> 4.0.13"
|
10
|
+
gem "mysql2", "~> 0.3.10", :platform => :ruby
|
13
11
|
end if RUBY_VERSION.to_f < 2.4
|
14
12
|
|
15
|
-
appraise
|
16
|
-
gem
|
17
|
-
gem
|
18
|
-
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
19
|
-
gem 'mysql2', '~> 0.3.13'
|
13
|
+
appraise "rails_4_1" do
|
14
|
+
gem "rails", "~> 4.1.16"
|
15
|
+
gem "mysql2", "~> 0.3.13", :platform => :ruby
|
20
16
|
end if RUBY_VERSION.to_f < 2.4
|
21
17
|
|
22
|
-
appraise
|
23
|
-
gem
|
24
|
-
gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
|
25
|
-
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
18
|
+
appraise "rails_4_2" do
|
19
|
+
gem "rails", "~> 4.2.8"
|
26
20
|
end if RUBY_VERSION.to_f < 2.4
|
27
21
|
|
28
|
-
appraise
|
29
|
-
gem
|
30
|
-
end if RUBY_VERSION.to_f >= 2.2
|
22
|
+
appraise "rails_5_0" do
|
23
|
+
gem "rails", "~> 5.0.3"
|
24
|
+
end if RUBY_VERSION.to_f >= 2.2 && RUBY_PLATFORM != "java"
|
31
25
|
|
32
|
-
appraise
|
33
|
-
gem
|
34
|
-
end if RUBY_VERSION.to_f >= 2.2
|
26
|
+
appraise "rails_5_1" do
|
27
|
+
gem "rails", "~> 5.1.1"
|
28
|
+
end if RUBY_VERSION.to_f >= 2.2 && RUBY_PLATFORM != "java"
|
data/Gemfile
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
|
-
gem
|
6
|
-
|
7
|
-
gem
|
7
|
+
gem "test-unit", :platform => :ruby_22
|
8
|
+
|
9
|
+
gem "mysql2", "~> 0.3", :platform => :ruby
|
10
|
+
gem "pg", "~> 0.18", :platform => :ruby
|
11
|
+
gem "sqlite3", "~> 1.3", :platform => :ruby
|
12
|
+
|
13
|
+
gem "activerecord-jdbcmysql-adapter", "~> 1.3.23", :platform => :jruby
|
14
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.23", :platform => :jruby
|
15
|
+
gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.23", :platform => :jruby
|
8
16
|
|
9
|
-
gem
|
10
|
-
:git => 'https://github.com/pat/combustion.git',
|
11
|
-
:branch => 'master',
|
12
|
-
:ref => 'ef434634d7'
|
17
|
+
gem "activerecord", [">= 3.2.22", "< 5"] if RUBY_PLATFORM == "java"
|
data/README.md
CHANGED
@@ -68,7 +68,7 @@ Article.tagged_with(:ids => [tag_a.id, tag_b.id], :match => :all)
|
|
68
68
|
Get it into your Gemfile - and don't forget the version constraint!
|
69
69
|
|
70
70
|
```Ruby
|
71
|
-
gem 'gutentag', '~> 0.
|
71
|
+
gem 'gutentag', '~> 1.0.0'
|
72
72
|
```
|
73
73
|
|
74
74
|
Next: your tags get persisted to your database, so let's import and run the migrations to get the tables set up:
|
@@ -105,6 +105,10 @@ add_index :gutentag_tags, :taggings_count
|
|
105
105
|
|
106
106
|
<h2 id="upgrading">Upgrading</h2>
|
107
107
|
|
108
|
+
### 1.0.0
|
109
|
+
|
110
|
+
Behaviour that was deprecated in 0.9.0 (`has_many_tags`, `tagged_with` arguments) have now been removed.
|
111
|
+
|
108
112
|
### 0.9.0
|
109
113
|
|
110
114
|
* In your models with tags, change `has_many_tags` to `Gutentag::ActiveRecord.call self`.
|
data/Rakefile
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require "rspec/core/rake_task"
|
6
|
+
require "rubocop/rake_task"
|
4
7
|
|
5
8
|
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
RuboCop::RakeTask.new(:rubocop)
|
6
10
|
|
7
|
-
task :default => [
|
8
|
-
task :test => [
|
11
|
+
task :default => %i[ test ]
|
12
|
+
task :test => %i[ rubocop spec ]
|
data/app/models/gutentag/tag.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Gutentag::Tag < ActiveRecord::Base
|
2
|
-
self.table_name =
|
4
|
+
self.table_name = "gutentag_tags"
|
3
5
|
|
4
|
-
has_many :taggings,
|
5
|
-
:
|
6
|
+
has_many :taggings,
|
7
|
+
:class_name => "Gutentag::Tagging",
|
8
|
+
:dependent => :destroy
|
6
9
|
|
7
10
|
attr_accessible :name if ActiveRecord::VERSION::MAJOR == 3
|
8
11
|
|
9
|
-
scope :by_weight,
|
12
|
+
scope :by_weight, lambda { order("gutentag_tags.taggings_count DESC") }
|
10
13
|
|
11
14
|
Gutentag.tag_validations.call self
|
12
15
|
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Gutentag::Tagging < ActiveRecord::Base
|
2
|
-
self.table_name =
|
4
|
+
self.table_name = "gutentag_taggings"
|
3
5
|
|
4
6
|
belongs_to :taggable, :polymorphic => true
|
5
|
-
belongs_to :tag, :class_name =>
|
7
|
+
belongs_to :tag, :class_name => "Gutentag::Tag", :counter_cache => true
|
6
8
|
|
7
9
|
validates :taggable, :presence => true
|
8
10
|
validates :tag, :presence => true
|
9
11
|
validates :tag_id, :uniqueness => {
|
10
|
-
:scope => [
|
12
|
+
:scope => %i[ taggable_id taggable_type ]
|
11
13
|
}
|
12
14
|
end
|
data/bin/literals
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
if (ruby -e "exit RUBY_VERSION.to_f >= 2.4")
|
2
|
+
then
|
3
|
+
echo "Automatic frozen string literals are supported"
|
4
|
+
gem install pragmater -v 4.0.0
|
5
|
+
pragmater --add lib --comments "# frozen_string_literal: true" --whitelist "**/*.rb"
|
6
|
+
pragmater --add spec --comments "# frozen_string_literal: true" --whitelist "**/*.rb"
|
7
|
+
else
|
8
|
+
echo "Automatic frozen string literals are not supported."
|
9
|
+
fi
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
superclass = ActiveRecord::VERSION::MAJOR < 5 ?
|
2
4
|
ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
3
5
|
class GutentagTables < superclass
|
@@ -10,9 +12,9 @@ class GutentagTables < superclass
|
|
10
12
|
end
|
11
13
|
|
12
14
|
add_index :gutentag_taggings, :tag_id
|
13
|
-
add_index :gutentag_taggings, [
|
14
|
-
add_index :gutentag_taggings, [
|
15
|
-
:unique => true, :name =>
|
15
|
+
add_index :gutentag_taggings, %i[ taggable_type taggable_id ]
|
16
|
+
add_index :gutentag_taggings, %i[ taggable_type taggable_id tag_id ],
|
17
|
+
:unique => true, :name => "unique_taggings"
|
16
18
|
|
17
19
|
create_table :gutentag_tags do |t|
|
18
20
|
t.string :name, :null => false
|
@@ -1,13 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
superclass = ActiveRecord::VERSION::MAJOR < 5 ?
|
2
4
|
ActiveRecord::Migration : ActiveRecord::Migration[4.2]
|
3
5
|
class NoNullCounters < superclass
|
4
6
|
def up
|
5
|
-
change_column :gutentag_tags, :taggings_count, :integer,
|
6
|
-
:
|
7
|
+
change_column :gutentag_tags, :taggings_count, :integer,
|
8
|
+
:default => 0,
|
9
|
+
:null => false
|
7
10
|
end
|
8
11
|
|
9
12
|
def down
|
10
|
-
change_column :gutentag_tags, :taggings_count, :integer,
|
11
|
-
:
|
13
|
+
change_column :gutentag_tags, :taggings_count, :integer,
|
14
|
+
:default => 0,
|
15
|
+
:null => true
|
12
16
|
end
|
13
17
|
end
|
data/gutentag.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# -*- encoding: utf-8 -*-
|
3
|
+
|
2
4
|
Gem::Specification.new do |s|
|
3
|
-
s.name =
|
4
|
-
s.version =
|
5
|
-
s.authors = [
|
6
|
-
s.email = [
|
7
|
-
s.homepage =
|
8
|
-
s.summary =
|
9
|
-
s.description =
|
10
|
-
s.license =
|
5
|
+
s.name = "gutentag"
|
6
|
+
s.version = "1.0.0"
|
7
|
+
s.authors = ["Pat Allan"]
|
8
|
+
s.email = ["pat@freelancing-gods.com"]
|
9
|
+
s.homepage = "https://github.com/pat/gutentag"
|
10
|
+
s.summary = "Good Tags"
|
11
|
+
s.description = "A good, simple, solid tagging extension for ActiveRecord"
|
12
|
+
s.license = "MIT"
|
11
13
|
|
12
14
|
s.files = `git ls-files`.split("\n")
|
13
15
|
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
14
|
-
s.require_paths = [
|
16
|
+
s.require_paths = ["lib"]
|
15
17
|
|
16
|
-
s.add_runtime_dependency
|
18
|
+
s.add_runtime_dependency "activerecord", ">= 3.2.0"
|
17
19
|
|
18
|
-
s.add_development_dependency
|
19
|
-
s.add_development_dependency
|
20
|
-
s.add_development_dependency
|
21
|
-
s.add_development_dependency
|
22
|
-
s.add_development_dependency
|
23
|
-
s.add_development_dependency
|
24
|
-
s.add_development_dependency 'rspec-rails', '~> 3.1'
|
25
|
-
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
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.7.0"
|
23
|
+
s.add_development_dependency "rails"
|
24
|
+
s.add_development_dependency "rspec-rails", "~> 3.1"
|
25
|
+
s.add_development_dependency "rubocop", "~> 0.51.0"
|
26
26
|
end
|
data/lib/gutentag.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/version"
|
3
4
|
|
4
5
|
module Gutentag
|
5
6
|
def self.dirtier
|
@@ -27,12 +28,12 @@ module Gutentag
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
33
|
-
require
|
34
|
-
require
|
35
|
-
require
|
31
|
+
require "gutentag/active_record"
|
32
|
+
require "gutentag/change_state"
|
33
|
+
require "gutentag/dirty"
|
34
|
+
require "gutentag/persistence"
|
35
|
+
require "gutentag/tag_validations"
|
36
|
+
require "gutentag/tagged_with"
|
36
37
|
|
37
38
|
if ActiveRecord::VERSION::MAJOR == 3
|
38
39
|
Gutentag.dirtier = Gutentag::Dirty
|
@@ -41,10 +42,9 @@ elsif ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR < 2
|
|
41
42
|
end
|
42
43
|
|
43
44
|
if defined?(Rails::Engine)
|
44
|
-
require
|
45
|
+
require "gutentag/engine"
|
45
46
|
else
|
46
|
-
require
|
47
|
-
|
48
|
-
require_relative
|
49
|
-
require_relative '../app/models/gutentag/tagging'
|
47
|
+
require "active_record"
|
48
|
+
require_relative "../app/models/gutentag/tag"
|
49
|
+
require_relative "../app/models/gutentag/tagging"
|
50
50
|
end
|
@@ -1,9 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Gutentag::ActiveRecord
|
2
4
|
def self.call(model)
|
3
|
-
model.has_many :taggings,
|
4
|
-
:
|
5
|
-
|
6
|
-
:
|
5
|
+
model.has_many :taggings,
|
6
|
+
:class_name => "Gutentag::Tagging",
|
7
|
+
:as => :taggable,
|
8
|
+
:dependent => :destroy
|
9
|
+
model.has_many :tags,
|
10
|
+
:class_name => "Gutentag::Tag",
|
11
|
+
:through => :taggings
|
7
12
|
|
8
13
|
model.after_save :persist_tags
|
9
14
|
|
@@ -12,5 +17,5 @@ class Gutentag::ActiveRecord
|
|
12
17
|
end
|
13
18
|
end
|
14
19
|
|
15
|
-
require
|
16
|
-
require
|
20
|
+
require "gutentag/active_record/class_methods"
|
21
|
+
require "gutentag/active_record/instance_methods"
|
@@ -1,19 +1,7 @@
|
|
1
|
-
|
2
|
-
def tagged_with(*arguments)
|
3
|
-
arguments.flatten!
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
when Integer
|
9
|
-
ActiveSupport::Deprecation.warn "Calling tagged_with with an array of integers will not be supported in Gutentag 1.0. Please use tagged_with :ids => [1, 2] instead."
|
10
|
-
Gutentag::TaggedWith.call(self, :ids => arguments)
|
11
|
-
when Gutentag::Tag
|
12
|
-
ActiveSupport::Deprecation.warn "Calling tagged_with with an array of tags will not be supported in Gutentag 1.0. Please use tagged_with :tags => [tag_a, tag_b] instead."
|
13
|
-
Gutentag::TaggedWith.call(self, :tags => arguments)
|
14
|
-
else
|
15
|
-
ActiveSupport::Deprecation.warn "Calling tagged_with with an array of strings will not be supported in Gutentag 1.0. Please use tagged_with :names => [\"melbourne\", \"ruby\"] instead."
|
16
|
-
Gutentag::TaggedWith.call(self, :names => arguments)
|
17
|
-
end
|
3
|
+
module Gutentag::ActiveRecord::ClassMethods
|
4
|
+
def tagged_with(options)
|
5
|
+
Gutentag::TaggedWith.call self, options
|
18
6
|
end
|
19
7
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gutentag::ActiveRecord::InstanceMethods
|
2
4
|
def reset_tag_names
|
3
5
|
@tag_names = nil
|
@@ -16,6 +18,6 @@ module Gutentag::ActiveRecord::InstanceMethods
|
|
16
18
|
private
|
17
19
|
|
18
20
|
def persist_tags
|
19
|
-
Gutentag::Persistence.new(self).persist
|
21
|
+
Gutentag::Persistence.new(Gutentag::ChangeState.new(self)).persist
|
20
22
|
end
|
21
23
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gutentag::ChangeState
|
4
|
+
attr_reader :taggable
|
5
|
+
attr_writer :normaliser
|
6
|
+
|
7
|
+
def initialize(taggable)
|
8
|
+
@taggable = taggable
|
9
|
+
@existing = normalised taggable.tags.collect(&:name)
|
10
|
+
@changes = normalised taggable.tag_names
|
11
|
+
end
|
12
|
+
|
13
|
+
def added
|
14
|
+
@added ||= changes - existing
|
15
|
+
end
|
16
|
+
|
17
|
+
def removed
|
18
|
+
@removed ||= existing - changes
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :existing, :changes
|
24
|
+
|
25
|
+
def normalised(names)
|
26
|
+
names.collect { |name| normaliser.call(name) }.uniq
|
27
|
+
end
|
28
|
+
|
29
|
+
def normaliser
|
30
|
+
@normaliser ||= proc { |name| Gutentag.normaliser.call(name) }
|
31
|
+
end
|
32
|
+
end
|