gutentag 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41b7dca53fda65125a90143737854b6fefda5156
4
- data.tar.gz: b0a453c0aa5aa9f40455f3f656c4f74376cdf828
3
+ metadata.gz: a963454a3117dc737b8d4e70e8a02c22c2c2693e
4
+ data.tar.gz: bc7c540a51edbabb378370b9157451a29dcbbfdb
5
5
  SHA512:
6
- metadata.gz: 7331fcc7c2865f3eb6c9c734b7abcbe9e1ae16fc570868b978a78b6d26467ddf04235810f788dcec3e915faed6f7927009e2ccc4bbe0e7fc2e3473521cbcfa70
7
- data.tar.gz: 64b42b9c53f92897b833464b5040bc2fa698f39cbe31c8142d9f5367a137fdc23def53960da25e4ebae6e579bb2395f44586259b0033e9423d0b48eb1bf9b270
6
+ metadata.gz: aaf39b46f22f2348b87dbc8d574d17d5d2b5728810980c16b1c344d894900701ff3434e43f2794c6ce3ce2515039de6fe887161110ee0aa4f0aa54db8152b1b1
7
+ data.tar.gz: 835f63c380604816cd1e5014960f3e75e199f167705635f45cea36467c288b0da7e504c1fa4ad8d35763aec26714cb6a754d58821ed54a244ca906e39cac7d0d
data/.travis.yml CHANGED
@@ -2,7 +2,9 @@ language: ruby
2
2
  script: bundle exec appraisal rspec
3
3
  rvm:
4
4
  - 2.0.0
5
- - 2.2.0
5
+ - 2.2.2
6
+ - 2.3.3
7
+ - 2.4.0
6
8
  before_install:
7
9
  - gem install bundler
8
10
  before_script:
data/Appraisals CHANGED
@@ -1,15 +1,27 @@
1
1
  appraise 'rails_3_2' do
2
- gem 'rails', '~> 3.2.21'
3
- end if RUBY_VERSION < '2.2.0'
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', '~> 4.0.13'
7
- end
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', '~> 4.1.13'
11
- end
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', '~> 4.2.4'
15
- end
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
@@ -3,3 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'test-unit', :platform => :ruby_22
6
+ gem 'rack', '~> 1.0' if RUBY_VERSION.to_f <= 2.1
7
+ gem 'nokogiri', '~> 1.6.0' if RUBY_VERSION.to_f <= 2.0
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.7.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.
@@ -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
- validates :name, :presence => true, :uniqueness => {:case_sensitive => false}
11
+ Gutentag.tag_validations.call self
12
12
 
13
13
  before_validation :normalise_name
14
14
 
@@ -3,6 +3,8 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "test-unit", :platform => :ruby_22
6
- gem "rails", "~> 3.2.21"
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 => "../"
@@ -4,5 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "test-unit", :platform => :ruby_22
6
6
  gem "rails", "~> 4.0.13"
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 => "../"
@@ -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.13"
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 => "../"
@@ -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.4"
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 => "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "test-unit", :platform => :ruby_22
6
+ gem "rails", "~> 5.0.1"
7
+
8
+ 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.7.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.2'
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.1'
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 { |instance| Gutentag::Persistence.new(instance).persist }
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.use_transactional_fixtures = true
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.7.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: 2015-08-27 00:00:00.000000000 Z
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.2
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.2
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.1
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.1
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.4.8
175
+ rubygems_version: 2.6.8
172
176
  signing_key:
173
177
  specification_version: 4
174
178
  summary: Good Tags