polytag 0.0.4 → 0.1.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.
Files changed (45) hide show
  1. data/.DS_Store +0 -0
  2. data/.pryrc +27 -0
  3. data/.rspec +3 -1
  4. data/README.md +26 -4
  5. data/lib/.DS_Store +0 -0
  6. data/lib/generators/polytag/.DS_Store +0 -0
  7. data/lib/generators/polytag/install/.DS_Store +0 -0
  8. data/lib/generators/polytag/install/templates/create_polytag_tables.rb +25 -11
  9. data/lib/polytag.rb +221 -58
  10. data/lib/polytag/concerns/tag_owner.rb +31 -0
  11. data/lib/polytag/concerns/tag_owner/association_extensions.rb +15 -0
  12. data/lib/polytag/concerns/tag_owner/association_extensions/owned_tags.rb +16 -0
  13. data/lib/polytag/concerns/tag_owner/class_helpers.rb +25 -0
  14. data/lib/polytag/concerns/tag_owner/model_helpers.rb +78 -0
  15. data/lib/polytag/concerns/taggable.rb +24 -0
  16. data/lib/polytag/concerns/taggable/association_extensions.rb +15 -0
  17. data/lib/polytag/concerns/taggable/class_helpers.rb +16 -0
  18. data/lib/polytag/concerns/taggable/model_helpers.rb +60 -0
  19. data/lib/polytag/connection.rb +27 -0
  20. data/lib/polytag/exceptions.rb +7 -0
  21. data/lib/polytag/tag.rb +6 -24
  22. data/lib/polytag/tag_group.rb +8 -46
  23. data/lib/polytag/version.rb +1 -1
  24. data/polytag.gemspec +7 -3
  25. data/spec/spec_helper.rb +15 -10
  26. data/spec/specs/owner_spec.rb +104 -0
  27. data/spec/specs/taggable_with_owner_spec.rb +120 -0
  28. data/spec/specs/taggable_without_owner_spec.rb +59 -0
  29. data/spec/support/active_record.rb +6 -6
  30. data/spec/support/owner.rb +1 -1
  31. data/spec/support/taggable.rb +3 -0
  32. metadata +115 -46
  33. checksums.yaml +0 -7
  34. data/circle.yml +0 -3
  35. data/lib/polytag/tag_group/owner.rb +0 -17
  36. data/lib/polytag/tag_relation.rb +0 -15
  37. data/spec/specs/polytag_querying_spec.rb +0 -56
  38. data/spec/specs/polytag_test_taggable_four_spec.rb +0 -54
  39. data/spec/specs/polytag_test_taggable_one_spec.rb +0 -47
  40. data/spec/specs/polytag_test_taggable_three_spec.rb +0 -51
  41. data/spec/specs/polytag_test_taggable_two_spec.rb +0 -51
  42. data/spec/support/test_taggable_four.rb +0 -7
  43. data/spec/support/test_taggable_one.rb +0 -3
  44. data/spec/support/test_taggable_three.rb +0 -8
  45. data/spec/support/test_taggable_two.rb +0 -7
@@ -0,0 +1,31 @@
1
+ module Polytag
2
+ module Concerns
3
+ module TagOwner
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ include ClassHelpers
8
+ end
9
+
10
+ included do
11
+ has_many :tag_groups,
12
+ class_name: '::Polytag::TagGroup',
13
+ dependent: :destroy,
14
+ as: :owner do
15
+ include AssociationExtensions
16
+ end
17
+
18
+ has_many :owned_tags,
19
+ class_name: '::Polytag::Connection',
20
+ dependent: :destroy,
21
+ as: :owner do
22
+ include AssociationExtensions::OwnedTags
23
+ end
24
+ end
25
+
26
+ def tag_group
27
+ ModelHelpers.new(self)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ module Polytag
2
+ module Concerns
3
+ module TagOwner
4
+ module AssociationExtensions
5
+ def default
6
+ where(name: :default).first
7
+ end
8
+
9
+ def get(group)
10
+ where(name: "#{group}".strip).first
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Polytag
2
+ module Concerns
3
+ module TagOwner
4
+ module AssociationExtensions
5
+ module OwnedTags
6
+ def get(tag, args = {})
7
+ tag_group_query = ::Polytag.get(:tag_group, nil, args.merge(owner: proxy_association.owner))
8
+ query = ::Polytag.get(:tag, nil, tag).where(polytag_tag_group_id: tag_group_query.select(:id))
9
+ where(polytag_connections: {polytag_tag_group_id: query.select(:id)})
10
+ end
11
+ alias find get
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module Polytag
2
+ module Concerns
3
+ module TagOwner
4
+ module ClassHelpers
5
+ def has_tag_group(group)
6
+ query = ::Polytag.get foc: nil,
7
+ tag_group: group
8
+
9
+ includes(:tag_groups).where(polytag_tag_groups: {id: query.select(:id)})
10
+ end
11
+
12
+ def has_tag(tag, group = nil)
13
+ if group
14
+ tag_group_query = ::Polytag.get(:tag_group, nil, group).select(:id)
15
+ query = ::Polytag.get(:tag, nil, tag).where(polytag_tag_group_id: tag_group_query)
16
+ else
17
+ query = ::Polytag.get(:tag, nil, tag)
18
+ end
19
+
20
+ includes(:tag_groups).where(polytag_tag_groups: {id: query.select(:id)})
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,78 @@
1
+ module Polytag
2
+ module Concerns
3
+ module TagOwner
4
+ class ModelHelpers
5
+ def initialize(owner)
6
+ @owner = owner
7
+ end
8
+
9
+ def new(group)
10
+ ::Polytag.get tag_group: group,
11
+ foc: :first_or_create,
12
+ owner: @owner
13
+ end
14
+ alias add new
15
+ alias create new
16
+
17
+ def del(group)
18
+ return false unless exist?(group)
19
+ group = ::Polytag.get tag_group: group,
20
+ owner: @owner,
21
+ foc: :first
22
+
23
+ group.destroy
24
+ true
25
+ end
26
+ alias delete del
27
+ alias remove del
28
+ alias destroy del
29
+
30
+ def exist?(group)
31
+ group = ::Polytag.get tag_group: group,
32
+ owner: @owner,
33
+ foc: :first
34
+
35
+ # Return the result
36
+ group.is_a?(::Polytag::TagGroup)
37
+ rescue ActiveRecord::RecordNotFound
38
+ false
39
+ end
40
+
41
+ def new_tag(tag, group = nil)
42
+ ::Polytag.get tag_group: group,
43
+ foc: :first_or_create,
44
+ owner: @owner,
45
+ tag: tag
46
+ end
47
+ alias add_tag new_tag
48
+ alias create_tag new_tag
49
+
50
+ def del_tag(tag, group = nil)
51
+ return false unless owns_tag?(group, tag)
52
+ tag = ::Polytag.get tag_group: group,
53
+ owner: @owner,
54
+ foc: :first,
55
+ tag: tag
56
+
57
+ tag.destroy
58
+ true
59
+ end
60
+ alias delete_tag del_tag
61
+ alias remove_tag del_tag
62
+ alias destroy_tag del_tag
63
+
64
+ def owns_tag?(tag, group = nil)
65
+ tag = ::Polytag.get tag_group: group,
66
+ owner: @owner,
67
+ foc: :first,
68
+ tag: tag
69
+
70
+ # Return the result
71
+ tag.is_a?(::Polytag::Tag)
72
+ rescue ActiveRecord::RecordNotFound
73
+ false
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,24 @@
1
+ module Polytag
2
+ module Concerns
3
+ module Taggable
4
+ extend ActiveSupport::Concern
5
+
6
+ module ClassMethods
7
+ include ClassHelpers
8
+ end
9
+
10
+ included do
11
+ has_many :tags,
12
+ class_name: '::Polytag::Connection',
13
+ dependent: :destroy,
14
+ as: :tagged do
15
+ include AssociationExtensions
16
+ end
17
+ end
18
+
19
+ def tag
20
+ ModelHelpers.new(self)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module Polytag
2
+ module Concerns
3
+ module Taggable
4
+ module AssociationExtensions
5
+ def tag_group(args = {})
6
+ includes(:tag_group).merge(::Polytag.get(tag_group: args[:tag_group], owner: args[:tag_group_owner]))
7
+ end
8
+
9
+ def no_tag_group
10
+ where(polytag_tag_group_id: nil, owner_type: nil, owner_id: nil)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Polytag
2
+ module Concerns
3
+ module Taggable
4
+ module ClassHelpers
5
+ def has_tag(tag, args = {})
6
+ query = ::Polytag.get tag: tag,
7
+ tag_group: args[:tag_group],
8
+ owner: args[:tag_group_owner],
9
+ foc: nil
10
+
11
+ includes(:tags).where(polytag_connections: {polytag_tag_id: query.select(:id)})
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,60 @@
1
+ module Polytag
2
+ module Concerns
3
+ module Taggable
4
+ class ModelHelpers
5
+ def initialize(owner)
6
+ @owner = owner
7
+ end
8
+
9
+ def new(tag, args = {})
10
+ ::Polytag.get tag: tag,
11
+ foc: :first_or_create,
12
+ tag_group: args[:tag_group],
13
+ owner: args[:tag_group_owner],
14
+ tagged: @owner
15
+ end
16
+ alias add new
17
+ alias create new
18
+
19
+ def del(tag, args = {})
20
+ return false unless exist?(tag, args)
21
+ tag = ::Polytag.get tag: tag,
22
+ tag_group: args[:tag_group],
23
+ owner: args[:tag_group_owner],
24
+ tagged: @owner,
25
+ foc: :first
26
+
27
+ tag.destroy
28
+ true
29
+ end
30
+ alias delete del
31
+ alias remove del
32
+ alias destroy del
33
+
34
+ def get(tag, args = {})
35
+ return false unless exist?(tag, args)
36
+ ::Polytag.get tag: tag,
37
+ tag_group: args[:tag_group],
38
+ owner: args[:tag_group_owner],
39
+ tagged: @owner,
40
+ foc: :first
41
+ end
42
+ alias find get
43
+
44
+ def exist?(tag, args = {})
45
+ tag = ::Polytag.get tag: tag,
46
+ tag_group: args[:tag_group],
47
+ owner: args[:tag_group_owner],
48
+ tagged: @owner,
49
+ foc: :first
50
+
51
+ # Return the result
52
+ tag.is_a?(::Polytag::Connection)
53
+ rescue ActiveRecord::RecordNotFound
54
+ false
55
+ end
56
+ alias has_tag? exist?
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,27 @@
1
+ class Polytag::Connection < ActiveRecord::Base
2
+ self.table_name = :polytag_connections
3
+
4
+ belongs_to :tag,
5
+ class_name: '::Polytag::Tag',
6
+ foreign_key: :polytag_tag_id
7
+
8
+ belongs_to :tag_group,
9
+ class_name: '::Polytag::TagGroup',
10
+ foreign_key: :polytag_tag_group_id
11
+
12
+ belongs_to :owner,
13
+ polymorphic: true
14
+
15
+ belongs_to :tagged,
16
+ polymorphic: true
17
+
18
+ delegate :name,
19
+ to: :tag
20
+
21
+ # Destroy the tag if it is no longer in use
22
+ after_destroy do
23
+ if ! tag.tag_group && tag.tag_connections.count < 1
24
+ tag.destroy
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module Polytag
2
+ class CantFindPolytagModel < ActiveRecord::RecordNotFound; end
3
+ class NotTagOwnerOrTaggable < Exception; end
4
+ class NotPolytagModel < Exception; end
5
+ class NotTagOwner < Exception; end
6
+ class NotTaggable < Exception; end
7
+ end
@@ -1,29 +1,11 @@
1
1
  class Polytag::Tag < ActiveRecord::Base
2
2
  self.table_name = :polytag_tags
3
- belongs_to :polytag_tag_group, class_name: '::Polytag::TagGroup'
4
- belongs_to :tag_group, class_name: '::Polytag::TagGroup',
5
- foreign_key: :polytag_tag_group_id
6
3
 
7
- has_many :polytag_tag_relations, class_name: '::Polytag::TagRelation',
8
- foreign_key: :polytag_tag_id,
9
- dependent: :destroy
4
+ has_many :tag_connections,
5
+ class_name: '::Polytag::Connection',
6
+ foreign_key: :polytag_tag_id
10
7
 
11
- has_many :relations, class_name: '::Polytag::TagRelation',
12
- foreign_key: :polytag_tag_id,
13
- dependent: :destroy
14
-
15
- # Indiscrimanetly get
16
- # the tagged models
17
- def tagged
18
- polytag_tag_relations.tagged.flatten
19
- end
20
-
21
- # Cleanup group if there are
22
- # no more tags left on the group
23
- after_destroy do
24
- polytag_tag_group.reload
25
- if polytag_tag_group.tags.count < 0
26
- polytag_tag_group.destroy
27
- end
28
- end
8
+ belongs_to :tag_group,
9
+ class_name: '::Polytag::TagGroup',
10
+ foreign_key: :polytag_tag_group_id
29
11
  end
@@ -1,52 +1,14 @@
1
1
  class Polytag::TagGroup < ActiveRecord::Base
2
2
  self.table_name = :polytag_tag_groups
3
3
 
4
- has_many :polytag_tag, class_name: '::Polytag::Tag',
5
- foreign_key: :polytag_tag_group_id,
6
- dependent: :destroy
4
+ has_many :tag_connections,
5
+ class_name: '::Polytag::Connection',
6
+ foreign_key: :polytag_tag_group_id
7
7
 
8
- has_many :tag, class_name: '::Polytag::Tag',
9
- foreign_key: :polytag_tag_group_id,
10
- dependent: :destroy
8
+ has_many :tags,
9
+ class_name: '::Polytag::Tag',
10
+ foreign_key: :polytag_tag_group_id
11
11
 
12
- belongs_to :owner, polymorphic: true
13
-
14
- # Cleanup tag if there are
15
- # no more relations left on the tag
16
- after_destroy do
17
- tag.reload
18
- if tag.relations.count < 0
19
- tag.destroy
20
- end
21
- end
22
-
23
- class << self
24
- def search_by_hash(hash = {})
25
- return self if hash.empty?
26
- conditions = {}
27
-
28
- # Query by owner information
29
- if hash[:owner]
30
- conditions.merge!(owner_type: "#{hash[:owner].class}")
31
- conditions.merge!(owner_id: hash[:owner].id)
32
- else
33
- if hash[:owner_type]
34
- conditions.merge!(owner_type: "#{hash[:owner_type]}")
35
- conditions.merge!(owner_id: hash[:owner_id]) if hash[:owner_id]
36
- end
37
- end
38
-
39
- # Query by tag group name
40
- conditions.merge!(name: "#{hash[:name]}") if hash[:name]
41
-
42
- # Query by tag group id
43
- conditions.merge!(id: hash[:id]) if hash[:id]
44
-
45
- where(conditions)
46
- end
47
-
48
- def find_by_hash(hash = {})
49
- search_by_hash(hash).first
50
- end
51
- end
12
+ belongs_to :owner,
13
+ polymorphic: true
52
14
  end
@@ -1,3 +1,3 @@
1
1
  module Polytag
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -19,11 +19,15 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "awesome_print"
23
+ spec.add_development_dependency "database_cleaner"
23
24
  spec.add_development_dependency "rspec"
24
25
  spec.add_development_dependency "rspec-rails"
26
+ spec.add_development_dependency "fuubar"
25
27
  spec.add_development_dependency "sqlite3"
26
- spec.add_development_dependency "awesome_print"
27
- spec.add_dependency "activerecord", ">= 3.2.13"
28
+ spec.add_development_dependency "rake"
29
+ spec.add_development_dependency "pry"
30
+
28
31
  spec.add_dependency "activesupport", ">= 3.2.13"
32
+ spec.add_dependency "activerecord", ">= 3.2.13"
29
33
  end