spraypaint 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/CHANGELOG +4 -0
- data/MIT-LICENSE +20 -0
- data/README +17 -0
- data/Rakefile +21 -0
- data/TODO +7 -0
- data/VERSION.yml +4 -0
- data/about.yml +10 -0
- data/generators/spraypaint_migration/spraypaint_migration_generator.rb +21 -0
- data/generators/spraypaint_migration/templates/spraypaint_migration.rb +25 -0
- data/lib/spraypaint.rb +59 -0
- data/lib/spraypaint/behaviour.rb +11 -0
- data/lib/spraypaint/behaviour/discovery.rb +57 -0
- data/lib/spraypaint/behaviour/manipulation.rb +71 -0
- data/lib/spraypaint/behaviour/persistence.rb +24 -0
- data/lib/spraypaint/default_sanitizer.rb +17 -0
- data/lib/spraypaint/model/tag.rb +15 -0
- data/lib/spraypaint/model/tagging.rb +11 -0
- data/lib/spraypaint/sanitizer.rb +11 -0
- data/rails/init.rb +3 -0
- data/spraypaint.gemspec +78 -0
- data/test/config/boot.rb +110 -0
- data/test/config/database.yml +5 -0
- data/test/config/environment.rb +27 -0
- data/test/config/environments/test.rb +0 -0
- data/test/db/schema.rb +40 -0
- data/test/spec/default_sanitizer_spec.rb +26 -0
- data/test/spec/models/tag_spec.rb +20 -0
- data/test/spec/models/tagging_spec.rb +49 -0
- data/test/spec/spec_helper.rb +50 -0
- data/test/spec/spraypaint_spec.rb +284 -0
- data/vendor/penknife/lib/penknife.rb +2 -0
- data/vendor/penknife/lib/penknife/rake.rb +41 -0
- data/vendor/penknife/lib/penknife/rake/plugin_tasks.rb +79 -0
- metadata +96 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tom Ward (tom@popdog.net)
|
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
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Features:
|
2
|
+
|
3
|
+
f = Film.find_by_title("The Umbrella's of Cherbourg")
|
4
|
+
f.tags
|
5
|
+
=> ["french", "umbrella", "catherine-deneuve"]
|
6
|
+
|
7
|
+
Tags can be added using standard array methods
|
8
|
+
|
9
|
+
f.tags << "jacques-demy"
|
10
|
+
f.save!
|
11
|
+
f.reload
|
12
|
+
f.tags
|
13
|
+
=> ["french", "umbrella", "catherine-deneuve", "jacques-demy"]
|
14
|
+
|
15
|
+
Tags maintain their order
|
16
|
+
|
17
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), "lib"))
|
2
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), "vendor/penknife/lib"))
|
3
|
+
|
4
|
+
require 'penknife/rake/plugin_tasks'
|
5
|
+
|
6
|
+
namespace :spraypaint do
|
7
|
+
Penknife::Rake::PluginTasks.new do |plugin|
|
8
|
+
plugin.plugin_root = File.dirname(File.expand_path(__FILE__))
|
9
|
+
plugin.name = 'spraypaint'
|
10
|
+
plugin.summary = 'Simple tagging in a can'
|
11
|
+
plugin.authors = ['Tom Ward (tomafro)']
|
12
|
+
plugin.email = 'tom@popdog.net'
|
13
|
+
plugin.homepage = 'http://github.com/tomafro/spraypaint'
|
14
|
+
plugin.code = 'http://github.com/tomafro/spraypaint.git'
|
15
|
+
plugin.license = 'MIT'
|
16
|
+
plugin.rails_version = '2.3+'
|
17
|
+
plugin.files = `git ls-files`.split("\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
task 'default' => ['spraypaint:spec', 'spraypaint:features']
|
data/TODO
ADDED
data/VERSION.yml
ADDED
data/about.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
:version: 1.0.0
|
3
|
+
:license: MIT
|
4
|
+
:rails_version: 2.3+
|
5
|
+
:author: Tom Ward (tomafro)
|
6
|
+
:summary: Simple tagging in a can
|
7
|
+
:plugin: http://github.com/tomafro/spraypaint.git
|
8
|
+
:email: tom@popdog.net
|
9
|
+
:name: spraypaint
|
10
|
+
:homepage: http://github.com/tomafro/spraypaint
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spraypaint'
|
2
|
+
|
3
|
+
class SpraypaintMigrationGenerator < Rails::Generator::NamedBase
|
4
|
+
def initialize(runtime_args, runtime_options)
|
5
|
+
super(["create_spraypnt_tagging_tables"], runtime_options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def manifest
|
9
|
+
record do |m|
|
10
|
+
m.migration_template 'spraypaint_migration.rb', 'db/migrate'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def tags_table
|
15
|
+
Spraypaint::Model::Tag.table_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def taggings_table
|
19
|
+
Spraypaint::Model::Tagging.table_name
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class <%= class_name.underscore.camelize %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table '<%= tags_table %>', :force => true do |table|
|
4
|
+
table.string 'name', :null => false
|
5
|
+
end
|
6
|
+
|
7
|
+
add_index '<%= tags_table %>', 'name', :unique => true
|
8
|
+
|
9
|
+
create_table '<%= taggings_table %>', :force => true do |table|
|
10
|
+
table.integer 'spraypaint_tag_id', :null => false
|
11
|
+
table.integer 'target_id', :null => false
|
12
|
+
table.string 'target_type', :null => false
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index '<%= taggings_table %>', 'target_id'
|
16
|
+
add_index '<%= taggings_table %>', 'target_type'
|
17
|
+
add_index '<%= taggings_table %>', 'spraypaint_tag_id'
|
18
|
+
add_index '<%= taggings_table %>', ['target_type', 'target_id', 'spraypaint_tag_id'], :unique => true, :name => 'spraypaint_unique_tagging_index'
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.down
|
22
|
+
drop_table '<%= taggings_table %>'
|
23
|
+
drop_table '<%= tags_table %>'
|
24
|
+
end
|
25
|
+
end
|
data/lib/spraypaint.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# = Spraypaint - simple tagging in a can
|
2
|
+
#
|
3
|
+
# == Getting started
|
4
|
+
#
|
5
|
+
# Generate and run the spraypaint migration
|
6
|
+
# script/generate spraypaint_migration
|
7
|
+
# rake db:migrate
|
8
|
+
#
|
9
|
+
# Enable spraypaint in a model
|
10
|
+
# class Film < ActiveRecord::Base
|
11
|
+
# tag_with_spraypaint
|
12
|
+
#
|
13
|
+
# def inspect
|
14
|
+
# "<#{self.title}>"
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Create some tagged films:
|
19
|
+
# Film.create! :title => 'The Umbrellas of Cherbourg', :director => 'Demy', :tags => ['umbrellas', 'french', 'musical']
|
20
|
+
# Film.create! :title => 'Jules Et Jim', :director => 'Truffaut', :tags => ['threesome', 'bicycle', 'french']
|
21
|
+
# Film.create! :title => 'Shoot The Pianist', :director => 'Truffaut', :tags => ['piano', 'gangster', 'french']
|
22
|
+
# Film.create! :title => 'The Sound of Music', :tags => ['musical', 'ww2']
|
23
|
+
#
|
24
|
+
# Use the tagged_with method to find records matching tags
|
25
|
+
# Film.tagged_with('musical')
|
26
|
+
# => [<The Umbrellas Of Cherbourg>, <The Sound Of Music>]
|
27
|
+
# Film.tagged_with('french', 'musical')
|
28
|
+
# => [<The Umbrellas Of Cherbourg>]
|
29
|
+
#
|
30
|
+
# As tagged_with is just a scope, you can chain it with standard finders or calculations
|
31
|
+
# Film.tagged_with('french').all(:order => 'title')
|
32
|
+
# => [<Jules Et Jim>, <Shoot The Pianist>, <The Umbrellas Of Cherbourg>]
|
33
|
+
# Film.tagged_with('musicl').all(:conditions => "name like '%Music%'")
|
34
|
+
# => [<The Sound Of Music>]
|
35
|
+
# Film.tagged_with('french').count
|
36
|
+
# => 3
|
37
|
+
#
|
38
|
+
# To find all tags on a model use #tags
|
39
|
+
# Film.tags
|
40
|
+
# => ['umbrellas', 'french', 'musical', 'threesome', 'bicycle', 'piano', 'gangster', 'ww2']
|
41
|
+
#
|
42
|
+
# The #tags method also plays nicely with scopes
|
43
|
+
# Film.all(:conditions => {'director' => 'Truffaut'}).tags
|
44
|
+
# => ['french', 'threesome', 'bicycle', 'piano', 'gangster']
|
45
|
+
# Film.tagged_with('french').tags
|
46
|
+
# => ['musical', 'french', 'threesome', 'bicycle', 'piano', 'gangster']
|
47
|
+
#
|
48
|
+
|
49
|
+
module Spraypaint
|
50
|
+
def self.activate_plugin
|
51
|
+
ActiveRecord::Base.extend(ClassMethods)
|
52
|
+
end
|
53
|
+
|
54
|
+
module ClassMethods
|
55
|
+
def tag_with_spraypaint(options = {})
|
56
|
+
include Spraypaint::Behaviour
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Spraypaint::Behaviour::Discovery
|
2
|
+
def self.included(base)
|
3
|
+
unless base == parent
|
4
|
+
base.named_scope :tagged_with, lambda {|*tags|
|
5
|
+
base.spraypaint_condition_hash_for(tags)
|
6
|
+
}
|
7
|
+
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
class TagString < String
|
14
|
+
def initialize(string, count)
|
15
|
+
super(string)
|
16
|
+
@tag_count = count.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def frequency
|
20
|
+
@tag_count
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def spraypaint_condition_hash_for(tags)
|
25
|
+
tags = self.tag_sanitizer.sanitize_array([*tags])
|
26
|
+
{:conditions => %{
|
27
|
+
EXISTS (
|
28
|
+
SELECT 1 FROM #{Spraypaint::Model::Tag.table_name}, #{Spraypaint::Model::Tagging.table_name}
|
29
|
+
WHERE #{Spraypaint::Model::Tagging.table_name}.target_id = #{self.table_name}.id
|
30
|
+
AND #{Spraypaint::Model::Tagging.table_name}.target_type = '#{self.base_class.name}'
|
31
|
+
AND #{Spraypaint::Model::Tag.table_name}.id = #{Spraypaint::Model::Tagging.table_name}.tag_id
|
32
|
+
AND (#{Spraypaint::Model::Tag.tag_condition(tags)})
|
33
|
+
GROUP BY #{Spraypaint::Model::Tagging.table_name}.target_id
|
34
|
+
HAVING count(distinct #{Spraypaint::Model::Tagging.table_name}.tag_id) = #{tags.size}
|
35
|
+
)
|
36
|
+
}}
|
37
|
+
end
|
38
|
+
|
39
|
+
def tags(options = {})
|
40
|
+
|
41
|
+
self.all({
|
42
|
+
:select => ['spraypaint_tags.id, spraypaint_tags.name tag_name, count(*) tag_count'],
|
43
|
+
:joins => %{
|
44
|
+
INNER JOIN spraypaint_taggings ON (spraypaint_taggings.target_id = #{self.table_name}.#{self.primary_key} AND spraypaint_taggings.target_type = '#{self.base_class.name}')
|
45
|
+
INNER JOIN spraypaint_tags ON (spraypaint_tags.id = spraypaint_taggings.tag_id)
|
46
|
+
},
|
47
|
+
:group => 'spraypaint_tags.id',
|
48
|
+
:order => 'count(*) desc, spraypaint_tags.name',
|
49
|
+
}.merge(options.slice(:conditions, :limit, :offset, :order))).collect {|tag| TagString.new(tag.tag_name, tag.tag_count) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def related_tags(*tags)
|
53
|
+
options = tags.extract_options!
|
54
|
+
tags(options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Spraypaint::Behaviour::Manipulation
|
2
|
+
def self.included(base)
|
3
|
+
unless base == parent
|
4
|
+
base.alias_method_chain :read_attribute, :spraypaint
|
5
|
+
base.alias_method_chain :create_or_update, :spraypaint
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def tags
|
11
|
+
read_attribute('tags')
|
12
|
+
end
|
13
|
+
|
14
|
+
def tags=(tags)
|
15
|
+
write_attribute('tags', self.class.tag_sanitizer.sanitize_array([*tags]))
|
16
|
+
end
|
17
|
+
|
18
|
+
def tag_string
|
19
|
+
read_attribute('tag_string') || tags.join(", ")
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag_string=(string)
|
23
|
+
write_attribute('tag_string', string)
|
24
|
+
self.tags = string && string.split(",").collect(&:strip)
|
25
|
+
end
|
26
|
+
|
27
|
+
def tags_changed?
|
28
|
+
attribute_changed?('tags')
|
29
|
+
end
|
30
|
+
|
31
|
+
def tags_change
|
32
|
+
attribute_change('tags')
|
33
|
+
end
|
34
|
+
|
35
|
+
def tags_was
|
36
|
+
attribute_was('tags')
|
37
|
+
end
|
38
|
+
|
39
|
+
def tags_will_change!
|
40
|
+
attribute_will_change('tags')
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def create_or_update_with_spraypaint
|
46
|
+
change = tags_change
|
47
|
+
returning create_or_update_without_spraypaint do |result|
|
48
|
+
if result && change
|
49
|
+
save_tag_names(change.last)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_attribute_with_spraypaint(attribute)
|
55
|
+
if attribute.to_s == "tags"
|
56
|
+
read_attribute_without_spraypaint(attribute) || load_tag_names
|
57
|
+
else
|
58
|
+
read_attribute_without_spraypaint(attribute)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module ClassMethods
|
63
|
+
def tag_sanitizer
|
64
|
+
@tag_sanitizer ||= Spraypaint::DefaultSanitizer.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def tag_sanitizer=(sanitizer)
|
68
|
+
@tag_sanitizer = sanitizer
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spraypaint::Behaviour::Persistence
|
2
|
+
def self.included(base)
|
3
|
+
unless base == parent
|
4
|
+
base.has_many 'spraypaint_taggings', :as => 'target', :dependent => :destroy, :class_name => 'Spraypaint::Model::Tagging'
|
5
|
+
base.has_many 'spraypaint_tags', :through => 'spraypaint_taggings', :source => 'tag', :class_name => '::Spraypaint::Model::Tag', :order => 'spraypaint_taggings.id'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def load_tag_names
|
12
|
+
self.spraypaint_tags.collect(&:name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def save_tag_names(names)
|
16
|
+
transaction do
|
17
|
+
spraypaint_taggings.destroy_all
|
18
|
+
names.each do |tag_name|
|
19
|
+
tag = Spraypaint::Model::Tag.find_or_create_by_name(tag_name)
|
20
|
+
self.spraypaint_tags << tag
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Spraypaint::DefaultSanitizer
|
2
|
+
include Spraypaint::Sanitizer
|
3
|
+
|
4
|
+
attr_accessor :allowed_characters
|
5
|
+
|
6
|
+
def initialize(allowed_characters = /[\w -]/)
|
7
|
+
self.allowed_characters = allowed_characters
|
8
|
+
end
|
9
|
+
|
10
|
+
def sanitize_tag(tag)
|
11
|
+
return nil if tag.nil?
|
12
|
+
string = tag.strip
|
13
|
+
string = string.mb_chars.normalize(:d).gsub(/[^\0-\x80]/, '')
|
14
|
+
string = string.scan(self.allowed_characters).join
|
15
|
+
string.empty? ? nil : string.to_s
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Spraypaint::Model::Tag < ActiveRecord::Base
|
2
|
+
# By default spraypaint uses the spraypaint namespace for all its tables, so
|
3
|
+
# the tags themselves are stored in spraypaint_tags. To change this, simply
|
4
|
+
# set the table name to something else
|
5
|
+
# Spraypaint::Model::Tag.set_table_name 'special_tags'
|
6
|
+
set_table_name :spraypaint_tags
|
7
|
+
|
8
|
+
# All tags must have a name. In practise this is enforced by the way tags are
|
9
|
+
# set and in the database, so this validation is redundant in normal usage
|
10
|
+
validates_presence_of :name
|
11
|
+
|
12
|
+
def self.tag_condition(tag)
|
13
|
+
sanitize_sql(:name => tag)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Spraypaint::Model::Tagging < ActiveRecord::Base
|
2
|
+
set_table_name :spraypaint_taggings
|
3
|
+
|
4
|
+
# Main association between an individual tagging and the actual tag
|
5
|
+
belongs_to :tag, :class_name => 'Spraypaint::Model::Tag'
|
6
|
+
|
7
|
+
# Association between the tagging and the object being tagged
|
8
|
+
belongs_to :target, :polymorphic => true
|
9
|
+
|
10
|
+
validates_presence_of :tag, :target
|
11
|
+
end
|
data/rails/init.rb
ADDED
data/spraypaint.gemspec
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{spraypaint}
|
8
|
+
s.version = "1.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tom Ward (tomafro)"]
|
12
|
+
s.date = %q{2009-10-18}
|
13
|
+
s.email = %q{tom@popdog.net}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".gitignore",
|
19
|
+
"CHANGELOG",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"Rakefile",
|
22
|
+
"TODO",
|
23
|
+
"VERSION.yml",
|
24
|
+
"about.yml",
|
25
|
+
"generators/spraypaint_migration/spraypaint_migration_generator.rb",
|
26
|
+
"generators/spraypaint_migration/templates/spraypaint_migration.rb",
|
27
|
+
"lib/spraypaint.rb",
|
28
|
+
"lib/spraypaint/behaviour.rb",
|
29
|
+
"lib/spraypaint/behaviour/discovery.rb",
|
30
|
+
"lib/spraypaint/behaviour/manipulation.rb",
|
31
|
+
"lib/spraypaint/behaviour/persistence.rb",
|
32
|
+
"lib/spraypaint/default_sanitizer.rb",
|
33
|
+
"lib/spraypaint/model/tag.rb",
|
34
|
+
"lib/spraypaint/model/tagging.rb",
|
35
|
+
"lib/spraypaint/sanitizer.rb",
|
36
|
+
"rails/init.rb",
|
37
|
+
"spraypaint.gemspec",
|
38
|
+
"test/config/boot.rb",
|
39
|
+
"test/config/database.yml",
|
40
|
+
"test/config/environment.rb",
|
41
|
+
"test/config/environments/test.rb",
|
42
|
+
"test/db/schema.rb",
|
43
|
+
"test/spec/default_sanitizer_spec.rb",
|
44
|
+
"test/spec/models/tag_spec.rb",
|
45
|
+
"test/spec/models/tagging_spec.rb",
|
46
|
+
"test/spec/spec_helper.rb",
|
47
|
+
"test/spec/spraypaint_spec.rb",
|
48
|
+
"vendor/penknife/lib/penknife.rb",
|
49
|
+
"vendor/penknife/lib/penknife/rake.rb",
|
50
|
+
"vendor/penknife/lib/penknife/rake/plugin_tasks.rb"
|
51
|
+
]
|
52
|
+
s.homepage = %q{http://github.com/tomafro/spraypaint}
|
53
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
54
|
+
s.require_paths = ["lib"]
|
55
|
+
s.rubygems_version = %q{1.3.5}
|
56
|
+
s.summary = %q{Simple tagging in a can}
|
57
|
+
s.test_files = [
|
58
|
+
"test/config/boot.rb",
|
59
|
+
"test/config/environment.rb",
|
60
|
+
"test/config/environments/test.rb",
|
61
|
+
"test/db/schema.rb",
|
62
|
+
"test/spec/default_sanitizer_spec.rb",
|
63
|
+
"test/spec/models/tag_spec.rb",
|
64
|
+
"test/spec/models/tagging_spec.rb",
|
65
|
+
"test/spec/spec_helper.rb",
|
66
|
+
"test/spec/spraypaint_spec.rb"
|
67
|
+
]
|
68
|
+
|
69
|
+
if s.respond_to? :specification_version then
|
70
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
71
|
+
s.specification_version = 3
|
72
|
+
|
73
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
74
|
+
else
|
75
|
+
end
|
76
|
+
else
|
77
|
+
end
|
78
|
+
end
|