easy_tag 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.md +159 -0
- data/Rakefile +27 -0
- data/app/models/easy_tag/tag.rb +29 -0
- data/app/models/easy_tag/tag_context.rb +19 -0
- data/app/models/easy_tag/tagging.rb +5 -0
- data/app/models/easy_tag.rb +8 -0
- data/config/routes.rb +2 -0
- data/lib/easy_tag/engine.rb +4 -0
- data/lib/easy_tag/taggable.rb +141 -0
- data/lib/easy_tag/tagger.rb +36 -0
- data/lib/easy_tag/version.rb +3 -0
- data/lib/easy_tag.rb +36 -0
- data/lib/generators/easy_tag/migration/migration_generator.rb +21 -0
- data/lib/generators/easy_tag/migration/templates/migration.rb +34 -0
- data/lib/tasks/easy_tag_tasks.rake +4 -0
- metadata +93 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
## EasyTag
|
2
|
+
|
3
|
+
This is a very simple tagging system for Rails. Because it is so simple, you should fork and modify it for your own purpose.
|
4
|
+
|
5
|
+
This gem is used in my other projects, thus, it will be kept updated, albeit slowly.
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
rails generate easy_tag:migration
|
10
|
+
rake db:migrate
|
11
|
+
rake db:test:prepare
|
12
|
+
|
13
|
+
## Basic Usage
|
14
|
+
|
15
|
+
EasyTag offers very few methods to manipulate tags. You mostly work
|
16
|
+
on adding and removing tags on taggable. For advanced usage, try
|
17
|
+
work on the assocation of EasyTag models, or fork this project
|
18
|
+
and extend its functionality.
|
19
|
+
|
20
|
+
### Tagger
|
21
|
+
|
22
|
+
You need to define __acts_as_tagger__ in tagger model like this:
|
23
|
+
|
24
|
+
class User < ActiveRecord::Base
|
25
|
+
acts_as_tagger
|
26
|
+
end
|
27
|
+
|
28
|
+
Only **ONE** model can be tagger.
|
29
|
+
|
30
|
+
You can find tags of tagger:
|
31
|
+
|
32
|
+
tagger.tags
|
33
|
+
|
34
|
+
Tags in a context can be retrieved like this:
|
35
|
+
|
36
|
+
tagger.tags.in_context(:skill)
|
37
|
+
|
38
|
+
### Taggable
|
39
|
+
|
40
|
+
You need to define __acts_as_taggable__ in tagger model like this:
|
41
|
+
|
42
|
+
class Post < ActiveRecord::Base
|
43
|
+
acts_as_taggable
|
44
|
+
end
|
45
|
+
|
46
|
+
You can manage tags of taggable
|
47
|
+
|
48
|
+
taggable.tags: return tags associated with this taggable
|
49
|
+
taggable.tags=: set tags of this taggable without context and tagger
|
50
|
+
taggable.set_tags: set tags of this taggable and remove old tags
|
51
|
+
|
52
|
+
All of setting methods (except tags=) can add :context and :tagger as optioanl parameters.
|
53
|
+
For example:
|
54
|
+
|
55
|
+
taggable.set_tags ['ruby', 'rvm'], :context => 'skill', :tagger => current_user
|
56
|
+
|
57
|
+
:context and :tagger also accept number as id for faster database query:
|
58
|
+
|
59
|
+
taggable.set_tags, :context => 'skill', :tagger => current_user.id
|
60
|
+
|
61
|
+
If not specified, default context is nil and default tagger is nil.
|
62
|
+
|
63
|
+
Tags should be an array of strings, or by default, a string with comma(,) to
|
64
|
+
divide tags.
|
65
|
+
Delimiter can be specified in :delimiter, for example:
|
66
|
+
|
67
|
+
taggable.set_tags 'rails; ruby', :context => 'skill', :delimiter => ';'
|
68
|
+
|
69
|
+
Space, single and double quotation will be trimmed automatically.
|
70
|
+
For more complicated processing of tag string, use block:
|
71
|
+
|
72
|
+
taggable.set_tags 'rails; ruby', :context => 'skill' do |tag_list|
|
73
|
+
return tag_list.split(',')
|
74
|
+
end
|
75
|
+
|
76
|
+
To retrieve tags in a context, use
|
77
|
+
|
78
|
+
taggable.tags.in_context(:skill)
|
79
|
+
|
80
|
+
To retreieve tags tagged by a tagger, use
|
81
|
+
|
82
|
+
taggable.tags.by_tagger(User.first)
|
83
|
+
|
84
|
+
__in_context__ and __by_tagger__ can be chained together. They are methods in scopes.
|
85
|
+
|
86
|
+
To retrieve taggable tagged with tags, use
|
87
|
+
|
88
|
+
Taggable.with_tags('ruby, rvm', :match => :any)
|
89
|
+
|
90
|
+
Options for __:match__ can be :any (default), :all (expensive).
|
91
|
+
|
92
|
+
__with_tags__ can also be used with __in_context__ and __by_tagger__
|
93
|
+
|
94
|
+
To delete tags, set __nil__:
|
95
|
+
|
96
|
+
taggable.set_tags(nil)
|
97
|
+
|
98
|
+
To delete tags associated with context and tagger, include options __context__ and __tagger__:
|
99
|
+
|
100
|
+
taggable.set_tags(nil, :context => :skill, :tagger = User.first)
|
101
|
+
|
102
|
+
### Tag
|
103
|
+
|
104
|
+
tag.taggers: taggers who use this tag
|
105
|
+
tag.taggings.collect(&:taggable): array of taggable tagged with this tag
|
106
|
+
|
107
|
+
To retrieve tags in a context, use
|
108
|
+
|
109
|
+
tags.in_context(:skill)
|
110
|
+
|
111
|
+
To retreieve tags tagged by a tagger, use
|
112
|
+
|
113
|
+
tagger.tags
|
114
|
+
|
115
|
+
### Tagging
|
116
|
+
|
117
|
+
No public methods for now.
|
118
|
+
|
119
|
+
This is the core model to link together tag, context, taggable and tagger.
|
120
|
+
If you need to work on low-level database query, you probably need to look
|
121
|
+
at this one.
|
122
|
+
|
123
|
+
### Tag Context
|
124
|
+
|
125
|
+
No public methods for now.
|
126
|
+
|
127
|
+
Just a place to keep records on tag context.
|
128
|
+
|
129
|
+
## FAQ
|
130
|
+
|
131
|
+
#### How do I get tag list from returned EasyTag::Tag ?
|
132
|
+
|
133
|
+
tags.pluck(:name).join(', ')
|
134
|
+
|
135
|
+
|
136
|
+
#### What's the difference between these two ?
|
137
|
+
|
138
|
+
user.posts.tags
|
139
|
+
|
140
|
+
user.posts.by_tagger(user)
|
141
|
+
|
142
|
+
|
143
|
+
The first returns all tags associated with posts, including tags tagged by others. The second return all tags associated with posts AND tagged by tagger.
|
144
|
+
|
145
|
+
#### What's the difference between these two ?
|
146
|
+
|
147
|
+
Post.with_tags('ruby')
|
148
|
+
|
149
|
+
Post.with_tags('ruby').in_context(nil)
|
150
|
+
|
151
|
+
The first returns all tags with 'ruby', regardless the context. In another word, it return all taggables with any context. The second returns all tags with 'ruby' with nil context. In another word, it will not return taggables where context exists. The same idea applies to __by_tagger__.
|
152
|
+
|
153
|
+
## Acknowledges
|
154
|
+
|
155
|
+
EasyTag is heavily influenced by [rocket_tag](https://github.com/bradphelan/rocket_tag), but not a direct fork.
|
156
|
+
|
157
|
+
## License
|
158
|
+
|
159
|
+
MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'EasyTag'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class EasyTag::Tag < ActiveRecord::Base
|
2
|
+
has_many :taggings, :dependent => :destroy,
|
3
|
+
:class_name => 'EasyTag::Tagging'
|
4
|
+
has_many :taggers, :through => :taggings
|
5
|
+
|
6
|
+
# Setup accessible (or protected) attributes for your model
|
7
|
+
attr_accessible :name
|
8
|
+
|
9
|
+
def self.compact_tag_list(tag_list, options = {})
|
10
|
+
options.reverse_merge! :downcase => true,
|
11
|
+
:delimiter => ','
|
12
|
+
if (tag_list.is_a?(String))
|
13
|
+
tag_list.downcase! if options[:downcase]
|
14
|
+
tags = tag_list.to_tags(options[:delimiter])
|
15
|
+
elsif (tag_list.is_a?(Array))
|
16
|
+
if options[:downcase]
|
17
|
+
tags = tag_list.collect { |t| t.downcase }
|
18
|
+
else
|
19
|
+
tags = tag_list
|
20
|
+
end
|
21
|
+
elsif tag_list.blank?
|
22
|
+
tags = nil
|
23
|
+
else
|
24
|
+
raise EasyTag::InvalidTagList
|
25
|
+
end
|
26
|
+
|
27
|
+
tags
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class EasyTag::TagContext < ActiveRecord::Base
|
2
|
+
has_many :taggings, :dependent => :destroy,
|
3
|
+
:class_name => 'EasyTag::Tagging'
|
4
|
+
has_many :tags, :through => :taggings
|
5
|
+
|
6
|
+
# Setup accessible (or protected) attributes for your model
|
7
|
+
attr_accessible :name
|
8
|
+
|
9
|
+
def self.get_id(context)
|
10
|
+
if context.is_a?(String) || context.is_a?(Symbol)
|
11
|
+
context_id = self.where(:name => context.to_s).first
|
12
|
+
elsif context.is_a?(Integer)
|
13
|
+
context_id = context
|
14
|
+
else
|
15
|
+
raise EasyTag::InvalidContext
|
16
|
+
end
|
17
|
+
context_id
|
18
|
+
end
|
19
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
module EasyTag
|
2
|
+
module Taggable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
has_many :taggings, :as => :taggable, :dependent => :destroy,
|
7
|
+
:class_name => 'EasyTag::Tagging'
|
8
|
+
has_many :tags, :through => :taggings, :uniq => true do
|
9
|
+
def in_context(context)
|
10
|
+
context_id = EasyTag::TagContext.get_id(context)
|
11
|
+
where('easy_tag_taggings.tag_context_id = ?', context_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def by_tagger(tagger)
|
15
|
+
tagger_id = EasyTag::Tagger.get_id(tagger)
|
16
|
+
where('easy_tag_taggings.tagger_id = ?', tagger_id)
|
17
|
+
end
|
18
|
+
end # end of has_many :tags
|
19
|
+
|
20
|
+
scope :with_tags, ->(tag_list, options = {}) {
|
21
|
+
options.reverse_merge! :match => :any
|
22
|
+
|
23
|
+
if block_given?
|
24
|
+
tags = yield(klass)
|
25
|
+
else
|
26
|
+
tags = EasyTag::Tag.compact_tag_list(tag_list, options.slice(:downcase, :delimiter))
|
27
|
+
end
|
28
|
+
|
29
|
+
return where('1 == 2') if tags.nil?
|
30
|
+
|
31
|
+
query = tags.collect { |t| "name = '#{t}'" }.join(' OR ')
|
32
|
+
tag_ids = EasyTag::Tag.where(query).pluck(:id)
|
33
|
+
|
34
|
+
if options[:match] == :all
|
35
|
+
ids = nil
|
36
|
+
tag_ids.each do |tag_id|
|
37
|
+
# p EasyTag::Tag.find(tag_id)
|
38
|
+
taggable_ids = EasyTag::Tagging.where(:tag_id => tag_id).where(:taggable_type => self.model_name).pluck(:taggable_id).to_a
|
39
|
+
if ids
|
40
|
+
ids = ids & taggable_ids
|
41
|
+
else
|
42
|
+
ids = taggable_ids # first tag
|
43
|
+
end
|
44
|
+
end
|
45
|
+
joins(:taggings).where(:id => ids).uniq
|
46
|
+
else
|
47
|
+
# :any
|
48
|
+
joins(:taggings).where('easy_tag_taggings.tag_id' => tag_ids).uniq
|
49
|
+
end
|
50
|
+
|
51
|
+
} do
|
52
|
+
def in_context(context)
|
53
|
+
context_id = EasyTag::TagContext.get_id(context)
|
54
|
+
where('easy_tag_taggings.tag_context_id = ?', context_id)
|
55
|
+
end
|
56
|
+
|
57
|
+
def by_tagger(tagger)
|
58
|
+
tagger_id = EasyTag::Tagger.get_id(tagger)
|
59
|
+
where('easy_tag_taggings.tagger_id = ?', tagger_id)
|
60
|
+
end
|
61
|
+
end # end of scope :with_tags
|
62
|
+
end # end of included
|
63
|
+
|
64
|
+
module ClassMethods
|
65
|
+
end # end of class methods
|
66
|
+
|
67
|
+
def set_tags(tag_list, options = {})
|
68
|
+
options.reverse_merge! :context => nil,
|
69
|
+
:tagger => nil,
|
70
|
+
:downcase => true,
|
71
|
+
:delimiter => ','
|
72
|
+
|
73
|
+
if block_given?
|
74
|
+
tags = yield(klass)
|
75
|
+
else
|
76
|
+
tags = EasyTag::Tag.compact_tag_list(tag_list, options.slice(:downcase, :delimiter))
|
77
|
+
end
|
78
|
+
|
79
|
+
context = compact_context(options[:context])
|
80
|
+
tagger = compact_tagger(options[:tagger])
|
81
|
+
|
82
|
+
# Remove old tags
|
83
|
+
self.taggings.where(:tag_context_id => context.try(:id), :tagger_id => tagger.try(:id)).destroy_all
|
84
|
+
# TODO: should remove unused tags and contexts
|
85
|
+
|
86
|
+
if tags
|
87
|
+
tags.each do |t|
|
88
|
+
tag = EasyTag::Tag.where(:name => t).first_or_create
|
89
|
+
raise SimgleTag::InvalidTag if tag.nil?
|
90
|
+
self.taggings.where(:tagger_id => tagger.try(:id), :tag_context_id => context.try(:id), :tag_id => tag.id).first_or_create
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def tags=(tag_list)
|
96
|
+
self.set_tags(tag_list)
|
97
|
+
end
|
98
|
+
|
99
|
+
def is_taggable?
|
100
|
+
return true
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def compact_context(context)
|
106
|
+
return nil if context.blank?
|
107
|
+
|
108
|
+
if (context.is_a?(String) || context.is_a?(Symbol))
|
109
|
+
return EasyTag::TagContext.where(:name => context.to_s).first_or_create
|
110
|
+
elsif (context.is_a?(Integer))
|
111
|
+
return EasyTag::TagContext.where(:id => context).first_or_create
|
112
|
+
end
|
113
|
+
|
114
|
+
raise EasyTag::InvalidTagContext
|
115
|
+
end
|
116
|
+
|
117
|
+
def compact_tagger(tagger)
|
118
|
+
return nil if tagger.blank?
|
119
|
+
return tagger if tagger.is_tagger?
|
120
|
+
|
121
|
+
if (tagger.is_a?(Integer))
|
122
|
+
if EasyTag::Tagger.class_variable_defined?(:@@tagger_class)
|
123
|
+
klass = EasyTag::Tagger.class_variable_get(:@@tagger_class)
|
124
|
+
return klass.where(:id => tagger).first_or_create
|
125
|
+
else
|
126
|
+
raise EasyTag::NoTaggerDefined
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
raise EasyTag::InvalidTagger
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class String
|
136
|
+
def to_tags(delimiter = ',')
|
137
|
+
self.split(delimiter).collect do |t|
|
138
|
+
t.strip.gsub(/\A["']|["']\Z/, '')
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module EasyTag
|
2
|
+
module Tagger
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
has_many :taggings, :dependent => :destroy,
|
7
|
+
:class_name => 'EasyTag::Tagging',
|
8
|
+
:foreign_key => 'tagger_id'
|
9
|
+
has_many :tags, :through => :taggings, :uniq => true do
|
10
|
+
def in_context(context)
|
11
|
+
context_id = EasyTag::TagContext.get_id(context)
|
12
|
+
where('easy_tag_taggings.tag_context_id = ?', context_id)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end # end of included
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def get_id(tagger)
|
19
|
+
if tagger.is_a?(Integer)
|
20
|
+
tagger_id = tagger
|
21
|
+
elsif tagger.is_tagger?
|
22
|
+
tagger_id = tagger.id
|
23
|
+
else
|
24
|
+
raise EasyTag::InvalidTagger
|
25
|
+
end
|
26
|
+
tagger_id
|
27
|
+
end
|
28
|
+
end # end of class methods
|
29
|
+
|
30
|
+
extend ClassMethods # to be use in EasyTag::Tag module
|
31
|
+
|
32
|
+
def is_tagger?
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/easy_tag.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'easy_tag/engine'
|
2
|
+
require 'easy_tag/taggable.rb'
|
3
|
+
require 'easy_tag/tagger.rb'
|
4
|
+
|
5
|
+
# For some reason, this does not work when set in app/models/easy_tag.rb
|
6
|
+
# Therefore, it is put here.
|
7
|
+
module EasyTag
|
8
|
+
def self.table_name_prefix
|
9
|
+
'easy_tag_'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(ActiveRecord::Base)
|
14
|
+
class ActiveRecord::Base
|
15
|
+
def is_taggable?
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_tagger?
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.acts_as_taggable(options = {})
|
24
|
+
options.reverse_merge!({})
|
25
|
+
include EasyTag::Taggable
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.acts_as_tagger(options = {})
|
29
|
+
options.reverse_merge!({})
|
30
|
+
include EasyTag::Tagger
|
31
|
+
|
32
|
+
EasyTag::Tagger.class_variable_set(:@@tagger_class, self)
|
33
|
+
EasyTag::Tagging.belongs_to :tagger, :class_name => self.model_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
require 'rails/generators/active_record'
|
4
|
+
|
5
|
+
module EasyTag
|
6
|
+
class MigrationGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
desc 'add easy tag'
|
10
|
+
|
11
|
+
source_root File.expand_path('../templates', __FILE__)
|
12
|
+
|
13
|
+
def self.next_migration_number(path)
|
14
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_migration_file
|
18
|
+
migration_template 'migration.rb', 'db/migrate/easy_tag_migration'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class EasyTagMigration < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def change
|
4
|
+
create_table :easy_tag_tags do |t|
|
5
|
+
t.string :name
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :easy_tag_tag_contexts do |t|
|
11
|
+
t.string :name
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :easy_tag_taggings do |t|
|
17
|
+
t.references :tag
|
18
|
+
t.references :tag_context
|
19
|
+
t.references :tagger
|
20
|
+
|
21
|
+
# You should make sure that the column created is
|
22
|
+
# long enough to store the required class names.
|
23
|
+
t.references :taggable, :polymorphic => true
|
24
|
+
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
add_index :easy_tag_taggings, :tag_id
|
29
|
+
add_index :easy_tag_taggings, :tagger_id
|
30
|
+
add_index :easy_tag_taggings, :tag_context_id
|
31
|
+
add_index :easy_tag_taggings, [:taggable_id, :taggable_type]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easy_tag
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yen-Ju Chen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.11
|
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.11
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sqlite3
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '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'
|
46
|
+
description: A very simple tagging system for Rails to be forked or extended.
|
47
|
+
email:
|
48
|
+
- yjchenx@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- app/models/easy_tag/tag.rb
|
54
|
+
- app/models/easy_tag/tag_context.rb
|
55
|
+
- app/models/easy_tag/tagging.rb
|
56
|
+
- app/models/easy_tag.rb
|
57
|
+
- config/routes.rb
|
58
|
+
- lib/easy_tag/engine.rb
|
59
|
+
- lib/easy_tag/taggable.rb
|
60
|
+
- lib/easy_tag/tagger.rb
|
61
|
+
- lib/easy_tag/version.rb
|
62
|
+
- lib/easy_tag.rb
|
63
|
+
- lib/generators/easy_tag/migration/migration_generator.rb
|
64
|
+
- lib/generators/easy_tag/migration/templates/migration.rb
|
65
|
+
- lib/tasks/easy_tag_tasks.rake
|
66
|
+
- MIT-LICENSE
|
67
|
+
- Rakefile
|
68
|
+
- README.md
|
69
|
+
homepage: https://github.com/yjchen/easy_tag
|
70
|
+
licenses: []
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.23
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: A very simple tagging system for Rails
|
93
|
+
test_files: []
|