tagtical 1.5.9 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +36 -0
- data/VERSION +1 -1
- data/generators/tagtical_migration/templates/migration.rb +3 -3
- data/lib/generators/tagtical/migration/templates/active_record/migration.rb +3 -3
- data/lib/tagtical/tag.rb +38 -0
- data/lib/tagtical/taggable/core.rb +20 -1
- data/lib/tagtical/taggable/tag_group.rb +51 -0
- data/lib/tagtical/taggable.rb +7 -2
- data/lib/tagtical.rb +1 -0
- data/spec/models.rb +7 -0
- data/spec/schema.rb +4 -0
- data/spec/tagtical/tag_group_spec.rb +29 -0
- data/spec/tagtical/taggable_spec.rb +40 -1
- metadata +12 -9
data/README.rdoc
CHANGED
@@ -39,6 +39,8 @@ parsed.
|
|
39
39
|
|
40
40
|
7. Custom contexts are *not* supported since we use STI. That is, you must define a set of tag types
|
41
41
|
ahead of time.
|
42
|
+
8. Functionality for joining across tags (seeing which tags two different models have in common)
|
43
|
+
with both superset and subset matching.
|
42
44
|
|
43
45
|
Additions include:
|
44
46
|
1. Scopes are created on Tag so you can do photo.tags.color and grab all the tags of type Tag::Color, for example.
|
@@ -282,6 +284,40 @@ just define the subclass and the code will automatically instantiate it as that
|
|
282
284
|
|
283
285
|
Now moving forward, these classes will be instantiated with this model. Wow cool!
|
284
286
|
|
287
|
+
=== Tag Groups
|
288
|
+
|
289
|
+
This functionality allows to join models across tags (seeing which tags two different models have in common)
|
290
|
+
with both superset and subset matching.
|
291
|
+
|
292
|
+
You can do it simply by providing :has_many_through_tags call in taggable model, like:
|
293
|
+
|
294
|
+
class User < ActiveRecord::Base
|
295
|
+
acts_as_taggable :skills
|
296
|
+
has_many_through_tags :schools, :superset
|
297
|
+
end
|
298
|
+
|
299
|
+
class School < ActiveRecord::Base
|
300
|
+
acts_as_taggable :skills
|
301
|
+
has_many_through_tags :users # :subset is default
|
302
|
+
end
|
303
|
+
|
304
|
+
So, users can study in a school only if they have all the required skills. We want to get
|
305
|
+
list of all schools of a user and all users of a school.
|
306
|
+
|
307
|
+
school1.skill_list = "math, biology"
|
308
|
+
school2.skill_list = "programming, chemistry"
|
309
|
+
user.skill_list = "chemistry, math, biology"
|
310
|
+
|
311
|
+
user.schools # => [school1]
|
312
|
+
school1.users # => [user]
|
313
|
+
school2.users # => []
|
314
|
+
|
315
|
+
You also may specify different class name, if you want to name your association differently:
|
316
|
+
|
317
|
+
class User < ActiveRecord::Base
|
318
|
+
acts_as_taggable :skills
|
319
|
+
has_many_through_tags :possible_schools, :superset, class_name: "School"
|
320
|
+
end
|
285
321
|
|
286
322
|
=== Tag Ownership
|
287
323
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.6.0
|
@@ -2,7 +2,7 @@ class TagticalMigration < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
3
3
|
create_table :tags do |t|
|
4
4
|
t.column :value, :string
|
5
|
-
t.column :type, :string
|
5
|
+
t.column :type, :string, :limit => 100
|
6
6
|
end
|
7
7
|
add_index :tags, [:type, :value], :unique => true
|
8
8
|
add_index :tags, :value
|
@@ -12,11 +12,11 @@ class TagticalMigration < ActiveRecord::Migration
|
|
12
12
|
t.column :tag_id, :integer
|
13
13
|
t.column :taggable_id, :integer
|
14
14
|
t.column :tagger_id, :integer
|
15
|
-
t.column :tagger_type, :string if Tagtical.config.polymorphic_tagger?
|
15
|
+
t.column :tagger_type, :string, :limit => 100 if Tagtical.config.polymorphic_tagger?
|
16
16
|
|
17
17
|
# You should make sure that the column created is
|
18
18
|
# long enough to store the required class names.
|
19
|
-
t.column :taggable_type, :string
|
19
|
+
t.column :taggable_type, :string, :limit => 100
|
20
20
|
|
21
21
|
t.column :created_at, :datetime
|
22
22
|
end
|
@@ -2,7 +2,7 @@ class TagticalMigration < ActiveRecord::Migration
|
|
2
2
|
def self.up
|
3
3
|
create_table :tags do |t|
|
4
4
|
t.string :value
|
5
|
-
t.string :type
|
5
|
+
t.string :type, :limit => 100
|
6
6
|
end
|
7
7
|
add_index :tags, [:type, :value], :unique => true
|
8
8
|
add_index :tags, :value
|
@@ -13,9 +13,9 @@ class TagticalMigration < ActiveRecord::Migration
|
|
13
13
|
|
14
14
|
# You should make sure that the column created is
|
15
15
|
# long enough to store the required class names.
|
16
|
-
t.references :taggable, :polymorphic => true
|
16
|
+
t.references :taggable, :polymorphic => true, :limit => 100
|
17
17
|
if Tagtical.config.polymorphic_tagger?
|
18
|
-
t.references :tagger, :polymorphic => true
|
18
|
+
t.references :tagger, :polymorphic => true, :limit => 100
|
19
19
|
else
|
20
20
|
t.integer :tagger_id
|
21
21
|
end
|
data/lib/tagtical/tag.rb
CHANGED
@@ -469,6 +469,44 @@ module Tagtical
|
|
469
469
|
Array(input).map { |o| taggable_class.find_tag_type!(o).klass }
|
470
470
|
end
|
471
471
|
|
472
|
+
# Instead of subclassing from Array, we make a Proxy, so we actually can use method_missing
|
473
|
+
# for catching results and converting them into Collection class if they return Array
|
474
|
+
class Collection
|
475
|
+
def initialize(*args)
|
476
|
+
@array = Array.new(*args)
|
477
|
+
end
|
478
|
+
|
479
|
+
# Usage:
|
480
|
+
# tag_types.get(["boy", "girl"]) # => ["boy", "girl"]
|
481
|
+
# tag_types.get("boy") # => "boy"
|
482
|
+
# # "boy".class === Tagtical::Tag::Type everywhere
|
483
|
+
def get(tag_type_names)
|
484
|
+
results = @array.select { |tag_type| tag_type_names.include?(tag_type) }
|
485
|
+
tag_type_names.is_a?(Array) ? results : results.first
|
486
|
+
end
|
487
|
+
|
488
|
+
def respond_to?(*args)
|
489
|
+
super || @array.respond_to?(*args)
|
490
|
+
end
|
491
|
+
|
492
|
+
def to_ary
|
493
|
+
@array
|
494
|
+
end
|
495
|
+
|
496
|
+
def to_a
|
497
|
+
@array
|
498
|
+
end
|
499
|
+
|
500
|
+
def method_missing(name, *args)
|
501
|
+
result = if block_given?
|
502
|
+
@array.send(name, *args) { |*block_args| yield(*block_args) }
|
503
|
+
else
|
504
|
+
@array.send(name, *args)
|
505
|
+
end
|
506
|
+
result.is_a?(@array.class) ? self.class.new(result) : result
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
472
510
|
end
|
473
511
|
end
|
474
512
|
end
|
@@ -14,7 +14,7 @@ module Tagtical::Taggable
|
|
14
14
|
empty_tag_types = tag_types.select do |tag_type|
|
15
15
|
Array.wrap(empty_tags_type_names).map(&:to_s).include?(tag_type)
|
16
16
|
end
|
17
|
-
empty_tag_type_classes = empty_tag_types.map { |t| t.klass.to_s }
|
17
|
+
empty_tag_type_classes = empty_tag_types.map { |t| t.klass.to_s }.to_a
|
18
18
|
if empty_tag_type_classes.present?
|
19
19
|
tagging_table = Tagtical::Tagging.arel_table
|
20
20
|
tag_table = Tagtical::Tag.arel_table
|
@@ -359,6 +359,25 @@ module Tagtical::Taggable
|
|
359
359
|
true
|
360
360
|
end
|
361
361
|
|
362
|
+
# Returns flat list of tag classes and tag values.
|
363
|
+
#
|
364
|
+
# taggable.update_attributes!(gender_list: "boy, girl", skill_list: "ruby")
|
365
|
+
# taggable.short_tags # => %w(gender_boy gender_girl skill_ruby tag_boy tag_girl tag_ruby)
|
366
|
+
# taggable.short_tags(only: :gender) # => %w(gender_boy gender_girl)
|
367
|
+
# taggable.short_tags(exclude: :gender) # => %w(skill_ruby tag_boy tag_girl tag_ruby)
|
368
|
+
def short_tags(options = {})
|
369
|
+
tag_types = if options[:only].present?
|
370
|
+
self.class.tag_types.select { |tt| Array.wrap(options[:only]).map(&:to_s).include?(tt) }
|
371
|
+
else
|
372
|
+
self.class.tag_types - Array.wrap(options[:exclude]).compact.map(&:to_s)
|
373
|
+
end
|
374
|
+
tag_types.map do |tag_type|
|
375
|
+
send(tag_type.has_many_name).map do |tag|
|
376
|
+
"#{tag_type}_#{tag.value}"
|
377
|
+
end
|
378
|
+
end.flatten.to_a
|
379
|
+
end
|
380
|
+
|
362
381
|
|
363
382
|
private
|
364
383
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Tagtical
|
2
|
+
module Taggable
|
3
|
+
module TagGroup
|
4
|
+
|
5
|
+
def has_many_through_tags(association_id, type = :subset, options = {})
|
6
|
+
case type
|
7
|
+
when :subset then has_many_through_tags_subset(association_id, options)
|
8
|
+
when :superset then has_many_through_tags_superset(association_id, options)
|
9
|
+
else raise "Wrong association type, should be :subset or :superset"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def has_many_through_tags_superset(association_id, options)
|
16
|
+
define_method(association_id) do
|
17
|
+
result = instance_variable_get("@#{association_id}") || begin
|
18
|
+
klass = (options[:class_name] || association_id.to_s.singularize.camelize).constantize
|
19
|
+
klass.
|
20
|
+
joins(
|
21
|
+
"LEFT JOIN #{Tagtical::Tagging.table_name} AS t1 " +
|
22
|
+
"ON t1.taggable_id = #{klass.table_name}.id AND t1.taggable_type = '#{klass}'"
|
23
|
+
).
|
24
|
+
joins(
|
25
|
+
"LEFT JOIN #{Tagtical::Tagging.table_name} AS t2 " +
|
26
|
+
"ON t2.tag_id = t1.tag_id AND t2.taggable_type = '#{self.class}' AND t2.taggable_id = #{id}"
|
27
|
+
).
|
28
|
+
group("#{klass.table_name}.id").
|
29
|
+
having("COUNT(t2.tag_id) = COUNT(#{klass.table_name}.id)")
|
30
|
+
end
|
31
|
+
instance_variable_set("@#{association_id}", result)
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_many_through_tags_subset(association_id, options)
|
37
|
+
define_method(association_id) do
|
38
|
+
result = instance_variable_get("@#{association_id}") || begin
|
39
|
+
klass = (options[:class_name] || association_id.to_s.singularize.camelize).constantize
|
40
|
+
klass.
|
41
|
+
joins(:taggings).
|
42
|
+
where("#{Tagtical::Tagging.table_name}.`tag_id` IN (?)", taggings.map(&:tag_id)).
|
43
|
+
group("#{klass.table_name}.id").having(["count(#{klass.table_name}.id) = ?", taggings.count])
|
44
|
+
end
|
45
|
+
instance_variable_set("@#{association_id}", result)
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/tagtical/taggable.rb
CHANGED
@@ -22,13 +22,14 @@ module Tagtical
|
|
22
22
|
def acts_as_taggable(*tag_types)
|
23
23
|
tag_types.flatten!
|
24
24
|
tag_types << Tagtical::Tag::Type::BASE # always include the base type.
|
25
|
-
tag_types = Tagtical::Tag::Type.register(tag_types.uniq.compact, self)
|
25
|
+
tag_types = Tagtical::Tag::Type::Collection.new(Tagtical::Tag::Type.register(tag_types.uniq.compact, self))
|
26
26
|
|
27
27
|
if taggable?
|
28
28
|
self.tag_types = (self.tag_types + tag_types).uniq
|
29
29
|
else
|
30
|
-
class_attribute
|
30
|
+
class_attribute :tag_types, :custom_tag_types
|
31
31
|
self.tag_types = tag_types
|
32
|
+
self.custom_tag_types = tag_types - [Tagtical::Tag::Type::BASE]
|
32
33
|
|
33
34
|
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "Tagtical::Tagging"
|
34
35
|
has_many :tags, :through => :taggings, :class_name => "Tagtical::Tag"
|
@@ -45,9 +46,13 @@ module Tagtical
|
|
45
46
|
include Tagtical::Taggable::Cache
|
46
47
|
include Tagtical::Taggable::Ownership
|
47
48
|
include Tagtical::Taggable::Related
|
49
|
+
extend Tagtical::Taggable::TagGroup
|
48
50
|
|
49
51
|
end
|
50
52
|
|
53
|
+
# Purpose of this is to keep additional tagtical class level methods grouped
|
54
|
+
# together with the acts_as_taggable call.
|
55
|
+
yield if block_given?
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
data/lib/tagtical.rb
CHANGED
@@ -33,6 +33,7 @@ require "tagtical/taggable/collection"
|
|
33
33
|
require "tagtical/taggable/cache"
|
34
34
|
require "tagtical/taggable/ownership"
|
35
35
|
require "tagtical/taggable/related"
|
36
|
+
require "tagtical/taggable/tag_group"
|
36
37
|
|
37
38
|
require "tagtical/acts_as_tagger"
|
38
39
|
require "tagtical/tag"
|
data/spec/models.rb
CHANGED
@@ -35,6 +35,7 @@ end
|
|
35
35
|
class TaggableModel < ActiveRecord::Base
|
36
36
|
acts_as_taggable(:languages, :skills, {:crafts => Tag::FooCraft}, :needs, :offerings, {:styles => "BarCraft"})
|
37
37
|
has_many :untaggable_models
|
38
|
+
has_many_through_tags :custom_groups, :superset
|
38
39
|
end
|
39
40
|
|
40
41
|
class CachedModel < ActiveRecord::Base
|
@@ -59,3 +60,9 @@ end
|
|
59
60
|
class UntaggableModel < ActiveRecord::Base
|
60
61
|
belongs_to :taggable_model
|
61
62
|
end
|
63
|
+
|
64
|
+
class CustomGroup < ActiveRecord::Base
|
65
|
+
acts_as_taggable(:skills, :languages) do
|
66
|
+
has_many_through_tags :taggable_models
|
67
|
+
end
|
68
|
+
end
|
data/spec/schema.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Tagtical::Taggable::TagGroup do
|
4
|
+
|
5
|
+
before { clean_database! }
|
6
|
+
|
7
|
+
it "should retrieve related tagged objects" do
|
8
|
+
group = CustomGroup.create!(language_list: "ruby", skill_list: "programmer")
|
9
|
+
objects = [
|
10
|
+
{:name => "One", language_list: "ruby, c", skill_list: "programmer"},
|
11
|
+
{:name => "Two", language_list: "c", skill_list: "programmer"},
|
12
|
+
{:name => "Three", language_list: "ruby", skill_list: "manager"},
|
13
|
+
{:name => "Four", language_list: "ruby", skill_list: "programmer"}
|
14
|
+
].map { |attrs| TaggableModel.create!(attrs) }
|
15
|
+
group.taggable_models.should == [objects[0], objects[3]]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should retrieve associated tag groups" do
|
19
|
+
groups = [
|
20
|
+
{language_list: "ruby, c", skill_list: "programmer", name: "Ruby C Programmer"},
|
21
|
+
{language_list: "c", skill_list: "programmer", name: "C Programmer"},
|
22
|
+
{language_list: "ruby", skill_list: "manager", name: "Ruby Manager"},
|
23
|
+
{language_list: "ruby", skill_list: "programmer", name: "Ruby Programmer"}
|
24
|
+
].map { |attrs| CustomGroup.create!(attrs) }
|
25
|
+
model = TaggableModel.create!(language_list: "ruby, c", skill_list: "programmer")
|
26
|
+
model.custom_groups.should == [groups[0], groups[1], groups[3]]
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -16,10 +16,40 @@ describe Tagtical::Taggable do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should have tag types" do
|
19
|
-
TaggableModel.tag_types.should include(
|
19
|
+
TaggableModel.tag_types.should include(Tagtical::Tag::Type::BASE, "language", "skill", "craft", "need", "offering")
|
20
20
|
@taggable.tag_types.should == TaggableModel.tag_types
|
21
21
|
end
|
22
22
|
|
23
|
+
describe ".custom_tag_types" do
|
24
|
+
subject { TaggableModel.custom_tag_types }
|
25
|
+
it { should include("language", "skill", "craft", "need", "offering") }
|
26
|
+
it { should_not include(Tagtical::Tag::Type::BASE) }
|
27
|
+
it { should == @taggable.custom_tag_types }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".tag_types" do
|
31
|
+
subject { TaggableModel.tag_types }
|
32
|
+
it { should be_a(Tagtical::Tag::Type::Collection) }
|
33
|
+
its(:first) { should be_a(Tagtical::Tag::Type) }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "tag types collection" do
|
37
|
+
|
38
|
+
it "should return its class instance after executing Array's methods" do
|
39
|
+
TaggableModel.tag_types.select { |t| t == "tag" }.should be_a(Tagtical::Tag::Type::Collection)
|
40
|
+
end
|
41
|
+
|
42
|
+
context "get tag types" do
|
43
|
+
specify "by array" do
|
44
|
+
TaggableModel.tag_types.get(["language", "skill"]).should =~ ["skill", "language"]
|
45
|
+
end
|
46
|
+
|
47
|
+
specify "by item" do
|
48
|
+
TaggableModel.tag_types.get("language").should == "language"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
23
53
|
it "should have tag_counts_on" do
|
24
54
|
TaggableModel.tag_counts_on(:tags).all.should be_empty
|
25
55
|
|
@@ -30,6 +60,15 @@ describe Tagtical::Taggable do
|
|
30
60
|
@taggable.tag_counts_on(:tags).length.should == 2
|
31
61
|
end
|
32
62
|
|
63
|
+
describe ".short_tags" do
|
64
|
+
subject { @taggable }
|
65
|
+
before { subject.update_attributes!(skill_list: %w(ruby rails), tag_list: %w(red)) }
|
66
|
+
|
67
|
+
its(:short_tags) { should == %w(skill_ruby skill_rails tag_red tag_ruby tag_rails) }
|
68
|
+
specify { subject.short_tags(only: :skill).should == %w(skill_ruby skill_rails) }
|
69
|
+
specify { subject.short_tags(exclude: :skill).should == %w(tag_red tag_ruby tag_rails) }
|
70
|
+
end
|
71
|
+
|
33
72
|
it "should be able to create tags" do
|
34
73
|
@taggable.skill_list = "ruby, rails, css"
|
35
74
|
@taggable.tag_list_on(:skills).should be_an_instance_of(Tagtical::TagList)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tagtical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ default_executable:
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
|
-
requirement: &
|
17
|
+
requirement: &2157842540 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '3.0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2157842540
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: sqlite3
|
28
|
-
requirement: &
|
28
|
+
requirement: &2157878760 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2157878760
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: mysql
|
39
|
-
requirement: &
|
39
|
+
requirement: &2157878300 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *2157878300
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: rspec
|
50
|
-
requirement: &
|
50
|
+
requirement: &2157877880 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *2157877880
|
59
59
|
description: Tagtical allows you do create subclasses for Tag and add additional functionality
|
60
60
|
in an STI fashion. For example. You could do Tag::Color.find_by_name('blue').to_rgb.
|
61
61
|
It also supports storing weights or relevance on the taggings.
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/tagtical/taggable/core.rb
|
81
81
|
- lib/tagtical/taggable/ownership.rb
|
82
82
|
- lib/tagtical/taggable/related.rb
|
83
|
+
- lib/tagtical/taggable/tag_group.rb
|
83
84
|
- lib/tagtical/taggable.rb
|
84
85
|
- lib/tagtical/tagging.rb
|
85
86
|
- lib/tagtical/tags_helper.rb
|
@@ -97,6 +98,7 @@ files:
|
|
97
98
|
- spec/schema.rb
|
98
99
|
- spec/spec_helper.rb
|
99
100
|
- spec/tagtical/acts_as_tagger_spec.rb
|
101
|
+
- spec/tagtical/tag_group_spec.rb
|
100
102
|
- spec/tagtical/tag_list_spec.rb
|
101
103
|
- spec/tagtical/tag_spec.rb
|
102
104
|
- spec/tagtical/taggable_spec.rb
|
@@ -139,6 +141,7 @@ test_files:
|
|
139
141
|
- spec/schema.rb
|
140
142
|
- spec/spec_helper.rb
|
141
143
|
- spec/tagtical/acts_as_tagger_spec.rb
|
144
|
+
- spec/tagtical/tag_group_spec.rb
|
142
145
|
- spec/tagtical/tag_list_spec.rb
|
143
146
|
- spec/tagtical/tag_spec.rb
|
144
147
|
- spec/tagtical/taggable_spec.rb
|