acts-as-taggable-on 1.0.13 → 1.0.19

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.
data/README.rdoc CHANGED
@@ -151,6 +151,12 @@ A helper is included to assist with generating tag clouds.
151
151
 
152
152
  Here is an example that generates a tag cloud.
153
153
 
154
+ Helper:
155
+
156
+ module PostsHelper
157
+ include TagsHelper
158
+ end
159
+
154
160
  Controller:
155
161
 
156
162
  class PostController < ApplicationController
@@ -160,7 +166,8 @@ Controller:
160
166
  end
161
167
 
162
168
  View:
163
- <% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %>
169
+
170
+ <% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
164
171
  <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
165
172
  <% end %>
166
173
 
@@ -187,5 +194,6 @@ CSS:
187
194
  * slainer68 - STI fix
188
195
  * harrylove - migration instructions and fix-ups
189
196
  * lawrencepit - cached tag work
197
+ * sobrinho - fixed tag_cloud helper
190
198
 
191
199
  Copyright (c) 2007-2009 Michael Bleigh (http://mbleigh.com/) and Intridea Inc. (http://intridea.com/), released under the MIT license
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ begin
9
9
  gemspec.email = "michael@intridea.com"
10
10
  gemspec.homepage = "http://github.com/mbleigh/acts-as-taggable-on"
11
11
  gemspec.authors = ["Michael Bleigh"]
12
- gemspec.files = FileList["[A-Z]*", "{lib,spec,rails}/**/*"] - FileList["**/*.log"]
12
+ gemspec.files = FileList["[A-Z]*", "{generators,lib,spec,rails}/**/*"] - FileList["**/*.log"]
13
13
  end
14
14
  Jeweler::GemcutterTasks.new
15
15
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.13
1
+ 1.0.19
@@ -0,0 +1,7 @@
1
+ class ActsAsTaggableOnMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "acts_as_taggable_on_migration"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ class ActsAsTaggableOnMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :tags do |t|
4
+ t.column :name, :string
5
+ end
6
+
7
+ create_table :taggings do |t|
8
+ t.column :tag_id, :integer
9
+ t.column :taggable_id, :integer
10
+ t.column :tagger_id, :integer
11
+ t.column :tagger_type, :string
12
+
13
+ # You should make sure that the column created is
14
+ # long enough to store the required class names.
15
+ t.column :taggable_type, :string
16
+ t.column :context, :string
17
+
18
+ t.column :created_at, :datetime
19
+ end
20
+
21
+ add_index :taggings, :tag_id
22
+ add_index :taggings, [:taggable_id, :taggable_type, :context]
23
+ end
24
+
25
+ def self.down
26
+ drop_table :taggings
27
+ drop_table :tags
28
+ end
29
+ end
@@ -19,15 +19,15 @@ module ActiveRecord
19
19
  args.compact! if args
20
20
  for tag_type in args
21
21
  tag_type = tag_type.to_s
22
- # use aliased_join_table_name for context condition so that sphix can join multiple
22
+ # use aliased_join_table_name for context condition so that sphinx can join multiple
23
23
  # tag references from same model without getting an ambiguous column error
24
- self.class_eval do
24
+ class_eval do
25
25
  has_many "#{tag_type.singularize}_taggings".to_sym, :as => :taggable, :dependent => :destroy,
26
- :include => :tag, :conditions => ['#{aliased_join_table_name rescue "taggings"}.context = ?',tag_type], :class_name => "Tagging"
26
+ :include => :tag, :conditions => ['#{aliased_join_table_name || Tagging.table_name rescue Tagging.table_name}.context = ?',tag_type], :class_name => "Tagging"
27
27
  has_many "#{tag_type}".to_sym, :through => "#{tag_type.singularize}_taggings".to_sym, :source => :tag
28
28
  end
29
29
 
30
- self.class_eval <<-RUBY
30
+ class_eval <<-RUBY
31
31
  def self.taggable?
32
32
  true
33
33
  end
@@ -86,7 +86,7 @@ module ActiveRecord
86
86
  if respond_to?(:tag_types)
87
87
  write_inheritable_attribute( :tag_types, (tag_types + args).uniq )
88
88
  else
89
- self.class_eval do
89
+ class_eval do
90
90
  write_inheritable_attribute(:tag_types, args.uniq)
91
91
  class_inheritable_reader :tag_types
92
92
 
@@ -117,6 +117,7 @@ module ActiveRecord
117
117
  # Pass either a tag string, or an array of strings or tags
118
118
  #
119
119
  # Options:
120
+ # :any - find models that match any of the given tags
120
121
  # :exclude - Find models that are not tagged with the given tags
121
122
  # :match_all - Find models that match all of the given tags, not just one
122
123
  # :conditions - A piece of SQL conditions to add to the query
@@ -139,9 +140,9 @@ module ActiveRecord
139
140
  end
140
141
 
141
142
  def find_options_for_find_tagged_with(tags, options = {})
142
- tags = TagList.from(tags)
143
+ tag_list = TagList.from(tags)
143
144
 
144
- return {} if tags.empty?
145
+ return {} if tag_list.empty?
145
146
 
146
147
  joins = []
147
148
  conditions = []
@@ -150,28 +151,30 @@ module ActiveRecord
150
151
 
151
152
 
152
153
  if options.delete(:exclude)
153
- tags_conditions = tags.map { |t| sanitize_sql(["#{Tag.table_name}.name LIKE ?", t]) }.join(" OR ")
154
+ tags_conditions = tag_list.map { |t| sanitize_sql(["#{Tag.table_name}.name LIKE ?", t]) }.join(" OR ")
154
155
  conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{Tagging.table_name}.taggable_id FROM #{Tagging.table_name} JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND (#{tags_conditions}) WHERE #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})"
155
156
 
157
+ elsif options.delete(:any)
158
+ tags_conditions = tag_list.map { |t| sanitize_sql(["#{Tag.table_name}.name LIKE ?", t]) }.join(" OR ")
159
+ conditions << "#{table_name}.#{primary_key} IN (SELECT #{Tagging.table_name}.taggable_id FROM #{Tagging.table_name} JOIN #{Tag.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id AND (#{tags_conditions}) WHERE #{Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})"
160
+
156
161
  else
162
+ tags = Tag.named_like_any(tag_list)
163
+ return { :conditions => "1 = 0" } unless tags.length == tag_list.length
164
+
157
165
  tags.each do |tag|
158
- safe_tag = tag.gsub(/[^a-zA-Z0-9]/, '')
166
+ safe_tag = tag.name.gsub(/[^a-zA-Z0-9]/, '')
159
167
  prefix = "#{safe_tag}_#{rand(1024)}"
160
168
 
161
169
  taggings_alias = "#{table_name}_taggings_#{prefix}"
162
- tags_alias = "#{table_name}_tags_#{prefix}"
163
170
 
164
171
  tagging_join = "JOIN #{Tagging.table_name} #{taggings_alias}" +
165
172
  " ON #{taggings_alias}.taggable_id = #{table_name}.#{primary_key}" +
166
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}"
173
+ " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}" +
174
+ " AND #{taggings_alias}.tag_id = #{tag.id}"
167
175
  tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
168
176
 
169
- tag_join = "JOIN #{Tag.table_name} #{tags_alias}" +
170
- " ON #{tags_alias}.id = #{taggings_alias}.tag_id" +
171
- " AND " + sanitize_sql(["#{tags_alias}.name like ?", tag])
172
-
173
177
  joins << tagging_join
174
- joins << tag_join
175
178
  end
176
179
  end
177
180
 
@@ -187,7 +190,8 @@ module ActiveRecord
187
190
 
188
191
  { :joins => joins.join(" "),
189
192
  :group => group,
190
- :conditions => conditions.join(" AND ") }.update(options)
193
+ :conditions => conditions.join(" AND "),
194
+ :readonly => false }.update(options)
191
195
  end
192
196
 
193
197
  # Calculate the tag counts for all tags.
@@ -225,14 +229,32 @@ module ActiveRecord
225
229
 
226
230
  joins = ["LEFT OUTER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"]
227
231
  joins << sanitize_sql(["AND #{Tagging.table_name}.context = ?",options.delete(:on).to_s]) unless options[:on].nil?
228
-
229
232
  joins << " INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{Tagging.table_name}.taggable_id"
230
- unless self.descends_from_active_record?
233
+
234
+ unless descends_from_active_record?
231
235
  # Current model is STI descendant, so add type checking to the join condition
232
- joins << " AND #{table_name}.#{self.inheritance_column} = '#{self.name}'"
236
+ joins << " AND #{table_name}.#{inheritance_column} = '#{name}'"
233
237
  end
234
238
 
235
- joins << scope[:joins] if scope && scope[:joins]
239
+ # Based on a proposed patch by donV to ActiveRecord Base
240
+ # This is needed because merge_joins and construct_join are private in ActiveRecord Base
241
+ if scope && scope[:joins]
242
+ case scope[:joins]
243
+ when Array
244
+ scope_joins = scope[:joins].flatten
245
+ strings = scope_joins.select{|j| j.is_a? String}
246
+ joins << strings.join(' ') + " "
247
+ symbols = scope_joins - strings
248
+ join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, symbols, nil)
249
+ joins << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
250
+ joins.flatten!
251
+ when Symbol, Hash
252
+ join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, scope[:joins], nil)
253
+ joins << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
254
+ when String
255
+ joins << scope[:joins]
256
+ end
257
+ end
236
258
 
237
259
  at_least = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least]
238
260
  at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most]
@@ -301,7 +323,7 @@ module ActiveRecord
301
323
  end
302
324
 
303
325
  def tag_counts_on(context, options={})
304
- self.class.tag_counts_on(context, options.merge(:id => self.id))
326
+ self.class.tag_counts_on(context, options.merge(:id => id))
305
327
  end
306
328
 
307
329
  def related_tags_for(context, klass, options = {})
@@ -311,9 +333,9 @@ module ActiveRecord
311
333
  end
312
334
 
313
335
  def related_search_options(context, klass, options = {})
314
- tags_to_find = self.tags_on(context).collect { |t| t.name }
336
+ tags_to_find = tags_on(context).collect { |t| t.name }
315
337
 
316
- exclude_self = "#{klass.table_name}.id != #{self.id} AND" if self.class == klass
338
+ exclude_self = "#{klass.table_name}.id != #{id} AND" if self.class == klass
317
339
 
318
340
  { :select => "#{klass.table_name}.*, COUNT(#{Tag.table_name}.id) AS count",
319
341
  :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
@@ -330,9 +352,9 @@ module ActiveRecord
330
352
  end
331
353
 
332
354
  def matching_context_search_options(search_context, result_context, klass, options = {})
333
- tags_to_find = self.tags_on(search_context).collect { |t| t.name }
355
+ tags_to_find = tags_on(search_context).collect { |t| t.name }
334
356
 
335
- exclude_self = "#{klass.table_name}.id != #{self.id} AND" if self.class == klass
357
+ exclude_self = "#{klass.table_name}.id != #{id} AND" if self.class == klass
336
358
 
337
359
  { :select => "#{klass.table_name}.*, COUNT(#{Tag.table_name}.id) AS count",
338
360
  :from => "#{klass.table_name}, #{Tag.table_name}, #{Tagging.table_name}",
@@ -357,7 +379,7 @@ module ActiveRecord
357
379
  new_tag_names = instance_variable_get("@#{tag_type.singularize}_list") - tags_on(tag_type).map(&:name)
358
380
  old_tags = tags_on(tag_type, owner).reject { |tag| instance_variable_get("@#{tag_type.singularize}_list").include?(tag.name) }
359
381
 
360
- self.class.transaction do
382
+ transaction do
361
383
  base_tags.delete(*old_tags) if old_tags.any?
362
384
  new_tag_names.each do |new_tag_name|
363
385
  new_tag = Tag.find_or_create_with_like_by_name(new_tag_name)
@@ -372,7 +394,7 @@ module ActiveRecord
372
394
 
373
395
  def reload_with_tag_list(*args)
374
396
  self.class.tag_types.each do |tag_type|
375
- self.instance_variable_set("@#{tag_type.to_s.singularize}_list", nil)
397
+ instance_variable_set("@#{tag_type.to_s.singularize}_list", nil)
376
398
  end
377
399
 
378
400
  reload_without_tag_list(*args)
@@ -1,11 +1,23 @@
1
1
  class Tag < ActiveRecord::Base
2
+
3
+ attr_accessible :name
4
+
5
+ ### ASSOCIATIONS:
6
+
2
7
  has_many :taggings, :dependent => :destroy
3
8
 
9
+ ### VALIDATIONS:
10
+
4
11
  validates_presence_of :name
5
12
  validates_uniqueness_of :name
6
13
 
14
+ ### NAMED SCOPES:
15
+
7
16
  named_scope :named, lambda { |name| { :conditions => ["name = ?", name] } }
8
17
  named_scope :named_like, lambda { |name| { :conditions => ["name LIKE ?", "%#{name}%"] } }
18
+ named_scope :named_like_any, lambda { |list| { :conditions => list.map { |tag| sanitize_sql(["name LIKE ?", tag.to_s]) }.join(" OR ") } }
19
+
20
+ ### METHODS:
9
21
 
10
22
  # LIKE is used for cross-database case-insensitivity
11
23
  def self.find_or_create_with_like_by_name(name)
@@ -41,9 +41,10 @@ class TagList < Array
41
41
  # tag_list = TagList.new("Round", "Square,Cube")
42
42
  # tag_list.to_s # 'Round, "Square,Cube"'
43
43
  def to_s
44
- clean!
44
+ tags = frozen? ? self.dup : self
45
+ tags.send(:clean!)
45
46
 
46
- map do |name|
47
+ tags.map do |name|
47
48
  name.include?(delimiter) ? "\"#{name}\"" : name
48
49
  end.join(delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ")
49
50
  end
@@ -55,7 +56,7 @@ class TagList < Array
55
56
  map!(&:strip)
56
57
  uniq!
57
58
  end
58
-
59
+
59
60
  def extract_and_apply_options!(args)
60
61
  options = args.last.is_a?(Hash) ? args.pop : {}
61
62
  options.assert_valid_keys :parse
@@ -79,8 +80,8 @@ class TagList < Array
79
80
  string = string.to_s.dup
80
81
 
81
82
  # Parse the quoted tags
82
- string.gsub!(/"(.*?)"\s*#{delimiter}?\s*/) { tag_list << $1; "" }
83
- string.gsub!(/'(.*?)'\s*#{delimiter}?\s*/) { tag_list << $1; "" }
83
+ string.gsub!(/(\A|#{delimiter})\s*"(.*?)"\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
84
+ string.gsub!(/(\A|#{delimiter})\s*'(.*?)'\s*(#{delimiter}\s*|\z)/) { tag_list << $2; $3 }
84
85
 
85
86
  tag_list.add(string.split(delimiter))
86
87
  end
@@ -1,8 +1,14 @@
1
1
  class Tagging < ActiveRecord::Base #:nodoc:
2
+ attr_accessible :tag, :tag_id, :context,
3
+ :taggable, :taggable_type, :taggable_id,
4
+ :tagger, :tagger_type, :tagger_id
5
+
2
6
  belongs_to :tag
3
7
  belongs_to :taggable, :polymorphic => true
4
8
  belongs_to :tagger, :polymorphic => true
5
9
 
6
10
  validates_presence_of :context
7
11
  validates_presence_of :tag_id
12
+
13
+ validates_uniqueness_of :tag_id, :scope => [:taggable_type, :taggable_id, :context]
8
14
  end
@@ -1,6 +1,8 @@
1
1
  module TagsHelper
2
2
  # See the README for an example using tag_cloud.
3
3
  def tag_cloud(tags, classes)
4
+ return [] if tags.empty?
5
+
4
6
  max_count = tags.sort_by(&:count).last.count.to_f
5
7
 
6
8
  tags.each do |tag|
data/rails/init.rb CHANGED
@@ -2,6 +2,4 @@ require 'acts-as-taggable-on'
2
2
 
3
3
  ActiveRecord::Base.send :include, ActiveRecord::Acts::TaggableOn
4
4
  ActiveRecord::Base.send :include, ActiveRecord::Acts::Tagger
5
- ActionView::Base.send :include, TagsHelper if defined?(ActionView::Base)
6
-
7
- RAILS_DEFAULT_LOGGER.info "** acts_as_taggable_on: initialized properly."
5
+ ActionView::Base.send :include, TagsHelper if defined?(ActionView::Base)
@@ -176,16 +176,6 @@ describe "Acts As Taggable On" do
176
176
  end
177
177
 
178
178
  describe 'Tagging Contexts' do
179
- before(:all) do
180
- class Array
181
- def freq
182
- k=Hash.new(0)
183
- self.each {|e| k[e]+=1}
184
- k
185
- end
186
- end
187
- end
188
-
189
179
  it 'should eliminate duplicate tagging contexts ' do
190
180
  TaggableModel.acts_as_taggable_on(:skills, :skills)
191
181
  TaggableModel.tag_types.freq[:skills].should_not == 3
@@ -212,10 +202,6 @@ describe "Acts As Taggable On" do
212
202
  TaggableModel.acts_as_taggable_on([nil])
213
203
  }.should_not raise_error
214
204
  end
215
-
216
- after(:all) do
217
- class Array; remove_method :freq; end
218
- end
219
205
  end
220
206
 
221
207
  end
@@ -20,6 +20,18 @@ describe TagList do
20
20
  @tag_list.include?("wicked").should be_true
21
21
  end
22
22
 
23
+ it "should be able to add delimited list of words with quoted delimiters" do
24
+ @tag_list.add("'cool, wicked', \"really cool, really wicked\"", :parse => true)
25
+ @tag_list.include?("cool, wicked").should be_true
26
+ @tag_list.include?("really cool, really wicked").should be_true
27
+ end
28
+
29
+ it "should be able to handle other uses of quotation marks correctly" do
30
+ @tag_list.add("john's cool car, mary's wicked toy", :parse => true)
31
+ @tag_list.include?("john's cool car").should be_true
32
+ @tag_list.include?("mary's wicked toy").should be_true
33
+ end
34
+
23
35
  it "should be able to add an array of words" do
24
36
  @tag_list.add(["cool", "wicked"], :parse => true)
25
37
  @tag_list.include?("cool").should be_true
@@ -49,4 +61,10 @@ describe TagList do
49
61
  @tag_list.add("cool","rad,bodacious")
50
62
  @tag_list.to_s.should == "awesome, radical, cool, \"rad,bodacious\""
51
63
  end
64
+
65
+ it "should be able to call to_s on a frozen tag list" do
66
+ @tag_list.freeze
67
+ lambda { @tag_list.add("cool","rad,bodacious") }.should raise_error(TypeError)
68
+ lambda { @tag_list.to_s }.should_not raise_error(TypeError)
69
+ end
52
70
  end
@@ -7,6 +7,17 @@ describe Tag do
7
7
  Tag.delete_all
8
8
  end
9
9
 
10
+ describe "named like any" do
11
+ before(:each) do
12
+ Tag.create(:name => "awesome")
13
+ Tag.create(:name => "epic")
14
+ end
15
+
16
+ it "should find both tags" do
17
+ Tag.named_like_any(["awesome", "epic"]).should have(2).items
18
+ end
19
+ end
20
+
10
21
  describe "find or create by name" do
11
22
  before(:each) do
12
23
  @tag.name = "awesome"
@@ -77,6 +77,8 @@ describe "Taggable" do
77
77
  @taggable.save
78
78
 
79
79
  TaggableModel.tagged_with("ruby").first.should == @taggable
80
+ TaggableModel.tagged_with("ruby, css").first.should == @taggable
81
+ TaggableModel.tagged_with("ruby, nonexistingtag").should be_empty
80
82
  TaggableModel.tagged_with("bob", :on => :skills).first.should_not == @taggable
81
83
  TaggableModel.tagged_with("bob", :on => :tags).first.should == @taggable
82
84
  end
@@ -106,6 +108,12 @@ describe "Taggable" do
106
108
  TaggableModel.all_tag_counts.first.count.should == 3 # ruby
107
109
  end
108
110
 
111
+ it "should not return read-only records" do
112
+ TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
113
+
114
+ TaggableModel.tagged_with("ruby").first.should_not be_readonly
115
+ end
116
+
109
117
  it "should be able to get scoped tag counts" do
110
118
  bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
111
119
  frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
@@ -141,7 +149,17 @@ describe "Taggable" do
141
149
  TaggableModel.find_tagged_with("ruby, rails", :order => 'taggable_models.name').should == [bob, frank]
142
150
  TaggableModel.find_tagged_with(["ruby", "rails"], :order => 'taggable_models.name').should == [bob, frank]
143
151
  end
144
-
152
+
153
+ it "should be able to find tagged with any tag" do
154
+ bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
155
+ frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
156
+ steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
157
+
158
+ TaggableModel.find_tagged_with(["ruby", "java"], :order => 'taggable_models.name', :any => true).should == [bob, frank, steve]
159
+ TaggableModel.find_tagged_with(["c++", "fitter"], :order => 'taggable_models.name', :any => true).should == [bob, steve]
160
+ TaggableModel.find_tagged_with(["depressed", "css"], :order => 'taggable_models.name', :any => true).should == [bob, frank]
161
+ end
162
+
145
163
  it "should be able to find tagged on a custom tag context" do
146
164
  bob = TaggableModel.create(:name => "Bob")
147
165
  bob.set_tag_list_on(:rotors, "spinning, jumping")
@@ -13,4 +13,13 @@ describe Tagging do
13
13
  @tagging.should_not be_valid
14
14
  @tagging.errors.on(:tag_id).should == "can't be blank"
15
15
  end
16
+
17
+ it "should not create duplicate taggings" do
18
+ @taggable = TaggableModel.create(:name => "Bob Jones")
19
+ @tag = Tag.create(:name => "awesome")
20
+
21
+ lambda {
22
+ 2.times { Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags') }
23
+ }.should change(Tagging, :count).by(1)
24
+ end
16
25
  end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,20 @@
1
1
  # require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
2
2
  require 'rubygems'
3
- require 'activerecord'
3
+ require 'active_record'
4
4
  require 'spec'
5
5
 
6
6
  module Spec::Example::ExampleGroupMethods
7
7
  alias :context :describe
8
8
  end
9
9
 
10
+ class Array
11
+ def freq
12
+ k=Hash.new(0)
13
+ each {|e| k[e]+=1}
14
+ k
15
+ end
16
+ end
17
+
10
18
  TEST_DATABASE_FILE = File.join(File.dirname(__FILE__), '..', 'test.sqlite3')
11
19
 
12
20
  File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
@@ -16,7 +24,10 @@ ActiveRecord::Base.establish_connection(
16
24
 
17
25
  RAILS_DEFAULT_LOGGER = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
18
26
 
19
- load(File.dirname(__FILE__) + '/schema.rb')
27
+ ActiveRecord::Base.silence do
28
+ ActiveRecord::Migration.verbose = false
29
+ load(File.dirname(__FILE__) + '/schema.rb')
30
+ end
20
31
 
21
32
  $: << File.join(File.dirname(__FILE__), '..', 'lib')
22
33
  require File.join(File.dirname(__FILE__), '..', 'init')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts-as-taggable-on
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.13
4
+ version: 1.0.19
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-11 00:00:00 +01:00
12
+ date: 2010-01-21 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -27,6 +27,8 @@ files:
27
27
  - README.rdoc
28
28
  - Rakefile
29
29
  - VERSION
30
+ - generators/acts_as_taggable_on_migration/acts_as_taggable_on_migration_generator.rb
31
+ - generators/acts_as_taggable_on_migration/templates/migration.rb
30
32
  - lib/acts-as-taggable-on.rb
31
33
  - lib/acts_as_taggable_on/acts_as_taggable_on.rb
32
34
  - lib/acts_as_taggable_on/acts_as_tagger.rb