gutentag 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6dfcf9cc249f5d24513e805b16a351641f06520
4
- data.tar.gz: 819247c5802512d2de7cccaea882f6faa8caa3cb
3
+ metadata.gz: e38980a4454dabe309f3c203ddd7b918f82c5193
4
+ data.tar.gz: 8b50af89daa6b099ae1cca584478758d11ab6b0c
5
5
  SHA512:
6
- metadata.gz: dd5025ccfab3083978980ea492d725235f550cec508d9a955c36ca8bb8337f44027aff7b56fc7d165b96d3fea0fb944369c54917d44ea050dcf243004748d84c
7
- data.tar.gz: '0191ae96a804109c49e990f2bde2e6192d2f0ae37f8f8bea68a12a1294e3e0ce717a179162793982a889332ef80c125bfb9955c004cc9979fc86ca4787dd578a'
6
+ metadata.gz: 31686ed82181198d188ea9e6f323b3e47e9dbb69e53d9458a2d1adbcbd75d17cc2baf6a563428caabe9dcca0552c22b1efb785e5834312baadefa59f2eeb9a4c
7
+ data.tar.gz: d9c469b2df3bc48d991700f0e062aa626efeca3c2d15fd813f0f108705ad471d4d833814fbf61af29d577a276e1936cc418746c8e37ce19e448bbfd12a51978c
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  *.lock
2
+ gemfiles
2
3
  pkg/*
3
4
  spec/internal/db/*.sqlite
5
+ .rubocop-*-yml
@@ -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
@@ -1,14 +1,15 @@
1
1
  language: ruby
2
- script: bundle exec appraisal rspec
2
+ script: bundle exec appraisal rake
3
3
  rvm:
4
- - 2.0.0
5
- - 2.2.2
6
- - 2.3.3
7
- - 2.4.0
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
- appraise 'rails_3_2' do
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 'rails_4_0' do
9
- gem 'rails', '~> 4.0.13'
10
- gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
11
- gem 'nokogiri', '~> 1.6.0', :platforms => [:ruby_20]
12
- gem 'mysql2', '~> 0.3.10'
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 'rails_4_1' do
16
- gem 'rails', '~> 4.1.16'
17
- gem 'rack', '~> 1.0', :platforms => [:ruby_20, :ruby_21]
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 'rails_4_2' do
23
- gem 'rails', '~> 4.2.7'
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 'rails_5_0' do
29
- gem 'rails', '~> 5.0.1'
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 'rails_5_1' do
33
- gem 'rails', '~> 5.1.0'
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
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
2
4
 
3
5
  gemspec
4
6
 
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
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 'combustion', '~> 0.6',
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.9.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
- require 'bundler/setup'
2
- require 'bundler/gem_tasks'
3
- require 'rspec/core/rake_task'
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 => [:test]
8
- task :test => [:spec]
11
+ task :default => %i[ test ]
12
+ task :test => %i[ rubocop spec ]
@@ -1,12 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Gutentag::Tag < ActiveRecord::Base
2
- self.table_name = 'gutentag_tags'
4
+ self.table_name = "gutentag_tags"
3
5
 
4
- has_many :taggings, :class_name => 'Gutentag::Tagging',
5
- :dependent => :destroy
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, ->{ order('gutentag_tags.taggings_count DESC') }
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 = 'gutentag_taggings'
4
+ self.table_name = "gutentag_taggings"
3
5
 
4
6
  belongs_to :taggable, :polymorphic => true
5
- belongs_to :tag, :class_name => 'Gutentag::Tag', :counter_cache => true
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 => [:taggable_id, :taggable_type]
12
+ :scope => %i[ taggable_id taggable_type ]
11
13
  }
12
14
  end
@@ -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, [:taggable_type, :taggable_id]
14
- add_index :gutentag_taggings, [:taggable_type, :taggable_id, :tag_id],
15
- :unique => true, :name => 'unique_taggings'
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,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 GutentagCacheCounter < superclass
@@ -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, :default => 0,
6
- :null => false
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, :default => 0,
11
- :null => true
13
+ change_column :gutentag_tags, :taggings_count, :integer,
14
+ :default => 0,
15
+ :null => true
12
16
  end
13
17
  end
@@ -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 = 'gutentag'
4
- s.version = '0.9.0'
5
- s.authors = ['Pat Allan']
6
- s.email = ['pat@freelancing-gods.com']
7
- s.homepage = 'https://github.com/pat/gutentag'
8
- s.summary = 'Good Tags'
9
- s.description = 'A good, simple, solid tagging extension for ActiveRecord'
10
- s.license = 'MIT'
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 = ['lib']
16
+ s.require_paths = ["lib"]
15
17
 
16
- s.add_runtime_dependency 'activerecord', '>= 3.2.0'
18
+ s.add_runtime_dependency "activerecord", ">= 3.2.0"
17
19
 
18
- s.add_development_dependency 'appraisal', '~> 2.1.0'
19
- s.add_development_dependency 'bundler', '>= 1.7.12'
20
- s.add_development_dependency 'combustion', '0.5.5'
21
- s.add_development_dependency 'mysql2'
22
- s.add_development_dependency 'pg'
23
- s.add_development_dependency 'rails'
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
@@ -1,5 +1,6 @@
1
- require 'active_record/version'
2
- require 'active_support/deprecation'
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 'gutentag/active_record'
31
- require 'gutentag/dirty'
32
- require 'gutentag/has_many_tags'
33
- require 'gutentag/persistence'
34
- require 'gutentag/tag_validations'
35
- require 'gutentag/tagged_with'
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 'gutentag/engine'
45
+ require "gutentag/engine"
45
46
  else
46
- require 'active_record'
47
- ActiveRecord::Base.extend Gutentag::HasManyTags
48
- require_relative '../app/models/gutentag/tag'
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, :class_name => 'Gutentag::Tagging',
4
- :as => :taggable, :dependent => :destroy
5
- model.has_many :tags, :class_name => 'Gutentag::Tag',
6
- :through => :taggings
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 'gutentag/active_record/class_methods'
16
- require 'gutentag/active_record/instance_methods'
20
+ require "gutentag/active_record/class_methods"
21
+ require "gutentag/active_record/instance_methods"
@@ -1,19 +1,7 @@
1
- module Gutentag::ActiveRecord::ClassMethods
2
- def tagged_with(*arguments)
3
- arguments.flatten!
1
+ # frozen_string_literal: true
4
2
 
5
- case arguments.first
6
- when Hash
7
- Gutentag::TaggedWith.call(self, arguments.first)
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