diff --git a/.travis.yml b/.travis.yml index 136344de6..a43f16be6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,10 +8,10 @@ env: - DB=mysql - DB=postgresql gemfile: - - gemfiles/rails_3.2.gemfile - - gemfiles/rails_4.0.gemfile - - gemfiles/rails_4.1.gemfile - - gemfiles/rails_edge.gemfile + - gemfiles/activerecord_3.2.gemfile + - gemfiles/activerecord_4.0.gemfile + - gemfiles/activerecord_4.1.gemfile + - gemfiles/activerecord_edge.gemfile cache: bundler script: bundle exec rake before_install: gem install bundler @@ -19,5 +19,5 @@ bundler_args: '--without local_development' matrix: fast_finish: true allow_failures: - - gemfile: gemfiles/rails_edge.gemfile - - rvm: rbx-2 + - gemfile: gemfiles/activerecord_edge.gemfile + - rvm: rbx-2 \ No newline at end of file diff --git a/Appraisals b/Appraisals index 21580dacd..05b14ca30 100644 --- a/Appraisals +++ b/Appraisals @@ -1,15 +1,20 @@ -appraise "rails-3.2" do - gem "rails", "~> 3.2" +appraise "activerecord-3.2" do + gem "activerecord", "~> 3.2" + gem "actionpack", "~> 3.2" end -appraise "rails-4.0" do - gem "rails", "~> 4.0" +appraise "activerecord-4.0" do + gem "activerecord", "~> 4.0" + gem "actionpack", "~> 4.0" end -appraise "rails-4.1" do - gem "rails", "~> 4.1.0" +appraise "activerecord-4.1" do + gem "activerecord", "~> 4.1" + gem "actionpack", "~> 4.1" end -appraise "rails-edge" do - gem "rails", github: "rails/rails" +appraise "activerecord-edge" do + gem "activerecord", github: "rails/rails" + gem "actionpack", github: "rails/rails" + gem 'arel', github: 'rails/arel' end diff --git a/UPGRADING.md b/UPGRADING.md index 76650a785..46dae2d62 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -5,3 +5,9 @@ Re-run the migrations generator rake acts_as_taggable_on_engine:install:migrations It will create any new migrations and skip existing ones + + +##Breaking changes: + + - ActsAsTaggableOn::Tag is not extend with ActsAsTaggableOn::Utils anymore. + Please use ActsAsTaggableOn::Utils instead \ No newline at end of file diff --git a/acts-as-taggable-on.gemspec b/acts-as-taggable-on.gemspec index 831ddb326..42eb3ef9e 100644 --- a/acts-as-taggable-on.gemspec +++ b/acts-as-taggable-on.gemspec @@ -23,7 +23,6 @@ Gem::Specification.new do |gem| end gem.add_runtime_dependency 'activerecord', ['>= 3', '< 5'] - gem.add_runtime_dependency 'activesupport', ['>= 3', '< 5'] gem.add_runtime_dependency 'actionpack', ['>= 3', '< 5'] gem.add_development_dependency 'sqlite3' @@ -35,4 +34,5 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'rspec' gem.add_development_dependency 'ammeter' gem.add_development_dependency 'barrier' + gem.add_development_dependency 'database_cleaner' end diff --git a/gemfiles/rails_3.2.gemfile b/gemfiles/activerecord_3.2.gemfile similarity index 77% rename from gemfiles/rails_3.2.gemfile rename to gemfiles/activerecord_3.2.gemfile index 259c3b5df..97df1f46d 100644 --- a/gemfiles/rails_3.2.gemfile +++ b/gemfiles/activerecord_3.2.gemfile @@ -2,7 +2,8 @@ source "https://rubygems.org" -gem "rails", "~> 3.2" +gem "activerecord", "~> 3.2" +gem "actionpack", "~> 3.2" group :local_development do gem "guard" diff --git a/gemfiles/rails_4.0.gemfile b/gemfiles/activerecord_4.0.gemfile similarity index 77% rename from gemfiles/rails_4.0.gemfile rename to gemfiles/activerecord_4.0.gemfile index fe5f83dc6..831383358 100644 --- a/gemfiles/rails_4.0.gemfile +++ b/gemfiles/activerecord_4.0.gemfile @@ -2,7 +2,8 @@ source "https://rubygems.org" -gem "rails", "~> 4.0" +gem "activerecord", "~> 4.0" +gem "actionpack", "~> 4.0" group :local_development do gem "guard" diff --git a/gemfiles/rails_4.1.gemfile b/gemfiles/activerecord_4.1.gemfile similarity index 77% rename from gemfiles/rails_4.1.gemfile rename to gemfiles/activerecord_4.1.gemfile index 0deee3d29..2fa4abdd8 100644 --- a/gemfiles/rails_4.1.gemfile +++ b/gemfiles/activerecord_4.1.gemfile @@ -2,7 +2,8 @@ source "https://rubygems.org" -gem "rails", "~> 4.1.0" +gem "activerecord", "~> 4.1" +gem "actionpack", "~> 4.1" group :local_development do gem "guard" diff --git a/gemfiles/rails_edge.gemfile b/gemfiles/activerecord_edge.gemfile similarity index 60% rename from gemfiles/rails_edge.gemfile rename to gemfiles/activerecord_edge.gemfile index cba3e46fb..490225b50 100644 --- a/gemfiles/rails_edge.gemfile +++ b/gemfiles/activerecord_edge.gemfile @@ -2,7 +2,9 @@ source "https://rubygems.org" -gem "rails", :github => "rails/rails" +gem "activerecord", :github => "rails/rails" +gem "actionpack", :github => "rails/rails" +gem "arel", :github => "rails/arel" group :local_development do gem "guard" diff --git a/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb b/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb index 4074e8753..be7336afd 100644 --- a/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb +++ b/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb @@ -131,7 +131,7 @@ def safe_to_sql(relation) def generate_tagging_scope_in_clause(tagging_scope, table_name, primary_key) table_name_pkey = "#{table_name}.#{primary_key}" - if ActsAsTaggableOn::Tag.using_mysql? + if ActsAsTaggableOn::Utils.using_mysql? # See https://github.com/mbleigh/acts-as-taggable-on/pull/457 for details scoped_ids = select(table_name_pkey).map(&:id) tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN (?)", scoped_ids) @@ -139,7 +139,7 @@ def generate_tagging_scope_in_clause(tagging_scope, table_name, primary_key) tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{safe_to_sql(select(table_name_pkey))})") end - return tagging_scope + tagging_scope end def tagging_conditions(options) diff --git a/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb b/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb index fc897c8fc..508993bff 100644 --- a/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb +++ b/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb @@ -24,16 +24,16 @@ def initialize_acts_as_taggable_on_core # when preserving tag order, include order option so that for a 'tags' context # the associations tag_taggings & tags are always returned in created order has_many_with_taggable_compatibility context_taggings, as: :taggable, - dependent: :destroy, - class_name: 'ActsAsTaggableOn::Tagging', - order: taggings_order, - conditions: ["#{ActsAsTaggableOn::Tagging.table_name}.context = (?)", tags_type], - include: :tag + dependent: :destroy, + class_name: 'ActsAsTaggableOn::Tagging', + order: taggings_order, + conditions: ["#{ActsAsTaggableOn::Tagging.table_name}.context = (?)", tags_type], + include: :tag has_many_with_taggable_compatibility context_tags, through: context_taggings, - source: :tag, - class_name: 'ActsAsTaggableOn::Tag', - order: taggings_order + source: :tag, + class_name: 'ActsAsTaggableOn::Tag', + order: taggings_order end @@ -96,13 +96,13 @@ def tagged_with(tags, options = {}) context = options.delete(:on) owned_by = options.delete(:owned_by) alias_base_name = undecorated_table_name.gsub('.', '_') - quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : '' + quote = ActsAsTaggableOn::Utils.using_postgresql? ? '"' : '' if options.delete(:exclude) if options.delete(:wild) - tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(' OR ') + tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{ActsAsTaggableOn::Utils.like_operator} ? ESCAPE '!'", "%#{ActsAsTaggableOn::Utils.escape_like(t)}%"]) }.join(' OR ') else - tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(' OR ') + tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{ActsAsTaggableOn::Utils.like_operator} ?", t]) }.join(' OR ') end conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name, nil)})" @@ -183,7 +183,7 @@ def tagged_with(tags, options = {}) group ||= [] # Rails interprets this as a no-op in the group() call below if options.delete(:order_by_matching_tag_count) select_clause = "#{table_name}.*, COUNT(#{taggings_alias}.tag_id) AS #{taggings_alias}_count" - group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" + group_columns = ActsAsTaggableOn::Utils.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" group = group_columns order_by << "#{taggings_alias}_count DESC" @@ -195,7 +195,7 @@ def tagged_with(tags, options = {}) joins << ' AND ' + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context - group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" + group_columns = ActsAsTaggableOn::Utils.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}" group = group_columns having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}" end @@ -284,7 +284,7 @@ def all_tags_on(context) opts = ["#{tagging_table_name}.context = ?", context.to_s] scope = base_tags.where(opts) - if ActsAsTaggableOn::Tag.using_postgresql? + if ActsAsTaggableOn::Utils.using_postgresql? group_columns = grouped_column_names_for(ActsAsTaggableOn::Tag) scope.order("max(#{tagging_table_name}.created_at)").group(group_columns) else @@ -415,9 +415,8 @@ def save_tags # # @param [Array] tag_list Tags to find or create # @param [Symbol] context The tag context for the tag_list - def find_or_create_tags_from_list_with_context(tag_list, context) + def find_or_create_tags_from_list_with_context(tag_list, _context) load_tags(tag_list) end end end - diff --git a/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb b/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb index 8c3555888..003ff1f66 100644 --- a/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb +++ b/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb @@ -53,7 +53,7 @@ def exclude_self(klass, id) end def group_columns(klass) - if ActsAsTaggableOn::Tag.using_postgresql? + if ActsAsTaggableOn::Utils.using_postgresql? grouped_column_names_for(klass) else "#{klass.table_name}.#{klass.primary_key}" diff --git a/lib/acts_as_taggable_on/tag.rb b/lib/acts_as_taggable_on/tag.rb index 2cbfe3328..7546a9e95 100644 --- a/lib/acts_as_taggable_on/tag.rb +++ b/lib/acts_as_taggable_on/tag.rb @@ -1,7 +1,6 @@ # coding: utf-8 module ActsAsTaggableOn class Tag < ::ActiveRecord::Base - extend ActsAsTaggableOn::Utils attr_accessible :name if defined?(ActiveModel::MassAssignmentSecurity) @@ -45,13 +44,13 @@ def self.named_any(list) end def self.named_like(name) - clause = ["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(name)}%"] + clause = ["name #{ActsAsTaggableOn::Utils.like_operator} ? ESCAPE '!'", "%#{ActsAsTaggableOn::Utils.escape_like(name)}%"] where(clause) end def self.named_like_any(list) clause = list.map { |tag| - sanitize_sql(["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(tag.to_s)}%"]) + sanitize_sql(["name #{ActsAsTaggableOn::Utils.like_operator} ? ESCAPE '!'", "%#{ActsAsTaggableOn::Utils.escape_like(tag.to_s)}%"]) }.join(' OR ') where(clause) end @@ -113,7 +112,7 @@ def comparable_name(str) end def binary - using_mysql? ? 'BINARY ' : nil + ActsAsTaggableOn::Utils.using_mysql? ? 'BINARY ' : nil end def unicode_downcase(string) diff --git a/lib/acts_as_taggable_on/taggable.rb b/lib/acts_as_taggable_on/taggable.rb index a53d14f46..15debebe6 100644 --- a/lib/acts_as_taggable_on/taggable.rb +++ b/lib/acts_as_taggable_on/taggable.rb @@ -58,9 +58,9 @@ def acts_as_ordered_taggable_on(*tag_types) # Make a model taggable on specified contexts # and optionally preserves the order in which tags are created # - # Seperate methods used above for backwards compatibility + # Separate methods used above for backwards compatibility # so that the original acts_as_taggable_on method is unaffected - # as it's not possible to add another arguement to the method + # as it's not possible to add another argument to the method # without the tag_types being enclosed in square brackets # # NB: method overridden in core module in order to create tag type diff --git a/lib/acts_as_taggable_on/tagger.rb b/lib/acts_as_taggable_on/tagger.rb index 2be8bb027..a00e8f886 100644 --- a/lib/acts_as_taggable_on/tagger.rb +++ b/lib/acts_as_taggable_on/tagger.rb @@ -16,26 +16,30 @@ module ClassMethods def acts_as_tagger(opts={}) class_eval do has_many_with_taggable_compatibility :owned_taggings, - opts.merge( - as: :tagger, - dependent: :destroy, - class_name: 'ActsAsTaggableOn::Tagging' - ) + opts.merge( + as: :tagger, + dependent: :destroy, + class_name: 'ActsAsTaggableOn::Tagging' + ) has_many_with_taggable_compatibility :owned_tags, - through: :owned_taggings, - source: :tag, - class_name: 'ActsAsTaggableOn::Tag', - uniq: true + through: :owned_taggings, + source: :tag, + class_name: 'ActsAsTaggableOn::Tag', + uniq: true end include ActsAsTaggableOn::Tagger::InstanceMethods extend ActsAsTaggableOn::Tagger::SingletonMethods end - def is_tagger? + def tagger? false end + + def is_tagger? + tagger? + end end module InstanceMethods @@ -54,23 +58,31 @@ def tag(taggable, opts={}) skip_save = opts.delete(:skip_save) return false unless taggable.respond_to?(:is_taggable?) && taggable.is_taggable? - fail 'You need to specify a tag context using :on' unless opts.key?(:on) - fail 'You need to specify some tags using :with' unless opts.key?(:with) + fail 'You need to specify a tag context using :on' unless opts.key?(:on) + fail 'You need to specify some tags using :with' unless opts.key?(:with) fail "No context :#{opts[:on]} defined in #{taggable.class}" unless opts[:force] || taggable.tag_types.include?(opts[:on]) taggable.set_owner_tag_list_on(self, opts[:on].to_s, opts[:with]) taggable.save unless skip_save end - def is_tagger? + def tagger? self.class.is_tagger? end + + def is_tagger? + tagger? + end end module SingletonMethods - def is_tagger? + def tagger? true end + + def is_tagger? + tagger? + end end end end diff --git a/lib/acts_as_taggable_on/utils.rb b/lib/acts_as_taggable_on/utils.rb index 79b79c4cf..0b251c249 100644 --- a/lib/acts_as_taggable_on/utils.rb +++ b/lib/acts_as_taggable_on/utils.rb @@ -2,14 +2,25 @@ module ActsAsTaggableOn module Utils extend self + # Use ActsAsTaggableOn::Tag connection def connection - ::ActiveRecord::Base.connection + ActsAsTaggableOn::Tag.connection end def using_postgresql? connection && connection.adapter_name == 'PostgreSQL' end + def postgresql_version + if using_postgresql? + connection.execute("SHOW SERVER_VERSION").first["server_version"].to_f + end + end + + def postgresql_support_json? + postgresql_version >= 9.2 + end + def using_sqlite? connection && connection.adapter_name == 'SQLite' end @@ -20,7 +31,7 @@ def using_mysql? end def using_case_insensitive_collation? - using_mysql? && ::ActiveRecord::Base.connection.collation =~ /_ci\Z/ + using_mysql? && connection.collation =~ /_ci\Z/ end def supports_concurrency? @@ -32,15 +43,13 @@ def sha_prefix(string) end def active_record4? - ::ActiveRecord::VERSION::MAJOR == 4 + ::ActiveRecord::VERSION::MAJOR == 4 end def active_record42? - active_record4? && ::ActiveRecord::VERSION::MINOR >= 2 + active_record4? && ::ActiveRecord::VERSION::MINOR >= 2 end - private - def like_operator using_postgresql? ? 'ILIKE' : 'LIKE' end diff --git a/lib/acts_as_taggable_on/version.rb b/lib/acts_as_taggable_on/version.rb index b3f0f1d48..eedc838d6 100644 --- a/lib/acts_as_taggable_on/version.rb +++ b/lib/acts_as_taggable_on/version.rb @@ -1,4 +1,4 @@ module ActsAsTaggableOn - VERSION = '3.2.0' + VERSION = '3.2.1' end diff --git a/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb b/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb index 516019447..0463c6442 100644 --- a/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb +++ b/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb @@ -2,9 +2,6 @@ require 'spec_helper' describe 'Acts As Taggable On' do - before(:each) do - clean_database! - end it "should provide a class method 'taggable?' that is false for untaggable models" do expect(UntaggableModel).to_not be_taggable @@ -12,7 +9,6 @@ describe 'Taggable Method Generation To Preserve Order' do before(:each) do - clean_database! TaggableModel.tag_types = [] TaggableModel.preserve_tag_order = false TaggableModel.acts_as_ordered_taggable_on(:ordered_tags) @@ -26,7 +22,6 @@ describe 'Taggable Method Generation' do before(:each) do - clean_database! TaggableModel.tag_types = [] TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings) @taggable = TaggableModel.new(name: 'Bob Jones') diff --git a/spec/acts_as_taggable_on/acts_as_tagger_spec.rb b/spec/acts_as_taggable_on/acts_as_tagger_spec.rb index 817401598..5d4ad2eae 100644 --- a/spec/acts_as_taggable_on/acts_as_tagger_spec.rb +++ b/spec/acts_as_taggable_on/acts_as_tagger_spec.rb @@ -1,9 +1,6 @@ require 'spec_helper' describe 'acts_as_tagger' do - before(:each) do - clean_database! - end describe 'Tagger Method Generation' do before(:each) do diff --git a/spec/acts_as_taggable_on/caching_spec.rb b/spec/acts_as_taggable_on/caching_spec.rb index 7c9bbaa30..71908a7ef 100644 --- a/spec/acts_as_taggable_on/caching_spec.rb +++ b/spec/acts_as_taggable_on/caching_spec.rb @@ -2,10 +2,6 @@ describe 'Acts As Taggable On' do - before(:each) do - clean_database! - end - describe 'Caching' do before(:each) do @taggable = CachedModel.new(name: 'Bob Jones') @@ -74,4 +70,7 @@ end end + describe 'CachingWithArray' do + pending '#TODO' + end end diff --git a/spec/acts_as_taggable_on/related_spec.rb b/spec/acts_as_taggable_on/related_spec.rb index 1bc93a4c6..af6530631 100644 --- a/spec/acts_as_taggable_on/related_spec.rb +++ b/spec/acts_as_taggable_on/related_spec.rb @@ -1,9 +1,6 @@ require 'spec_helper' describe 'Acts As Taggable On' do - before(:each) do - clean_database! - end describe 'Related Objects' do diff --git a/spec/acts_as_taggable_on/single_table_inheritance_spec.rb b/spec/acts_as_taggable_on/single_table_inheritance_spec.rb index 68102eef0..2d3993bb2 100644 --- a/spec/acts_as_taggable_on/single_table_inheritance_spec.rb +++ b/spec/acts_as_taggable_on/single_table_inheritance_spec.rb @@ -1,11 +1,6 @@ require 'spec_helper' describe 'Single Table Inheritance' do - - before(:each) do - clean_database! - end - let(:taggable) { TaggableModel.new(name: 'taggable model') } let(:inheriting_model) { InheritingTaggableModel.new(name: 'Inheriting Taggable Model') } diff --git a/spec/acts_as_taggable_on/tag_spec.rb b/spec/acts_as_taggable_on/tag_spec.rb index 0d011e75e..4c82d1d0b 100644 --- a/spec/acts_as_taggable_on/tag_spec.rb +++ b/spec/acts_as_taggable_on/tag_spec.rb @@ -9,14 +9,15 @@ describe ActsAsTaggableOn::Tag do before(:each) do - clean_database! @tag = ActsAsTaggableOn::Tag.new @user = TaggableModel.create(name: 'Pablo') end + + describe 'named like any' do context 'case insensitive collation and unique index on tag name' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? before(:each) do ActsAsTaggableOn::Tag.create(name: 'Awesome') ActsAsTaggableOn::Tag.create(name: 'epic') @@ -29,7 +30,7 @@ end context 'case insensitive collation without indexes or case sensitive collation with indexes' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? include_context 'without unique index' end @@ -66,7 +67,7 @@ end end - unless ActsAsTaggableOn::Tag.using_sqlite? + unless ActsAsTaggableOn::Utils.using_sqlite? describe 'find or create by unicode name' do before(:each) do @tag.name = 'привет' @@ -81,7 +82,7 @@ expect(ActsAsTaggableOn::Tag.find_or_create_with_like_by_name('ПРИВЕТ')).to eq(@tag) end - if ActsAsTaggableOn::Tag.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? it 'should find by name accent insensitive' do @tag.name = 'inupiat' @tag.save @@ -106,7 +107,7 @@ end context 'case sensitive' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? include_context 'without unique index' end @@ -125,7 +126,7 @@ end context 'case sensitive' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? include_context 'without unique index' end @@ -225,7 +226,7 @@ end context 'case sensitive' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? include_context 'without unique index' end @@ -239,7 +240,7 @@ end context 'case sensitive' do - if described_class.using_case_insensitive_collation? + if ActsAsTaggableOn::Utils.using_case_insensitive_collation? include_context 'without unique index' end diff --git a/spec/acts_as_taggable_on/taggable_spec.rb b/spec/acts_as_taggable_on/taggable_spec.rb index af30d2d98..5397c6f33 100644 --- a/spec/acts_as_taggable_on/taggable_spec.rb +++ b/spec/acts_as_taggable_on/taggable_spec.rb @@ -3,17 +3,9 @@ describe 'Taggable To Preserve Order' do before(:each) do - clean_database! @taggable = OrderedTaggableModel.new(name: 'Bob Jones') end - it 'should have tag types' do - [:tags, :colours].each do |type| - expect(OrderedTaggableModel.tag_types).to include type - end - - expect(@taggable.tag_types).to eq(OrderedTaggableModel.tag_types) - end it 'should have tag associations' do [:tags, :colours].each do |type| @@ -105,7 +97,6 @@ describe 'Taggable' do before(:each) do - clean_database! @taggable = TaggableModel.new(name: 'Bob Jones') @taggables = [@taggable, TaggableModel.new(name: 'John Doe')] end @@ -264,7 +255,7 @@ expect(TaggableModel.select('distinct(taggable_models.id), taggable_models.*').joins(:untaggable_models).tagged_with(['rails', 'ruby'], :any => false).to_a.sort).to eq([bob, frank].sort) end - unless ActsAsTaggableOn::Tag.using_sqlite? + unless ActsAsTaggableOn::Utils.using_sqlite? it 'should not care about case for unicode names' do ActsAsTaggableOn.strict_case_match = false TaggableModel.create(name: 'Anya', tag_list: 'ПРИВЕТ') @@ -645,7 +636,6 @@ describe 'NonStandardIdTaggable' do before(:each) do - clean_database! @taggable = NonStandardIdTaggableModel.new(name: 'Bob Jones') @taggables = [@taggable, NonStandardIdTaggableModel.new(name: 'John Doe')] end @@ -820,7 +810,6 @@ # See https://github.com/mbleigh/acts-as-taggable-on/pull/457 for details context 'tag_counts and aggreating scopes, compatability with MySQL ' do before(:each) do - clean_database! TaggableModel.new(:name => 'Barb Jones').tap { |t| t.tag_list = %w(awesome fun) }.save TaggableModel.new(:name => 'John Doe').tap { |t| t.tag_list = %w(cool fun hella) }.save TaggableModel.new(:name => 'Jo Doe').tap { |t| t.tag_list = %w(curious young naive sharp) }.save @@ -859,10 +848,9 @@ end -if ActsAsTaggableOn::Tag.using_postgresql? +if ActsAsTaggableOn::Utils.using_postgresql? describe 'Taggable model with json columns' do before(:each) do - clean_database! @taggable = TaggableModelWithJson.new(:name => 'Bob Jones') @taggables = [@taggable, TaggableModelWithJson.new(:name => 'John Doe')] end diff --git a/spec/acts_as_taggable_on/tagger_spec.rb b/spec/acts_as_taggable_on/tagger_spec.rb index 957298e63..b57d635ba 100644 --- a/spec/acts_as_taggable_on/tagger_spec.rb +++ b/spec/acts_as_taggable_on/tagger_spec.rb @@ -2,11 +2,12 @@ describe 'Tagger' do before(:each) do - clean_database! @user = User.create @taggable = TaggableModel.create(name: 'Bob Jones') end + + it 'should have taggings' do @user.tag(@taggable, with: 'ruby,scheme', on: :tags) expect(@user.owned_taggings.size).to eq(2) diff --git a/spec/acts_as_taggable_on/tagging_spec.rb b/spec/acts_as_taggable_on/tagging_spec.rb index efe83c2fa..6b3c7e5b1 100644 --- a/spec/acts_as_taggable_on/tagging_spec.rb +++ b/spec/acts_as_taggable_on/tagging_spec.rb @@ -2,7 +2,6 @@ describe ActsAsTaggableOn::Tagging do before(:each) do - clean_database! @tagging = ActsAsTaggableOn::Tagging.new end diff --git a/spec/acts_as_taggable_on/tags_helper_spec.rb b/spec/acts_as_taggable_on/tags_helper_spec.rb index cc3b2a6b4..1fd8bd718 100644 --- a/spec/acts_as_taggable_on/tags_helper_spec.rb +++ b/spec/acts_as_taggable_on/tags_helper_spec.rb @@ -2,8 +2,6 @@ describe ActsAsTaggableOn::TagsHelper do before(:each) do - clean_database! - @bob = TaggableModel.create(name: 'Bob Jones', language_list: 'ruby, php') @tom = TaggableModel.create(name: 'Tom Marley', language_list: 'ruby, java') @eve = TaggableModel.create(name: 'Eve Nodd', language_list: 'ruby, c++') @@ -14,6 +12,7 @@ class Helper end.new end + it 'should yield the proper css classes' do tags = {} diff --git a/spec/acts_as_taggable_on/utils_spec.rb b/spec/acts_as_taggable_on/utils_spec.rb index d66729b15..71e74c8ca 100644 --- a/spec/acts_as_taggable_on/utils_spec.rb +++ b/spec/acts_as_taggable_on/utils_spec.rb @@ -3,11 +3,11 @@ describe ActsAsTaggableOn::Utils do describe 'like_operator' do before(:each) do - clean_database! TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings) @taggable = TaggableModel.new(name: 'Bob Jones') end + it 'should return \'ILIKE\' when the adapter is PostgreSQL' do allow(TaggableModel.connection).to receive(:adapter_name) { 'PostgreSQL' } expect(TaggableModel.send(:like_operator)).to eq('ILIKE') diff --git a/spec/internal/app/models/cached_model_with_array.rb b/spec/internal/app/models/cached_model_with_array.rb new file mode 100644 index 000000000..c19e1dd5b --- /dev/null +++ b/spec/internal/app/models/cached_model_with_array.rb @@ -0,0 +1,5 @@ +if ActsAsTaggableOn::Utils.using_postgresql? + class CachedModelWithArray < ActiveRecord::Base + acts_as_taggable + end +end diff --git a/spec/internal/app/models/models.rb b/spec/internal/app/models/models.rb index 0171e7f4b..d28b1f24d 100644 --- a/spec/internal/app/models/models.rb +++ b/spec/internal/app/models/models.rb @@ -6,6 +6,7 @@ class TaggableModel < ActiveRecord::Base has_many :untaggable_models attr_reader :tag_list_submethod_called + def tag_list=(v) @tag_list_submethod_called = true super @@ -76,7 +77,14 @@ class OrderedTaggableModel < ActiveRecord::Base acts_as_ordered_taggable_on :colours end -class TaggableModelWithJson < ActiveRecord::Base - acts_as_taggable - acts_as_taggable_on :skills +if ActsAsTaggableOn::Utils.using_postgresql? + class CachedModelWithArray < ActiveRecord::Base + acts_as_taggable + end + if ActsAsTaggableOn::Utils.postgresql_support_json? + class TaggableModelWithJson < ActiveRecord::Base + acts_as_taggable + acts_as_taggable_on :skills + end + end end diff --git a/spec/internal/db/schema.rb b/spec/internal/db/schema.rb index 05c310417..6a0a61757 100644 --- a/spec/internal/db/schema.rb +++ b/spec/internal/db/schema.rb @@ -74,14 +74,24 @@ t.column :type, :string end - create_table :taggable_model_with_jsons, :force => true do |t| - t.column :name, :string - t.column :type, :string - if self.connection.adapter_name == 'PostgreSQL' && self.connection.execute("SHOW SERVER_VERSION").first["server_version"].to_f >= 9.2 - type = :json - else - type = :string + + # Special cases for postgresql + if ActsAsTaggableOn::Utils.using_postgresql? + + create_table :other_cached_with_array_models, force: true do |t| + t.column :name, :string + t.column :type, :string + t.column :cached_language_list, :string, array: true + t.column :cached_status_list, :string, array: true + t.column :cached_glass_list, :string, array: true + end + + if self. + create_table :taggable_model_with_jsons, :force => true do |t| + t.column :name, :string + t.column :type, :string + t.column :opts, :json + end end - t.column :opts, type end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 94f1fc897..813f82140 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,96 +6,13 @@ I18n.enforce_available_locales = true require 'rails' require 'rspec/its' -require 'ammeter/init' +require 'ammeter/init' # <= You are next require 'barrier' +require 'database_cleaner' -unless [].respond_to?(:freq) - class Array - def freq - k=Hash.new(0) - each { |e| k[e]+=1 } - k - end - end -end - -def init_logger - ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log')) - ActiveRecord::Migration.verbose = false -end - -def logger_on - ActiveRecord::Base.logger.level = ENV['TRAVIS']? ::Logger::ERROR : ::Logger::DEBUG -end - -def logger_off - ActiveRecord::Base.logger.level = ::Logger::UNKNOWN -end - -# set adapter to use, default is sqlite3 -# to use an alternative adapter run => rake spec DB='postgresql' -db_name = ENV['DB'] || 'sqlite3' -database_yml = File.expand_path('../internal/config/database.yml', __FILE__) - -if File.exist?(database_yml) - active_record_configuration = YAML.load_file(database_yml) - - ActiveRecord::Base.configurations = active_record_configuration - config = ActiveRecord::Base.configurations[db_name] - - begin - #activerecord 4 uses symbol - #TODO, remove when activerecord 3 support is dropped - if ActsAsTaggableOn::Utils.active_record4? - ActiveRecord::Base.establish_connection(db_name.to_sym) - else - ActiveRecord::Base.establish_connection(db_name) - end - ActiveRecord::Base.connection - rescue - case db_name - when /mysql/ - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], {charset: 'utf8', collation: 'utf8_unicode_ci'}) - when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8')) - end - - ActiveRecord::Base.establish_connection(config) - end - - init_logger - ActiveRecord::Base.default_timezone = :utc - - begin - logger_off - load(File.dirname(__FILE__) + '/internal/db/schema.rb') - load(File.dirname(__FILE__) + '/internal/app/models/models.rb') - ensure - logger_on - end - -else - fail "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample" -end +Dir['./spec/support/**/*.rb'].sort.each { |f| require f } RSpec.configure do |config| config.raise_errors_for_deprecations! end -def clean_database! - models = [ActsAsTaggableOn::Tag, ActsAsTaggableOn::Tagging, TaggableModel, OtherTaggableModel, - InheritingTaggableModel, AlteredInheritingTaggableModel, User, UntaggableModel, - OrderedTaggableModel, TaggableModelWithJson] - models.each do |model| - #Sqlite don't support truncate - if ActsAsTaggableOn::Utils.using_sqlite? - ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}" - else - ActiveRecord::Base.connection.execute "TRUNCATE #{model.table_name}" - end - end -end - -clean_database! diff --git a/spec/support/database.rb b/spec/support/database.rb index e42c93362..49d1bb935 100644 --- a/spec/support/database.rb +++ b/spec/support/database.rb @@ -1,34 +1,42 @@ # set adapter to use, default is sqlite3 # to use an alternative adapter run => rake spec DB='postgresql' db_name = ENV['DB'] || 'sqlite3' -database_yml = File.expand_path('../../database.yml', __FILE__) - -raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample" unless File.exists?(database_yml) - -ActiveRecord::Migration.verbose = false -ActiveRecord::Base.default_timezone = :utc -ActiveRecord::Base.configurations = YAML.load_file(database_yml) -ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), '../debug.log')) - -config = ActiveRecord::Base.configurations[db_name] - -begin - ActiveRecord::Base.establish_connection(db_name) - ActiveRecord::Base.connection -rescue - case db_name - when /mysql/ - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], {:charset => 'utf8', :collation => 'utf8_unicode_ci'}) - else #assume postgresql - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8')) +database_yml = File.expand_path('../../internal/config/database.yml', __FILE__) + +if File.exist?(database_yml) + + ActiveRecord::Migration.verbose = false + ActiveRecord::Base.default_timezone = :utc + ActiveRecord::Base.configurations = YAML.load_file(database_yml) + ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), '../debug.log')) + ActiveRecord::Base.logger.level = ENV['TRAVIS'] ? ::Logger::ERROR : ::Logger::DEBUG + config = ActiveRecord::Base.configurations[db_name] + + begin + #activerecord 4 uses symbol + #TODO, remove when activerecord 3 support is dropped + if ActsAsTaggableOn::Utils.active_record4? + ActiveRecord::Base.establish_connection(db_name.to_sym) + else + ActiveRecord::Base.establish_connection(db_name) + end + ActiveRecord::Base.connection + rescue + case db_name + when /mysql/ + ActiveRecord::Base.establish_connection(config.merge('database' => nil)) + ActiveRecord::Base.connection.create_database(config['database'], {charset: 'utf8', collation: 'utf8_unicode_ci'}) + when 'postgresql' + ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) + ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8')) + end + + ActiveRecord::Base.establish_connection(config) end - ActiveRecord::Base.establish_connection(config) -end - - -load(File.dirname(__FILE__) + '/../schema.rb') -load(File.dirname(__FILE__) + '/../models.rb') + load(File.dirname(__FILE__) + '/../internal/db/schema.rb') + load(File.dirname(__FILE__) + '/../internal/app/models/models.rb') +else + fail "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample" +end \ No newline at end of file diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb index f8599e6f6..fd3030297 100644 --- a/spec/support/database_cleaner.rb +++ b/spec/support/database_cleaner.rb @@ -1,11 +1,17 @@ -#TODO replace with database_cleaner gem +RSpec.configure do |config| -def clean_database! - models = [ActsAsTaggableOn::Tag, ActsAsTaggableOn::Tagging, TaggableModel, OtherTaggableModel, InheritingTaggableModel, - AlteredInheritingTaggableModel, User, UntaggableModel, OrderedTaggableModel] - models.each do |model| - ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}" + config.before(:suite) do + DatabaseCleaner.clean_with(:truncation) + DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean + end + + config.before(:each) do + DatabaseCleaner.start end -end -clean_database! + config.after(:each) do + DatabaseCleaner.clean + end + +end