tagtical 1.5.9 → 1.6.0
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 +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
|