gutentag 0.7.0 → 0.8.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/.travis.yml +3 -1
- data/Appraisals +20 -8
- data/Gemfile +2 -0
- data/README.md +15 -1
- data/app/models/gutentag/tag.rb +1 -1
- data/gemfiles/rails_3_2.gemfile +3 -1
- data/gemfiles/rails_4_0.gemfile +2 -0
- data/gemfiles/rails_4_1.gemfile +3 -1
- data/gemfiles/rails_4_2.gemfile +3 -1
- data/gemfiles/rails_5_0.gemfile +8 -0
- data/gutentag.gemspec +3 -3
- data/lib/gutentag/active_record.rb +15 -1
- data/lib/gutentag/tag_names.rb +21 -0
- data/lib/gutentag/tag_validations.rb +18 -0
- data/lib/gutentag.rb +11 -1
- data/spec/gutentag/active_record_spec.rb +79 -0
- data/spec/spec_helper.rb +5 -6
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a963454a3117dc737b8d4e70e8a02c22c2c2693e
|
4
|
+
data.tar.gz: bc7c540a51edbabb378370b9157451a29dcbbfdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aaf39b46f22f2348b87dbc8d574d17d5d2b5728810980c16b1c344d894900701ff3434e43f2794c6ce3ce2515039de6fe887161110ee0aa4f0aa54db8152b1b1
|
7
|
+
data.tar.gz: 835f63c380604816cd1e5014960f3e75e199f167705635f45cea36467c288b0da7e504c1fa4ad8d35763aec26714cb6a754d58821ed54a244ca906e39cac7d0d
|
data/.travis.yml
CHANGED
data/Appraisals
CHANGED
@@ -1,15 +1,27 @@
|
|
1
1
|
appraise 'rails_3_2' do
|
2
|
-
gem 'rails',
|
3
|
-
|
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
|
+
end if RUBY_VERSION.to_f < 2.2
|
4
6
|
|
5
7
|
appraise 'rails_4_0' do
|
6
|
-
gem 'rails',
|
7
|
-
|
8
|
+
gem 'rails', '~> 4.0.13'
|
9
|
+
gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
|
10
|
+
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
11
|
+
end if RUBY_VERSION.to_f < 2.4
|
8
12
|
|
9
13
|
appraise 'rails_4_1' do
|
10
|
-
gem 'rails',
|
11
|
-
|
14
|
+
gem 'rails', '~> 4.1.16'
|
15
|
+
gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
|
16
|
+
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
17
|
+
end if RUBY_VERSION.to_f < 2.4
|
12
18
|
|
13
19
|
appraise 'rails_4_2' do
|
14
|
-
gem 'rails',
|
15
|
-
|
20
|
+
gem 'rails', '~> 4.2.7'
|
21
|
+
gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
|
22
|
+
gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
|
23
|
+
end if RUBY_VERSION.to_f < 2.4
|
24
|
+
|
25
|
+
appraise 'rails_5_0' do
|
26
|
+
gem 'rails', '~> 5.0.1'
|
27
|
+
end if RUBY_VERSION.to_f >= 2.2
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,7 +12,7 @@ This was built partly as a proof-of-concept, and partly to see how a tagging gem
|
|
12
12
|
|
13
13
|
Get it into your Gemfile - and don't forget the version constraint!
|
14
14
|
|
15
|
-
gem 'gutentag', '~> 0.
|
15
|
+
gem 'gutentag', '~> 0.8.0'
|
16
16
|
|
17
17
|
Next: your tags get persisted to your database, so let's import and run the migrations to get the tables set up:
|
18
18
|
|
@@ -44,6 +44,14 @@ If you want to use Gutentag outside of Rails, you can. However, this means you l
|
|
44
44
|
|
45
45
|
## Upgrading
|
46
46
|
|
47
|
+
### 0.8.0
|
48
|
+
|
49
|
+
No breaking changes.
|
50
|
+
|
51
|
+
### 0.7.0
|
52
|
+
|
53
|
+
No breaking changes.
|
54
|
+
|
47
55
|
### 0.6.0
|
48
56
|
|
49
57
|
Rails 4.2 is supported as of Gutentag 0.6.0 - but please note that due to internal changes in ActiveRecord, changes to tag_names will no longer be tracked by your model's dirty state. This feature will continue to work in Rails 3.2 through to 4.1 though.
|
@@ -80,6 +88,12 @@ Changes to tag_names are not persisted immediately - you must save your taggable
|
|
80
88
|
article.tag_names << 'ruby'
|
81
89
|
article.save
|
82
90
|
|
91
|
+
You can also query for instances with specified tags. This is OR logic, not AND - it'll match any instances that have *any* of the tags or tag names.
|
92
|
+
|
93
|
+
Article.tagged_with('tag1', 'tag2')
|
94
|
+
Article.tagged_with(Gutentag::Tag.where(name: ['tag1', 'tag2'])
|
95
|
+
# => [#<Article id: "123">]
|
96
|
+
|
83
97
|
## Contribution
|
84
98
|
|
85
99
|
Please note that this project now has a [Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). By participating in this project you agree to abide by its terms.
|
data/app/models/gutentag/tag.rb
CHANGED
@@ -8,7 +8,7 @@ class Gutentag::Tag < ActiveRecord::Base
|
|
8
8
|
|
9
9
|
scope :by_weight, ->{ order('gutentag_tags.taggings_count DESC') }
|
10
10
|
|
11
|
-
|
11
|
+
Gutentag.tag_validations.call self
|
12
12
|
|
13
13
|
before_validation :normalise_name
|
14
14
|
|
data/gemfiles/rails_3_2.gemfile
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gem "test-unit", :platform => :ruby_22
|
6
|
-
gem "
|
6
|
+
gem "rack", "~> 1.0", :platforms => [:ruby_20, :ruby_21]
|
7
|
+
gem "rails", "~> 3.2.22.5"
|
8
|
+
gem "nokogiri", "~> 1.6.0", :platforms => [:ruby_20]
|
7
9
|
|
8
10
|
gemspec :path => "../"
|
data/gemfiles/rails_4_0.gemfile
CHANGED
data/gemfiles/rails_4_1.gemfile
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gem "test-unit", :platform => :ruby_22
|
6
|
-
gem "rails", "~> 4.1.
|
6
|
+
gem "rails", "~> 4.1.16"
|
7
|
+
gem "rack", "~> 1.0", :platforms => [:ruby_20, :ruby_21]
|
8
|
+
gem "nokogiri", "~> 1.6.0", :platforms => [:ruby_20]
|
7
9
|
|
8
10
|
gemspec :path => "../"
|
data/gemfiles/rails_4_2.gemfile
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gem "test-unit", :platform => :ruby_22
|
6
|
-
gem "rails", "~> 4.2.
|
6
|
+
gem "rails", "~> 4.2.7"
|
7
|
+
gem "rack", "~> 1.0", :platforms => [:ruby_20, :ruby_21]
|
8
|
+
gem "nokogiri", "~> 1.6.0", :platforms => [:ruby_20]
|
7
9
|
|
8
10
|
gemspec :path => "../"
|
data/gutentag.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'gutentag'
|
4
|
-
s.version = '0.
|
4
|
+
s.version = '0.8.0'
|
5
5
|
s.authors = ['Pat Allan']
|
6
6
|
s.email = ['pat@freelancing-gods.com']
|
7
7
|
s.homepage = 'https://github.com/pat/gutentag'
|
@@ -15,9 +15,9 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.add_runtime_dependency 'activerecord', '>= 3.2.0'
|
17
17
|
|
18
|
-
s.add_development_dependency 'appraisal', '~> 1.0
|
18
|
+
s.add_development_dependency 'appraisal', '~> 2.1.0'
|
19
19
|
s.add_development_dependency 'bundler', '>= 1.7.12'
|
20
|
-
s.add_development_dependency 'combustion', '0.5.
|
20
|
+
s.add_development_dependency 'combustion', '0.5.5'
|
21
21
|
s.add_development_dependency 'rails'
|
22
22
|
s.add_development_dependency 'rspec-rails', '~> 3.1'
|
23
23
|
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
@@ -3,6 +3,8 @@ require 'active_support/concern'
|
|
3
3
|
module Gutentag::ActiveRecord
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
+
UNIQUENESS_METHOD = ActiveRecord::VERSION::MAJOR == 3 ? :uniq : :distinct
|
7
|
+
|
6
8
|
module ClassMethods
|
7
9
|
def has_many_tags
|
8
10
|
has_many :taggings, :class_name => 'Gutentag::Tagging', :as => :taggable,
|
@@ -10,7 +12,13 @@ module Gutentag::ActiveRecord
|
|
10
12
|
has_many :tags, :class_name => 'Gutentag::Tag',
|
11
13
|
:through => :taggings
|
12
14
|
|
13
|
-
after_save
|
15
|
+
after_save :persist_tags
|
16
|
+
end
|
17
|
+
|
18
|
+
def tagged_with(*tags)
|
19
|
+
joins(:tags).where(
|
20
|
+
Gutentag::Tag.table_name => {:name => Gutentag::TagNames.call(tags)}
|
21
|
+
).public_send UNIQUENESS_METHOD
|
14
22
|
end
|
15
23
|
end
|
16
24
|
|
@@ -27,4 +35,10 @@ module Gutentag::ActiveRecord
|
|
27
35
|
|
28
36
|
@tag_names = names
|
29
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def persist_tags
|
42
|
+
Gutentag::Persistence.new(self).persist
|
43
|
+
end
|
30
44
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Gutentag::TagNames
|
2
|
+
def self.call(*names)
|
3
|
+
new(names).call
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(names)
|
7
|
+
@names = names.flatten
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
name_values.collect { |name| Gutentag::TagName.call name }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :names
|
17
|
+
|
18
|
+
def name_values
|
19
|
+
names.collect { |name| name.respond_to?(:name) ? name.name : name.to_s }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Gutentag::TagValidations
|
2
|
+
def self.call(klass)
|
3
|
+
new(klass).call
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(klass)
|
7
|
+
@klass = klass
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
klass.validates :name, :presence => true,
|
12
|
+
:uniqueness => {:case_sensitive => false}
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :klass
|
18
|
+
end
|
data/lib/gutentag.rb
CHANGED
@@ -16,12 +16,22 @@ module Gutentag
|
|
16
16
|
def self.normaliser=(normaliser)
|
17
17
|
@normaliser = normaliser
|
18
18
|
end
|
19
|
+
|
20
|
+
def self.tag_validations
|
21
|
+
@tag_validations ||= Gutentag::TagValidations
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.tag_validations=(tag_validations)
|
25
|
+
@tag_validations = tag_validations
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
29
|
require 'gutentag/active_record'
|
22
30
|
require 'gutentag/dirty'
|
23
31
|
require 'gutentag/persistence'
|
24
32
|
require 'gutentag/tag_name'
|
33
|
+
require 'gutentag/tag_names'
|
34
|
+
require 'gutentag/tag_validations'
|
25
35
|
|
26
36
|
if ActiveRecord::VERSION::MAJOR == 3
|
27
37
|
Gutentag.dirtier = Gutentag::Dirty
|
@@ -33,7 +43,7 @@ if defined?(Rails::Engine)
|
|
33
43
|
require 'gutentag/engine'
|
34
44
|
else
|
35
45
|
require 'active_record'
|
36
|
-
ActiveRecord::Base.include Gutentag::ActiveRecord
|
46
|
+
ActiveRecord::Base.send :include, Gutentag::ActiveRecord
|
37
47
|
require File.expand_path(
|
38
48
|
'./../app/models/gutentag/tag', File.dirname(__FILE__)
|
39
49
|
)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Gutentag::ActiveRecord do
|
4
|
+
describe '.tagged_with' do
|
5
|
+
let!(:melborne_article) do
|
6
|
+
article = Article.create :title => 'Overview'
|
7
|
+
article.tag_names << 'melborne'
|
8
|
+
article.save!
|
9
|
+
article
|
10
|
+
end
|
11
|
+
|
12
|
+
let!(:oregon_article) do
|
13
|
+
article = Article.create
|
14
|
+
article.tag_names << 'oregon'
|
15
|
+
article.save!
|
16
|
+
article
|
17
|
+
end
|
18
|
+
|
19
|
+
let!(:melborne_oregon_article) do
|
20
|
+
article = Article.create
|
21
|
+
article.tag_names = %w(oregon melborne)
|
22
|
+
article.save!
|
23
|
+
article
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'given a single tag name' do
|
27
|
+
subject { Article.tagged_with('melborne') }
|
28
|
+
|
29
|
+
it { expect(subject.count).to eq 2 }
|
30
|
+
it { is_expected.to include melborne_article, melborne_oregon_article }
|
31
|
+
it { is_expected.not_to include oregon_article }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'given a single tag name[symbol]' do
|
35
|
+
subject { Article.tagged_with(:melborne) }
|
36
|
+
|
37
|
+
it { expect(subject.count).to eq 2 }
|
38
|
+
it { is_expected.to include melborne_article, melborne_oregon_article }
|
39
|
+
it { is_expected.not_to include oregon_article }
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'given multiple tag names' do
|
43
|
+
subject { Article.tagged_with('melborne', 'oregon') }
|
44
|
+
|
45
|
+
it { expect(subject.count).to eq 3 }
|
46
|
+
it { is_expected.to include melborne_article, oregon_article, melborne_oregon_article }
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'given an array of tag names' do
|
50
|
+
subject { Article.tagged_with(%w(melborne oregon)) }
|
51
|
+
|
52
|
+
it { expect(subject.count).to eq 3 }
|
53
|
+
it { is_expected.to include melborne_article, oregon_article, melborne_oregon_article }
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'given a single tag instance' do
|
57
|
+
subject { Article.tagged_with(Gutentag::Tag.find_by_name('melborne')) }
|
58
|
+
|
59
|
+
it { expect(subject.count).to eq 2 }
|
60
|
+
it { is_expected.to include melborne_article, melborne_oregon_article }
|
61
|
+
it { is_expected.not_to include oregon_article }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'given multiple tag objects' do
|
65
|
+
subject { Article.tagged_with(Gutentag::Tag.where(name: %w(melborne oregon))) }
|
66
|
+
|
67
|
+
it { expect(subject.count).to eq 3 }
|
68
|
+
it { is_expected.to include melborne_article, oregon_article, melborne_oregon_article }
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'chaining where clause' do
|
72
|
+
subject { Article.tagged_with(%w(melborne oregon)).where(title: 'Overview') }
|
73
|
+
|
74
|
+
it { expect(subject.count).to eq 1 }
|
75
|
+
it { is_expected.to include melborne_article }
|
76
|
+
it { is_expected.not_to include oregon_article, melborne_oregon_article }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
|
3
|
-
# Get Bundler set up
|
4
|
-
Bundler.setup :default, :development
|
5
|
-
# Require Rails first
|
6
|
-
require 'rails'
|
7
|
-
# Then require everything else
|
8
3
|
Bundler.require :default, :development
|
9
4
|
|
10
5
|
Combustion.initialize! :active_record
|
@@ -12,5 +7,9 @@ Combustion.initialize! :active_record
|
|
12
7
|
require 'rspec/rails'
|
13
8
|
|
14
9
|
RSpec.configure do |config|
|
15
|
-
config.
|
10
|
+
if config.respond_to?(:use_transactional_tests)
|
11
|
+
config.use_transactional_tests = true
|
12
|
+
else
|
13
|
+
config.use_transactional_fixtures = true
|
14
|
+
end
|
16
15
|
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: 0.
|
4
|
+
version: 0.8.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:
|
11
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0
|
33
|
+
version: 2.1.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.0
|
40
|
+
version: 2.1.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.5.
|
61
|
+
version: 0.5.5
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.5.
|
68
|
+
version: 0.5.5
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rails
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- gemfiles/rails_4_0.gemfile
|
132
132
|
- gemfiles/rails_4_1.gemfile
|
133
133
|
- gemfiles/rails_4_2.gemfile
|
134
|
+
- gemfiles/rails_5_0.gemfile
|
134
135
|
- gutentag.gemspec
|
135
136
|
- lib/gutentag.rb
|
136
137
|
- lib/gutentag/active_record.rb
|
@@ -138,8 +139,11 @@ files:
|
|
138
139
|
- lib/gutentag/engine.rb
|
139
140
|
- lib/gutentag/persistence.rb
|
140
141
|
- lib/gutentag/tag_name.rb
|
142
|
+
- lib/gutentag/tag_names.rb
|
143
|
+
- lib/gutentag/tag_validations.rb
|
141
144
|
- spec/acceptance/tag_names_spec.rb
|
142
145
|
- spec/acceptance/tags_spec.rb
|
146
|
+
- spec/gutentag/active_record_spec.rb
|
143
147
|
- spec/gutentag/tag_name_spec.rb
|
144
148
|
- spec/internal/app/models/article.rb
|
145
149
|
- spec/internal/config/database.yml
|
@@ -168,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
172
|
version: '0'
|
169
173
|
requirements: []
|
170
174
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.6.8
|
172
176
|
signing_key:
|
173
177
|
specification_version: 4
|
174
178
|
summary: Good Tags
|