tag_echidna 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.
@@ -0,0 +1,2 @@
1
+ Gemfile.lock
2
+ spec/internal/db/*.sqlite
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,6 @@
1
+ class TagEchidna::Tag < ActiveRecord::Base
2
+ has_many :taggings, :class_name => 'TagEchidna::Tagging',
3
+ :dependent => :destroy
4
+
5
+ validates :name, :presence => true, :uniqueness => true
6
+ end
@@ -0,0 +1,7 @@
1
+ class TagEchidna::Tagging < ActiveRecord::Base
2
+ belongs_to :taggable, :polymorphic => true
3
+ belongs_to :tag, :class_name => 'TagEchidna::Tag'
4
+
5
+ validates :taggable, :presence => true
6
+ validates :tag, :presence => true
7
+ end
@@ -0,0 +1,27 @@
1
+ class TagTables < ActiveRecord::Migration
2
+ def up
3
+ create_table :taggings do |t|
4
+ t.integer :tag_id, :null => false
5
+ t.integer :taggable_id, :null => false
6
+ t.string :taggable_type, :null => false
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :taggings, :tag_id
11
+ add_index :taggings, [:taggable_type, :taggable_id]
12
+ add_index :taggings, [:taggable_type, :taggable_id, :tag_id],
13
+ :unique => true, :name => 'unique_taggings'
14
+
15
+ create_table :tags do |t|
16
+ t.string :name, :null => false
17
+ t.timestamps
18
+ end
19
+
20
+ add_index :tags, :name, :unique => true
21
+ end
22
+
23
+ def down
24
+ drop_table :tags
25
+ drop_table :taggings
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module TagEchidna
2
+ #
3
+ end
4
+
5
+ require 'tag_echidna/active_record'
6
+ require 'tag_echidna/engine'
7
+ require 'tag_echidna/tag_names'
@@ -0,0 +1,26 @@
1
+ module TagEchidna::ActiveRecord
2
+ def self.included(base)
3
+ base.extend TagEchidna::ActiveRecord::ClassMethods
4
+ end
5
+
6
+ module ClassMethods
7
+ def has_many_tags
8
+ has_many :taggings, :class_name => 'TagEchidna::Tagging',
9
+ :as => :taggable, :dependent => :destroy
10
+ has_many :tags, :class_name => 'TagEchidna::Tag',
11
+ :through => :taggings
12
+ end
13
+ end
14
+
15
+ def tag_names
16
+ @tag_names ||= TagEchidna::TagNames.new self
17
+ end
18
+
19
+ def tag_names=(names)
20
+ if names.is_a?(TagEchidna::TagNames)
21
+ @tag_names = names
22
+ else
23
+ @tag_names = TagEchidna::TagNames.new_with_names self, names
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'rails/engine'
2
+
3
+ class TagEchidna::Engine < Rails::Engine
4
+ engine_name :tag_echidna
5
+
6
+ ActiveSupport.on_load :active_record do
7
+ include TagEchidna::ActiveRecord
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ class TagEchidna::TagNames
2
+ include Enumerable
3
+
4
+ def self.new_with_names(taggable, names)
5
+ tag_names = new(taggable)
6
+ tag_names.clear
7
+ names.each { |name| tag_names << name }
8
+ tag_names
9
+ end
10
+
11
+ def initialize(taggable)
12
+ @taggable = taggable
13
+ end
14
+
15
+ def to_a
16
+ taggable.tags.collect &:name
17
+ end
18
+
19
+ def +(array)
20
+ array.each { |name| self.<< name }
21
+ self
22
+ end
23
+
24
+ def -(array)
25
+ array.each { |name| self.delete name }
26
+ self
27
+ end
28
+
29
+ def <<(name)
30
+ tag = TagEchidna::Tag.where(:name => name).first ||
31
+ TagEchidna::Tag.create(:name => name)
32
+
33
+ taggable.tags << tag
34
+ end
35
+
36
+ def clear
37
+ taggable.tags.clear
38
+ end
39
+
40
+ def delete(name)
41
+ taggable.tags.delete TagEchidna::Tag.where(:name => name).first
42
+ end
43
+
44
+ def each(&block)
45
+ to_a.each &block
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :taggable
51
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Managing tags via names" do
4
+ let(:article) { Article.create }
5
+
6
+ it "returns tag names" do
7
+ article.tags << TagEchidna::Tag.create(:name => 'melbourne')
8
+
9
+ article.tag_names.to_a.should == ['melbourne']
10
+ end
11
+
12
+ it "adds tags via their names" do
13
+ article.tag_names << 'melbourne'
14
+
15
+ article.tags.collect(&:name).should == ['melbourne']
16
+ end
17
+
18
+ it "accepts a completely new set of tags" do
19
+ article.tag_names = ['portland', 'oregon']
20
+
21
+ article.tags.collect(&:name).should == ['portland', 'oregon']
22
+ end
23
+
24
+ it "enumerates through tag names" do
25
+ article.tag_names = ['melbourne', 'victoria']
26
+ names = []
27
+
28
+ article.tag_names.each do |name|
29
+ names << name
30
+ end
31
+
32
+ names.should == ['melbourne', 'victoria']
33
+ end
34
+
35
+ it "does not allow duplication of tags" do
36
+ existing = Article.create
37
+ existing.tags << TagEchidna::Tag.create(:name => 'portland')
38
+
39
+ article.tag_names = ['portland']
40
+
41
+ existing.tag_ids.should == article.tag_ids
42
+ end
43
+
44
+ it "appends tag names" do
45
+ article.tag_names = ['portland']
46
+ article.tag_names += ['oregon', 'ruby']
47
+
48
+ article.tags.collect(&:name).should == ['portland', 'oregon', 'ruby']
49
+ end
50
+
51
+ it "removes a single tag name" do
52
+ article.tag_names = ['portland', 'oregon']
53
+ article.tag_names.delete 'oregon'
54
+
55
+ article.tags.collect(&:name).should == ['portland']
56
+ end
57
+
58
+ it "removes tag names" do
59
+ article.tag_names = ['portland', 'oregon', 'ruby']
60
+ article.tag_names -= ['oregon', 'ruby']
61
+
62
+ article.tags.collect(&:name).should == ['portland']
63
+ end
64
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Adding and removing tags' do
4
+ let(:article) { Article.create }
5
+ let(:pancakes) { TagEchidna::Tag.create :name => 'pancakes' }
6
+
7
+ it "stores new tags" do
8
+ article.tags << pancakes
9
+
10
+ article.tags.reload.should == [pancakes]
11
+ end
12
+
13
+ it "removes existing tags" do
14
+ article.tags << pancakes
15
+
16
+ article.tags.delete pancakes
17
+
18
+ article.tags.reload.should == []
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ class Article < ActiveRecord::Base
2
+ has_many_tags
3
+ end
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/combustion_test.sqlite
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :articles, :force => true do |t|
3
+ t.string :title
4
+ t.timestamps
5
+ end
6
+ end
@@ -0,0 +1 @@
1
+ *.log
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+
3
+ Bundler.require :default, :development
4
+
5
+ Combustion.initialize! :active_record
6
+
7
+ require 'rspec/rails'
8
+
9
+ RSpec.configure do |config|
10
+ config.use_transactional_fixtures = true
11
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |s|
3
+ s.name = 'tag_echidna'
4
+ s.version = '0.1.0'
5
+ s.authors = ['Pat Allan']
6
+ s.email = ['pat@freelancing-gods.com']
7
+ s.homepage = 'https://github.com/pat/tag_echidna'
8
+ s.summary = 'The Tag Echidna'
9
+ s.description = 'This friendly echidna gives you tags in your Rails app.'
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
13
+ s.require_paths = ['lib']
14
+
15
+ s.add_runtime_dependency 'activerecord', '>= 3.2.0'
16
+ s.add_development_dependency 'combustion', '~> 0.4.0'
17
+ s.add_development_dependency 'rspec-rails', '~> 2.13'
18
+ s.add_development_dependency 'sqlite3', '~> 1.3.7'
19
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tag_echidna
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pat Allan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: combustion
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.4.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec-rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.13'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.13'
62
+ - !ruby/object:Gem::Dependency
63
+ name: sqlite3
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.3.7
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.3.7
78
+ description: This friendly echidna gives you tags in your Rails app.
79
+ email:
80
+ - pat@freelancing-gods.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - Gemfile
87
+ - app/models/tag_echidna/tag.rb
88
+ - app/models/tag_echidna/tagging.rb
89
+ - db/migrate/1_tag_tables.rb
90
+ - lib/tag_echidna.rb
91
+ - lib/tag_echidna/active_record.rb
92
+ - lib/tag_echidna/engine.rb
93
+ - lib/tag_echidna/tag_names.rb
94
+ - spec/acceptance/tag_names_spec.rb
95
+ - spec/acceptance/tags_spec.rb
96
+ - spec/internal/app/models/article.rb
97
+ - spec/internal/config/database.yml
98
+ - spec/internal/db/schema.rb
99
+ - spec/internal/log/.gitignore
100
+ - spec/spec_helper.rb
101
+ - tag_echidna.gemspec
102
+ homepage: https://github.com/pat/tag_echidna
103
+ licenses: []
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 1.8.23
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: The Tag Echidna
126
+ test_files: []
127
+ has_rdoc: