scoped-tags 0.3.1 → 0.4.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/VERSION.yml +3 -2
- data/generators/scoped_tags_migration/{scoped_tags_generator.rb → scoped_tags_migration_generator.rb} +1 -1
- data/lib/scoped_tags/active_record_additions.rb +22 -22
- data/lib/scoped_tags/tagging.rb +1 -1
- data/readme.md +20 -1
- data/spec/debug.log +255 -0
- data/spec/scoped_tags/scoped_tags_spec.rb +2 -2
- data/spec/scoped_tags/tag_and_tagging_spec.rb +33 -17
- data/spec/spec_helper.rb +15 -11
- data/spec/test.sqlite3 +0 -0
- metadata +21 -12
- data/install.rb +0 -1
- data/uninstall.rb +0 -1
data/VERSION.yml
CHANGED
@@ -1,64 +1,64 @@
|
|
1
1
|
module ScopedTags
|
2
|
-
|
2
|
+
|
3
3
|
module ActiveRecordAdditions
|
4
|
-
|
4
|
+
|
5
5
|
def self.included(base)
|
6
6
|
base.class_eval do
|
7
7
|
def self.scoped_tags(contexts, options = nil)
|
8
8
|
self.class.instance_eval{ attr_accessor :tag_contexts }
|
9
|
-
|
9
|
+
|
10
10
|
raise ScopedTagsError, 'context is required for scoped-tags setup' if contexts.blank?
|
11
|
-
|
11
|
+
|
12
12
|
self.tag_contexts = [contexts].flatten
|
13
|
-
|
14
|
-
has_many :taggings,
|
15
|
-
has_many :
|
16
|
-
|
13
|
+
|
14
|
+
has_many :taggings, :as => :taggable, :class_name => 'Tagging', :dependent => :delete_all
|
15
|
+
has_many :base_tags, :through => :taggings, :class_name => 'Tag', :source => :tag, :readonly => true
|
16
|
+
|
17
17
|
self.tag_contexts.each do |context|
|
18
18
|
has_many context, :through => :taggings, :class_name => 'Tag',
|
19
19
|
:source => :tag,
|
20
|
-
:conditions =>
|
21
|
-
|
20
|
+
:conditions => { :context => context.to_s.downcase }
|
21
|
+
|
22
22
|
c = context.to_s.singularize
|
23
23
|
define_method("#{c}_list") { get_tag_list(context) }
|
24
24
|
define_method("#{c}_list=") { |new_list| set_tag_list(context, new_list) }
|
25
25
|
self.class.instance_eval do
|
26
26
|
define_method("tagged_with_#{context}") { |*args| find_tagged_with(args.first, context.to_s, args.extract_options!) }
|
27
27
|
end
|
28
|
-
end
|
29
|
-
|
28
|
+
end
|
29
|
+
|
30
30
|
self.send :extend, ClassMethods
|
31
31
|
self.send :include, InstanceMethods
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
|
35
|
+
|
36
|
+
|
37
37
|
module ClassMethods
|
38
38
|
def find_tagged_with(tag_names, context, options = {})
|
39
39
|
tag_names = tag_names.is_a?(Array) ? tag_names : tag_names.split(TagListCollection.delimiter)
|
40
40
|
tag_names = tag_names.collect(&:strip).reject(&:blank?)
|
41
|
-
|
42
|
-
required_options = { :include => [:taggings, :
|
41
|
+
|
42
|
+
required_options = { :include => [:taggings, :base_tags],
|
43
43
|
:conditions => ['tags.name IN (?) AND tags.context = ?', tag_names, context] }
|
44
|
-
|
44
|
+
|
45
45
|
self.all(options.merge(required_options))
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
|
50
50
|
module InstanceMethods
|
51
51
|
protected
|
52
52
|
def get_tag_list(context)
|
53
53
|
@tag_list_collections = { } if not @tag_list_collections
|
54
54
|
@tag_list_collections[context] ||= TagListCollection.new(self, context.to_s.downcase)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def set_tag_list(context, new_tags)
|
58
58
|
get_tag_list(context).replace(new_tags)
|
59
|
-
end
|
59
|
+
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
end
|
data/lib/scoped_tags/tagging.rb
CHANGED
@@ -2,7 +2,7 @@ class Tagging < ActiveRecord::Base
|
|
2
2
|
belongs_to :tag
|
3
3
|
belongs_to :taggable, :polymorphic => true
|
4
4
|
|
5
|
-
validates_uniqueness_of :taggable_id, :scope => :tag_id
|
5
|
+
validates_uniqueness_of :taggable_id, :scope => [:tag_id, :taggable_type]
|
6
6
|
|
7
7
|
attr_accessible :taggable_type, :taggable_id, :tag_id
|
8
8
|
end
|
data/readme.md
CHANGED
@@ -26,12 +26,31 @@ Key Features
|
|
26
26
|
- tags are available for use in the validations as they are always kept in sync
|
27
27
|
|
28
28
|
|
29
|
+
Installation
|
30
|
+
------------
|
31
|
+
|
32
|
+
./script/plugin install git://github.com/joshk/scoped-tags.git
|
33
|
+
|
34
|
+
or
|
35
|
+
|
36
|
+
gem install scoped-tags --source http://gemcutter.org
|
37
|
+
|
38
|
+
although it is highly recommended that you install the gemcutter gem and set gemcutter as your default gem repository.
|
39
|
+
|
40
|
+
If you are using rails you can also use:
|
41
|
+
|
42
|
+
config.gem 'scoped-tags', :source => 'http://gemcutter.org' # source not needed if gemcutter is installed
|
43
|
+
|
44
|
+
To generate the migration file use:
|
45
|
+
|
46
|
+
./script/generate scoped_tags_migration
|
47
|
+
|
29
48
|
|
30
49
|
How can I use it?
|
31
50
|
-----------------
|
32
51
|
|
33
52
|
class Person
|
34
|
-
scoped_tags :
|
53
|
+
scoped_tags :interests
|
35
54
|
end
|
36
55
|
|
37
56
|
me = Person.new(:name => 'Josh')
|
data/spec/debug.log
CHANGED
@@ -1 +1,256 @@
|
|
1
1
|
# Logfile created on Sat Oct 17 19:04:03 +0200 2009 by logger.rb/22285
|
2
|
+
[4;36;1mSQL (0.5ms)[0m [0;1mselect sqlite_version(*)[0m
|
3
|
+
[4;35;1mSQL (0.3ms)[0m [0m SELECT name
|
4
|
+
FROM sqlite_master
|
5
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
6
|
+
[0m
|
7
|
+
[4;36;1mSQL (0.6ms)[0m [0;1mCREATE TABLE "scoped_tagged_models" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)) [0m
|
8
|
+
[4;35;1mSQL (0.1ms)[0m [0m SELECT name
|
9
|
+
FROM sqlite_master
|
10
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
11
|
+
[0m
|
12
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE TABLE "tags" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "context" varchar(255)) [0m
|
13
|
+
[4;35;1mSQL (0.1ms)[0m [0m SELECT name
|
14
|
+
FROM sqlite_master
|
15
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
16
|
+
[0m
|
17
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE TABLE "taggings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "tag_id" integer, "taggable_id" integer, "taggable_type" varchar(255)) [0m
|
18
|
+
[4;35;1mSQL (0.2ms)[0m [0mCREATE INDEX "index_tags_on_context_and_name" ON "tags" ("context", "name")[0m
|
19
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE INDEX "index_taggings_on_taggable_id_and_taggable_type" ON "taggings" ("taggable_id", "taggable_type")[0m
|
20
|
+
[4;35;1mSQL (0.3ms)[0m [0m SELECT name
|
21
|
+
FROM sqlite_master
|
22
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
23
|
+
[0m
|
24
|
+
[4;36;1mSQL (0.3ms)[0m [0;1mCREATE TABLE "schema_migrations" ("version" varchar(255) NOT NULL) [0m
|
25
|
+
[4;35;1mSQL (0.1ms)[0m [0mCREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")[0m
|
26
|
+
[4;36;1mSQL (0.2ms)[0m [0;1m SELECT name
|
27
|
+
FROM sqlite_master
|
28
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
29
|
+
[0m
|
30
|
+
[4;35;1mSQL (0.1ms)[0m [0mSELECT version FROM "schema_migrations"[0m
|
31
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mINSERT INTO "schema_migrations" (version) VALUES ('0')[0m
|
32
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
33
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'blues' and context = 'genres') LIMIT 1[0m
|
34
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'blues' and context = 'genres') LIMIT 1[0m
|
35
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
36
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'country' and context = 'genres') LIMIT 1[0m
|
37
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'blues' and context = 'genres') LIMIT 1[0m
|
38
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'blues' and context = 'genres') LIMIT 1[0m
|
39
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
40
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
41
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres') LIMIT 1[0m
|
42
|
+
[4;35;1mScopedTaggedModel Create (0.1ms)[0m [0mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
43
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
44
|
+
[4;35;1mTag Create (0.1ms)[0m [0mINSERT INTO "tags" ("name", "context") VALUES('rock', 'genres')[0m
|
45
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
46
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(1, 1, 'ScopedTaggedModel')[0m
|
47
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres') LIMIT 1[0m
|
48
|
+
[4;35;1mTag Create (0.1ms)[0m [0mINSERT INTO "tags" ("name", "context") VALUES('pop', 'genres')[0m
|
49
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
50
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 1, 'ScopedTaggedModel')[0m
|
51
|
+
[4;36;1mScopedTaggedModel Load Including Associations (0.5ms)[0m [0;1mSELECT "scoped_tagged_models"."id" AS t0_r0, "scoped_tagged_models"."name" AS t0_r1, "taggings"."id" AS t1_r0, "taggings"."tag_id" AS t1_r1, "taggings"."taggable_id" AS t1_r2, "taggings"."taggable_type" AS t1_r3, "tags"."id" AS t2_r0, "tags"."name" AS t2_r1, "tags"."context" AS t2_r2 FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" ON "taggings".taggable_id = "scoped_tagged_models".id AND "taggings".taggable_type = 'ScopedTaggedModel' LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop') AND tags.context = 'genres') [0m
|
52
|
+
[4;35;1mScopedTaggedModel Load Including Associations (0.5ms)[0m [0mSELECT "scoped_tagged_models"."id" AS t0_r0, "scoped_tagged_models"."name" AS t0_r1, "taggings"."id" AS t1_r0, "taggings"."tag_id" AS t1_r1, "taggings"."taggable_id" AS t1_r2, "taggings"."taggable_type" AS t1_r3, "tags"."id" AS t2_r0, "tags"."name" AS t2_r1, "tags"."context" AS t2_r2 FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" ON "taggings".taggable_id = "scoped_tagged_models".id AND "taggings".taggable_type = 'ScopedTaggedModel' LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop') AND tags.context = 'genres') [0m
|
53
|
+
[4;36;1mScopedTaggedModel Delete all (0.1ms)[0m [0;1mDELETE FROM "scoped_tagged_models" WHERE 1=1[0m
|
54
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
55
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
56
|
+
[4;35;1mScopedTaggedModel Create (0.1ms)[0m [0mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
57
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 2 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
58
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 2, 'ScopedTaggedModel')[0m
|
59
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
60
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
61
|
+
[4;36;1mScopedTaggedModel Create (0.1ms)[0m [0;1mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
62
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 3 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
63
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 3, 'ScopedTaggedModel')[0m
|
64
|
+
[4;35;1mScopedTaggedModel Load IDs For Limited Eager Loading (0.2ms)[0m [0mSELECT DISTINCT "scoped_tagged_models".id FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop') AND tags.context = 'genres') LIMIT 1[0m
|
65
|
+
[4;36;1mScopedTaggedModel Load Including Associations (0.3ms)[0m [0;1mSELECT "scoped_tagged_models"."id" AS t0_r0, "scoped_tagged_models"."name" AS t0_r1, "taggings"."id" AS t1_r0, "taggings"."tag_id" AS t1_r1, "taggings"."taggable_id" AS t1_r2, "taggings"."taggable_type" AS t1_r3, "tags"."id" AS t2_r0, "tags"."name" AS t2_r1, "tags"."context" AS t2_r2 FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" ON "taggings".taggable_id = "scoped_tagged_models".id AND "taggings".taggable_type = 'ScopedTaggedModel' LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop') AND tags.context = 'genres') AND "scoped_tagged_models".id IN (2) [0m
|
66
|
+
[4;35;1mScopedTaggedModel Delete all (0.1ms)[0m [0mDELETE FROM "scoped_tagged_models" WHERE 1=1[0m
|
67
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
68
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
69
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'dance' and context = 'genres') LIMIT 1[0m
|
70
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
71
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'techno' AND "tags".context = 'genres') LIMIT 1[0m
|
72
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'dance' AND "tags".context = 'genres') LIMIT 1[0m
|
73
|
+
[4;36;1mScopedTaggedModel Create (0.1ms)[0m [0;1mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
74
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 4 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
75
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 4, 'ScopedTaggedModel')[0m
|
76
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'techno' AND "tags".context = 'genres') LIMIT 1[0m
|
77
|
+
[4;36;1mTag Create (0.1ms)[0m [0;1mINSERT INTO "tags" ("name", "context") VALUES('techno', 'genres')[0m
|
78
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 4 AND "taggings".tag_id = 3 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
79
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(3, 4, 'ScopedTaggedModel')[0m
|
80
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'dance' AND "tags".context = 'genres') LIMIT 1[0m
|
81
|
+
[4;36;1mTag Create (0.1ms)[0m [0;1mINSERT INTO "tags" ("name", "context") VALUES('dance', 'genres')[0m
|
82
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 4 AND "taggings".tag_id = 4 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
83
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(4, 4, 'ScopedTaggedModel')[0m
|
84
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
85
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
86
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'dance' and context = 'genres') LIMIT 1[0m
|
87
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
88
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'techno' AND "tags".context = 'genres' AND "tags".id <> 3) LIMIT 1[0m
|
89
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'dance' AND "tags".context = 'genres' AND "tags".id <> 4) LIMIT 1[0m
|
90
|
+
[4;35;1mScopedTaggedModel Create (0.1ms)[0m [0mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
91
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 5 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
92
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 5, 'ScopedTaggedModel')[0m
|
93
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 5 AND "taggings".tag_id = 3 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
94
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(3, 5, 'ScopedTaggedModel')[0m
|
95
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 5 AND "taggings".tag_id = 4 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
96
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(4, 5, 'ScopedTaggedModel')[0m
|
97
|
+
[4;36;1mScopedTaggedModel Load IDs For Limited Eager Loading (0.3ms)[0m [0;1mSELECT DISTINCT "scoped_tagged_models".id FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop','techno','dance') AND tags.context = 'genres') LIMIT 1[0m
|
98
|
+
[4;35;1mScopedTaggedModel Load Including Associations (1.0ms)[0m [0mSELECT "scoped_tagged_models"."id" AS t0_r0, "scoped_tagged_models"."name" AS t0_r1, "taggings"."id" AS t1_r0, "taggings"."tag_id" AS t1_r1, "taggings"."taggable_id" AS t1_r2, "taggings"."taggable_type" AS t1_r3, "tags"."id" AS t2_r0, "tags"."name" AS t2_r1, "tags"."context" AS t2_r2 FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" ON "taggings".taggable_id = "scoped_tagged_models".id AND "taggings".taggable_type = 'ScopedTaggedModel' LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop','techno','dance') AND tags.context = 'genres') AND "scoped_tagged_models".id IN (4) [0m
|
99
|
+
[4;36;1mScopedTaggedModel Delete all (0.1ms)[0m [0;1mDELETE FROM "scoped_tagged_models" WHERE 1=1[0m
|
100
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
101
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
102
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'dance' and context = 'genres') LIMIT 1[0m
|
103
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
104
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'techno' AND "tags".context = 'genres' AND "tags".id <> 3) LIMIT 1[0m
|
105
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'dance' AND "tags".context = 'genres' AND "tags".id <> 4) LIMIT 1[0m
|
106
|
+
[4;35;1mScopedTaggedModel Create (0.1ms)[0m [0mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
107
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 6 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
108
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 6, 'ScopedTaggedModel')[0m
|
109
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 6 AND "taggings".tag_id = 3 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
110
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(3, 6, 'ScopedTaggedModel')[0m
|
111
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 6 AND "taggings".tag_id = 4 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
112
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(4, 6, 'ScopedTaggedModel')[0m
|
113
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
114
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
115
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'dance' and context = 'genres') LIMIT 1[0m
|
116
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
117
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'techno' AND "tags".context = 'genres' AND "tags".id <> 3) LIMIT 1[0m
|
118
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'dance' AND "tags".context = 'genres' AND "tags".id <> 4) LIMIT 1[0m
|
119
|
+
[4;36;1mScopedTaggedModel Create (0.1ms)[0m [0;1mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
120
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 7 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
121
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 7, 'ScopedTaggedModel')[0m
|
122
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 7 AND "taggings".tag_id = 3 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
123
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(3, 7, 'ScopedTaggedModel')[0m
|
124
|
+
[4;35;1mTagging Load (0.3ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 7 AND "taggings".tag_id = 4 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
125
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(4, 7, 'ScopedTaggedModel')[0m
|
126
|
+
[4;35;1mScopedTaggedModel Load IDs For Limited Eager Loading (0.2ms)[0m [0mSELECT DISTINCT "scoped_tagged_models".id FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop','techno','dance') AND tags.context = 'genres') LIMIT 1[0m
|
127
|
+
[4;36;1mScopedTaggedModel Load Including Associations (0.9ms)[0m [0;1mSELECT "scoped_tagged_models"."id" AS t0_r0, "scoped_tagged_models"."name" AS t0_r1, "taggings"."id" AS t1_r0, "taggings"."tag_id" AS t1_r1, "taggings"."taggable_id" AS t1_r2, "taggings"."taggable_type" AS t1_r3, "tags"."id" AS t2_r0, "tags"."name" AS t2_r1, "tags"."context" AS t2_r2 FROM "scoped_tagged_models" LEFT OUTER JOIN "taggings" ON "taggings".taggable_id = "scoped_tagged_models".id AND "taggings".taggable_type = 'ScopedTaggedModel' LEFT OUTER JOIN "taggings" base_tags_scoped_tagged_models_join ON ("scoped_tagged_models"."id" = "base_tags_scoped_tagged_models_join"."taggable_id" AND "base_tags_scoped_tagged_models_join"."taggable_type" = 'ScopedTaggedModel') LEFT OUTER JOIN "tags" ON ("tags"."id" = "base_tags_scoped_tagged_models_join"."tag_id") WHERE (tags.name IN ('pop','techno','dance') AND tags.context = 'genres') AND "scoped_tagged_models".id IN (6) [0m
|
128
|
+
[4;35;1mSQL (0.2ms)[0m [0m SELECT name
|
129
|
+
FROM sqlite_master
|
130
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
131
|
+
[0m
|
132
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mDROP TABLE "scoped_tagged_models"[0m
|
133
|
+
[4;35;1mSQL (0.1ms)[0m [0mCREATE TABLE "scoped_tagged_models" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)) [0m
|
134
|
+
[4;36;1mSQL (0.2ms)[0m [0;1m SELECT name
|
135
|
+
FROM sqlite_master
|
136
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
137
|
+
[0m
|
138
|
+
[4;35;1mSQL (0.1ms)[0m [0mDROP TABLE "tags"[0m
|
139
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE TABLE "tags" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "context" varchar(255)) [0m
|
140
|
+
[4;35;1mSQL (0.2ms)[0m [0m SELECT name
|
141
|
+
FROM sqlite_master
|
142
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
143
|
+
[0m
|
144
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mDROP TABLE "taggings"[0m
|
145
|
+
[4;35;1mSQL (0.1ms)[0m [0mCREATE TABLE "taggings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "tag_id" integer, "taggable_id" integer, "taggable_type" varchar(255)) [0m
|
146
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE INDEX "index_tags_on_context_and_name" ON "tags" ("context", "name")[0m
|
147
|
+
[4;35;1mSQL (0.1ms)[0m [0mCREATE INDEX "index_taggings_on_taggable_id_and_taggable_type" ON "taggings" ("taggable_id", "taggable_type")[0m
|
148
|
+
[4;36;1mSQL (0.2ms)[0m [0;1m SELECT name
|
149
|
+
FROM sqlite_master
|
150
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
151
|
+
[0m
|
152
|
+
[4;35;1mSQL (0.1ms)[0m [0mSELECT version FROM "schema_migrations"[0m
|
153
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'Context1') LIMIT 1[0m
|
154
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(1, 1, 'Context1')[0m
|
155
|
+
[4;36;1mTagging Load (0.2ms)[0m [0;1mSELECT * FROM "taggings" LIMIT 1[0m
|
156
|
+
[4;35;1mTagging Load (0.2ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'Context1') LIMIT 1[0m
|
157
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'Context1') LIMIT 1[0m
|
158
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'Context2') LIMIT 1[0m
|
159
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mPRAGMA index_list("taggings")[0m
|
160
|
+
[4;35;1mSQL (0.1ms)[0m [0mPRAGMA index_info('index_taggings_on_taggable_id_and_taggable_type')[0m
|
161
|
+
[4;36;1mTagging Load (0.1ms)[0m [0;1mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'Context2') LIMIT 1[0m
|
162
|
+
[4;35;1mTagging Create (0.1ms)[0m [0mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(1, 1, 'Context2')[0m
|
163
|
+
[4;36;1mTag Delete all (0.1ms)[0m [0;1mDELETE FROM "tags" WHERE 1=1[0m
|
164
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
165
|
+
[4;36;1mTag Create (0.1ms)[0m [0;1mINSERT INTO "tags" ("name", "context") VALUES('rock', 'genres')[0m
|
166
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT * FROM "tags" LIMIT 1[0m
|
167
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
168
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genret') LIMIT 1[0m
|
169
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE ("tags"."name" IS NULL AND "tags".context IS NULL) LIMIT 1[0m
|
170
|
+
[4;35;1mSQL (0.1ms)[0m [0mPRAGMA index_list("tags")[0m
|
171
|
+
[4;36;1mSQL (0.2ms)[0m [0;1mPRAGMA index_info('index_tags_on_context_and_name')[0m
|
172
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock and roll' AND "tags".context = 'genres') LIMIT 1[0m
|
173
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres') LIMIT 1[0m
|
174
|
+
[4;35;1mSQL (0.2ms)[0m [0m SELECT name
|
175
|
+
FROM sqlite_master
|
176
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
177
|
+
[0m
|
178
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mDROP TABLE "scoped_tagged_models"[0m
|
179
|
+
[4;35;1mSQL (0.2ms)[0m [0mCREATE TABLE "scoped_tagged_models" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255)) [0m
|
180
|
+
[4;36;1mSQL (0.4ms)[0m [0;1m SELECT name
|
181
|
+
FROM sqlite_master
|
182
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
183
|
+
[0m
|
184
|
+
[4;35;1mSQL (0.1ms)[0m [0mDROP TABLE "tags"[0m
|
185
|
+
[4;36;1mSQL (0.1ms)[0m [0;1mCREATE TABLE "tags" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "context" varchar(255)) [0m
|
186
|
+
[4;35;1mSQL (0.4ms)[0m [0m SELECT name
|
187
|
+
FROM sqlite_master
|
188
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
189
|
+
[0m
|
190
|
+
[4;36;1mSQL (0.2ms)[0m [0;1mDROP TABLE "taggings"[0m
|
191
|
+
[4;35;1mSQL (2.2ms)[0m [0mCREATE TABLE "taggings" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "tag_id" integer, "taggable_id" integer, "taggable_type" varchar(255)) [0m
|
192
|
+
[4;36;1mSQL (0.2ms)[0m [0;1mCREATE INDEX "index_tags_on_context_and_name" ON "tags" ("context", "name")[0m
|
193
|
+
[4;35;1mSQL (0.2ms)[0m [0mCREATE INDEX "index_taggings_on_taggable_id_and_taggable_type" ON "taggings" ("taggable_id", "taggable_type")[0m
|
194
|
+
[4;36;1mSQL (0.2ms)[0m [0;1m SELECT name
|
195
|
+
FROM sqlite_master
|
196
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
197
|
+
[0m
|
198
|
+
[4;35;1mSQL (0.2ms)[0m [0mSELECT version FROM "schema_migrations"[0m
|
199
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres') LIMIT 1[0m
|
200
|
+
[4;35;1mTag Create (0.1ms)[0m [0mINSERT INTO "tags" ("name", "context") VALUES('pop', 'genres')[0m
|
201
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
202
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
203
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
204
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
205
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'dance' and context = 'genres') LIMIT 1[0m
|
206
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'techno' and context = 'genres') LIMIT 1[0m
|
207
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'house' and context = 'genres') LIMIT 1[0m
|
208
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
209
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
210
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
211
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
212
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
213
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 1) LIMIT 1[0m
|
214
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'disco' AND "tags".context = 'genres') LIMIT 1[0m
|
215
|
+
[4;36;1mScopedTaggedModel Create (0.1ms)[0m [0;1mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
216
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres') LIMIT 1[0m
|
217
|
+
[4;36;1mTag Create (0.1ms)[0m [0;1mINSERT INTO "tags" ("name", "context") VALUES('rock', 'genres')[0m
|
218
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
219
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 1, 'ScopedTaggedModel')[0m
|
220
|
+
[4;35;1mTagging Load (0.2ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
221
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(1, 1, 'ScopedTaggedModel')[0m
|
222
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'disco' AND "tags".context = 'genres') LIMIT 1[0m
|
223
|
+
[4;36;1mTag Create (0.1ms)[0m [0;1mINSERT INTO "tags" ("name", "context") VALUES('disco', 'genres')[0m
|
224
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 1 AND "taggings".tag_id = 3 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
225
|
+
[4;36;1mTagging Create (0.2ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(3, 1, 'ScopedTaggedModel')[0m
|
226
|
+
[4;35;1mTagging Delete all (0.1ms)[0m [0mDELETE FROM "taggings" WHERE ("taggings"."tag_id" = 2 AND "taggings"."taggable_id" = 1 AND "taggings"."taggable_type" = 'ScopedTaggedModel') [0m
|
227
|
+
[4;36;1mScopedTaggedModel Load (0.2ms)[0m [0;1mSELECT * FROM "scoped_tagged_models" WHERE ("scoped_tagged_models"."id" = 1) [0m
|
228
|
+
[4;35;1mSQL (0.2ms)[0m [0mSELECT count(*) AS count_all FROM "tags" INNER JOIN "taggings" ON "tags".id = "taggings".tag_id WHERE (("taggings".taggable_id = 1) AND ("taggings".taggable_type = 'ScopedTaggedModel') AND (("tags"."context" = 'genres'))) [0m
|
229
|
+
[4;36;1mTag Load (0.3ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
230
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
231
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
232
|
+
[4;35;1mTagging Delete all (0.1ms)[0m [0mDELETE FROM "taggings" WHERE ("taggings"."tag_id" = 3 AND "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'ScopedTaggedModel') [0m
|
233
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'rock' AND "tags".context = 'genres' AND "tags".id <> 2) LIMIT 1[0m
|
234
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT "tags".id FROM "tags" WHERE (LOWER("tags"."name") = 'pop' AND "tags".context = 'genres' AND "tags".id <> 1) LIMIT 1[0m
|
235
|
+
[4;36;1mScopedTaggedModel Create (0.1ms)[0m [0;1mINSERT INTO "scoped_tagged_models" ("name") VALUES(NULL)[0m
|
236
|
+
[4;35;1mTagging Load (0.2ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 2 AND "taggings".tag_id = 2 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
237
|
+
[4;36;1mTagging Create (0.1ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(2, 2, 'ScopedTaggedModel')[0m
|
238
|
+
[4;35;1mTagging Load (0.1ms)[0m [0mSELECT "taggings".id FROM "taggings" WHERE ("taggings"."taggable_id" = 2 AND "taggings".tag_id = 1 AND "taggings".taggable_type = 'ScopedTaggedModel') LIMIT 1[0m
|
239
|
+
[4;36;1mTagging Create (0.2ms)[0m [0;1mINSERT INTO "taggings" ("tag_id", "taggable_id", "taggable_type") VALUES(1, 2, 'ScopedTaggedModel')[0m
|
240
|
+
[4;35;1mScopedTaggedModel Load (0.2ms)[0m [0mSELECT * FROM "scoped_tagged_models" WHERE ("scoped_tagged_models"."id" = 2) [0m
|
241
|
+
[4;36;1mSQL (0.2ms)[0m [0;1mSELECT count(*) AS count_all FROM "tags" INNER JOIN "taggings" ON "tags".id = "taggings".tag_id WHERE (("taggings".taggable_id = 2) AND ("taggings".taggable_type = 'ScopedTaggedModel') AND (("tags"."context" = 'genres'))) [0m
|
242
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
243
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
244
|
+
[4;35;1mTag Load (0.2ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
245
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
246
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
247
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'rock' and context = 'genres') LIMIT 1[0m
|
248
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'pop' and context = 'genres') LIMIT 1[0m
|
249
|
+
[4;36;1mTag Load (0.2ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'disco' and context = 'genres') LIMIT 1[0m
|
250
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'funk' and context = 'genres') LIMIT 1[0m
|
251
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'house' and context = 'genres') LIMIT 1[0m
|
252
|
+
[4;35;1mTagging Delete all (0.1ms)[0m [0mDELETE FROM "taggings" WHERE ("taggings"."tag_id" = 2 AND "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'ScopedTaggedModel') [0m
|
253
|
+
[4;36;1mTagging Delete all (0.1ms)[0m [0;1mDELETE FROM "taggings" WHERE ("taggings"."tag_id" = 1 AND "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'ScopedTaggedModel') [0m
|
254
|
+
[4;35;1mTagging Delete all (0.1ms)[0m [0mDELETE FROM "taggings" WHERE ("taggings"."tag_id" = 3 AND "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'ScopedTaggedModel') [0m
|
255
|
+
[4;36;1mTag Load (0.1ms)[0m [0;1mSELECT * FROM "tags" WHERE (name = 'funk' and context = 'genres') LIMIT 1[0m
|
256
|
+
[4;35;1mTag Load (0.1ms)[0m [0mSELECT * FROM "tags" WHERE (name = 'house' and context = 'genres') LIMIT 1[0m
|
@@ -12,7 +12,7 @@ describe "ScopedTaggedModel" do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should include a tags method" do
|
15
|
-
@scoped_model.should respond_to(:
|
15
|
+
@scoped_model.should respond_to(:base_tags)
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should include the genres method" do
|
@@ -81,7 +81,7 @@ describe "ScopedTaggedModel" do
|
|
81
81
|
@scoped_model.genre_list << tag
|
82
82
|
@scoped_model.save!
|
83
83
|
|
84
|
-
ar_check = ScopedTaggedModel.all(:conditions => ['tags.name IN (?) AND tags.context = ?', tag, 'genres'], :include => [:taggings, :
|
84
|
+
ar_check = ScopedTaggedModel.all(:conditions => ['tags.name IN (?) AND tags.context = ?', tag, 'genres'], :include => [:taggings, :base_tags])
|
85
85
|
ar_check.size.should == 1
|
86
86
|
|
87
87
|
ScopedTaggedModel.methods.should include('tagged_with_genres')
|
@@ -2,60 +2,76 @@ require File.dirname(__FILE__) + '/../spec_helper'
|
|
2
2
|
|
3
3
|
|
4
4
|
describe Tagging do
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
reload_database
|
8
|
+
Tagging.create!(:tag_id => 1, :taggable_id => 1, :taggable_type => "Context1")
|
9
|
+
end
|
10
|
+
|
7
11
|
it { should belong_to(:tag) }
|
8
12
|
it { should belong_to(:taggable) }
|
9
|
-
it { should validate_uniqueness_of(:taggable_id).scoped_to(:tag_id) }
|
10
|
-
|
13
|
+
it { should validate_uniqueness_of(:taggable_id).scoped_to(:tag_id, :taggable_type) }
|
14
|
+
|
11
15
|
it { should allow_mass_assignment_of(:taggable_id)
|
12
16
|
should allow_mass_assignment_of(:taggable_type)
|
13
17
|
should allow_mass_assignment_of(:tag_id) }
|
14
|
-
|
18
|
+
|
15
19
|
it { should_not allow_mass_assignment_of(:created_at)
|
16
20
|
should_not allow_mass_assignment_of(:updated_at) }
|
17
|
-
|
21
|
+
|
18
22
|
it { should have_db_index([:taggable_id, :taggable_type]) }
|
23
|
+
|
24
|
+
it "should validate uniqueness of taggable_id scoped to tag_id and taggable type" do
|
25
|
+
proc {
|
26
|
+
Tagging.create!(:tag_id => 1, :taggable_id => 1, :taggable_type => "Context2")
|
27
|
+
}.should_not raise_error
|
28
|
+
end
|
29
|
+
|
19
30
|
end
|
20
31
|
|
21
32
|
|
22
33
|
describe Tag do
|
23
|
-
before(:all)
|
24
|
-
|
34
|
+
before(:all) do
|
35
|
+
Tag.delete_all
|
36
|
+
Tag.create!(:name => 'rock', :context => 'genres')
|
37
|
+
end
|
38
|
+
|
25
39
|
it { should have_many(:taggings).dependent(:delete_all) }
|
26
|
-
|
40
|
+
|
27
41
|
it { should validate_uniqueness_of(:name).scoped_to(:context).case_insensitive }
|
28
42
|
it { should validate_presence_of(:context) }
|
29
|
-
|
43
|
+
|
30
44
|
it { should allow_mass_assignment_of(:name)
|
31
45
|
should allow_mass_assignment_of(:context) }
|
32
|
-
|
46
|
+
|
33
47
|
it { should_not allow_mass_assignment_of(:created_at)
|
34
48
|
should_not allow_mass_assignment_of(:updated_at) }
|
35
|
-
|
49
|
+
|
36
50
|
it { should have_db_index([:context, :name]) }
|
37
|
-
|
51
|
+
|
38
52
|
it "should trim and squeeze spaces from name and context before validation" do
|
39
53
|
t = Tag.new(:name => ' rock and roll', :context => ' genres ')
|
40
54
|
t.valid?
|
41
55
|
t.name.should == 'rock and roll'
|
42
|
-
t.context.should == 'genres'
|
56
|
+
t.context.should == 'genres'
|
43
57
|
end
|
44
|
-
|
58
|
+
|
45
59
|
it "should lowercase the name and context before validation" do
|
46
60
|
t = Tag.new(:name => 'POP', :context => 'GENRES')
|
47
61
|
t.valid?
|
48
62
|
t.name.should == 'pop'
|
49
63
|
t.context.should == 'genres'
|
50
64
|
end
|
51
|
-
|
65
|
+
|
52
66
|
it "should recognize that it is equal to another tag with the same name and context" do
|
53
67
|
t = Tag.new(:name => 'pop', :context => 'genres')
|
54
68
|
s = Tag.new(:name => 'pop', :context => 'genres')
|
55
69
|
t.should == s
|
56
70
|
end
|
57
|
-
|
71
|
+
|
58
72
|
it "#find_or_new_by_name_ane_context" do
|
73
|
+
reload_database # or we will have duplication
|
74
|
+
|
59
75
|
Tag.create!(:name => 'pop', :context => 'genres')
|
60
76
|
s = Tag.find_or_new_by_name_and_context('pop', 'genres')
|
61
77
|
s.new_record?.should be_false
|
data/spec/spec_helper.rb
CHANGED
@@ -1,25 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
1
3
|
require 'spec'
|
2
4
|
require 'shoulda'
|
3
5
|
|
6
|
+
require 'sqlite3' # So we don't get Encoding errors which we get with plain sqlite3
|
7
|
+
|
4
8
|
require 'active_support'
|
5
9
|
require 'active_record'
|
6
10
|
|
7
11
|
require 'scoped-tags'
|
8
12
|
|
9
|
-
Spec::Runner.configure do |config|
|
10
|
-
config.include(Shoulda::ActiveRecord::Matchers, :type => :model)
|
11
|
-
end
|
12
13
|
|
13
|
-
|
14
|
+
def reload_database
|
15
|
+
load(File.expand_path('../schema.rb', __FILE__))
|
16
|
+
end
|
14
17
|
|
15
|
-
|
16
|
-
ActiveRecord::
|
17
|
-
"adapter" => "sqlite3", "database" => TEST_DATABASE_FILE
|
18
|
-
)
|
19
|
-
|
20
|
-
load('schema.rb')
|
18
|
+
Spec::Runner.configure do |config|
|
19
|
+
config.include(Shoulda::ActiveRecord::Matchers, :type => :model)
|
21
20
|
|
22
|
-
|
21
|
+
config.before(:suite) do
|
22
|
+
ActiveRecord::Base.logger = Logger.new(File.expand_path("../debug.log", __FILE__))
|
23
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
24
|
+
reload_database
|
25
|
+
end
|
26
|
+
end
|
23
27
|
|
24
28
|
class ScopedTaggedModel < ActiveRecord::Base
|
25
29
|
scoped_tags :genres
|
data/spec/test.sqlite3
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scoped-tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Josh Kalderimis
|
@@ -9,19 +14,23 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-03-31 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: activerecord
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 3
|
30
|
+
- 3
|
23
31
|
version: 2.3.3
|
24
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
description:
|
26
35
|
email: josh.kalderimis@gmail.com
|
27
36
|
executables: []
|
@@ -33,9 +42,8 @@ extra_rdoc_files: []
|
|
33
42
|
files:
|
34
43
|
- MIT-LICENSE
|
35
44
|
- VERSION.yml
|
36
|
-
- generators/scoped_tags_migration/
|
45
|
+
- generators/scoped_tags_migration/scoped_tags_migration_generator.rb
|
37
46
|
- generators/scoped_tags_migration/templates/migration.rb
|
38
|
-
- install.rb
|
39
47
|
- lib/scoped-tags.rb
|
40
48
|
- lib/scoped_tags/active_record_additions.rb
|
41
49
|
- lib/scoped_tags/tag.rb
|
@@ -43,7 +51,6 @@ files:
|
|
43
51
|
- lib/scoped_tags/tag_list_proxy.rb
|
44
52
|
- lib/scoped_tags/tagging.rb
|
45
53
|
- readme.md
|
46
|
-
- uninstall.rb
|
47
54
|
has_rdoc: true
|
48
55
|
homepage: http://github.com/joshk/scoped-tags
|
49
56
|
licenses: []
|
@@ -57,18 +64,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
64
|
requirements:
|
58
65
|
- - ">="
|
59
66
|
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
60
69
|
version: "0"
|
61
|
-
version:
|
62
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
71
|
requirements:
|
64
72
|
- - ">="
|
65
73
|
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
66
76
|
version: "0"
|
67
|
-
version:
|
68
77
|
requirements: []
|
69
78
|
|
70
79
|
rubyforge_project:
|
71
|
-
rubygems_version: 1.3.
|
80
|
+
rubygems_version: 1.3.6
|
72
81
|
signing_key:
|
73
82
|
specification_version: 3
|
74
83
|
summary: Scoped tagging plugin for your rails models which keeps your associations in sync with your tag arrays
|
data/install.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Install hook code here
|
data/uninstall.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
# Uninstall hook code here
|