jakewendt-simply_taggable 0.3.2

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/README.rdoc ADDED
@@ -0,0 +1,53 @@
1
+ = Simply Taggable
2
+
3
+ Introduction goes here.
4
+
5
+ == TODO
6
+
7
+ Build generator to install migrations, javascript, stylesheets, tasks, autotest
8
+
9
+ Generator also creates factory initializer
10
+
11
+ Build complete tests
12
+
13
+ Import existing model tests.
14
+
15
+ Add namable type tags/taggings
16
+
17
+
18
+ == Example
19
+
20
+ Example goes here.
21
+
22
+
23
+
24
+ == Usage
25
+
26
+ config.gem 'jakewendt-simply_taggable',
27
+ :source => 'http://rubygems.org'
28
+
29
+ script/generate simply_taggable
30
+ script/generate simply_taggable_tagger User <- Maybe
31
+
32
+
33
+ == Gemified with Jeweler
34
+
35
+ vi Rakefile
36
+ rake version:write
37
+
38
+ rake version:bump:patch
39
+ rake version:bump:minor
40
+ rake version:bump:major
41
+
42
+ rake gemspec
43
+
44
+ rake install
45
+ rake release
46
+
47
+
48
+ == Credit and References
49
+
50
+ Can't remember which one, but I'm sure that I got much of this from a
51
+ Ryan Bates Railscast.
52
+
53
+ Copyright (c) 2009 [George 'Jake' Wendt], released under the MIT license
data/app/models/tag.rb ADDED
@@ -0,0 +1,36 @@
1
+ class Tag < ActiveRecord::Base
2
+ # belongs_to :user
3
+ belongs_to :tagger, :polymorphic => true #, :counter_cache => true
4
+ has_many :taggings, :dependent => :destroy
5
+ has_many :taggables, :through => :taggings
6
+
7
+ validates_presence_of :tagger_id, :tagger_type
8
+ validates_presence_of :name
9
+ validates_length_of :name, :in => 1..250
10
+ validates_uniqueness_of :name, :scope => [:tagger_id, :tagger_type]
11
+
12
+ attr_accessible :name
13
+
14
+ class MultipleTagsFound < StandardError
15
+ attr_reader :message;
16
+ def initialize(message="Multiple tags found")
17
+ @message = message
18
+ end
19
+ end
20
+
21
+ def before_save
22
+ name.squish!
23
+ end
24
+
25
+ def self.find_or_create(conditions={})
26
+ tags = find(:all, :conditions => conditions)
27
+ case tags.length
28
+ when 0
29
+ self.create!(conditions)
30
+ when 1
31
+ tags[0]
32
+ else raise MultipleTagsFound.new("Multiple tags found matching #{conditions.inspect}.")
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,4 @@
1
+ class Tagging < ActiveRecord::Base
2
+ belongs_to :taggable, :polymorphic => true
3
+ belongs_to :tag, :counter_cache => :taggables_count
4
+ end
data/config/routes.rb ADDED
File without changes
File without changes
@@ -0,0 +1,71 @@
1
+ class SimplyTaggableGenerator < Rails::Generator::Base
2
+
3
+ def manifest
4
+ # See Rails::Generator::Commands::Create
5
+ # rails-2.3.10/lib/rails_generator/commands.rb
6
+ # for code methods for record (Manifest)
7
+ record do |m|
8
+ m.directory('config/autotest')
9
+ m.file('autotest_simply_taggable.rb', 'config/autotest/simply_taggable.rb')
10
+ m.directory('lib/tasks')
11
+ m.file('simply_taggable.rake', 'lib/tasks/simply_taggable.rake')
12
+
13
+ %w( create_tags create_taggings ).each do |migration|
14
+ m.migration_template "migrations/#{migration}.rb",
15
+ 'db/migrate', :migration_file_name => migration
16
+ end
17
+
18
+ m.directory('public/javascripts')
19
+ Dir["#{File.dirname(__FILE__)}/templates/javascripts/*js"].each{|file|
20
+ f = file.split('/').slice(-2,2).join('/')
21
+ m.file(f, "public/javascripts/#{File.basename(file)}")
22
+ }
23
+ m.directory('public/stylesheets')
24
+ Dir["#{File.dirname(__FILE__)}/templates/stylesheets/*css"].each{|file|
25
+ f = file.split('/').slice(-2,2).join('/')
26
+ m.file(f, "public/stylesheets/#{File.basename(file)}")
27
+ }
28
+
29
+ # m.directory('test/functional/pages')
30
+ # Dir["#{File.dirname(__FILE__)}/templates/functional/*rb"].each{|file|
31
+ # f = file.split('/').slice(-2,2).join('/')
32
+ # m.file(f, "test/functional/pages/#{File.basename(file)}")
33
+ # }
34
+ # m.directory('test/unit/pages')
35
+ # Dir["#{File.dirname(__FILE__)}/templates/unit/*rb"].each{|file|
36
+ # f = file.split('/').slice(-2,2).join('/')
37
+ # m.file(f, "test/unit/pages/#{File.basename(file)}")
38
+ # }
39
+ end
40
+ end
41
+
42
+ end
43
+ module Rails::Generator::Commands
44
+ class Create
45
+ def migration_template(relative_source,
46
+ relative_destination, template_options = {})
47
+ migration_directory relative_destination
48
+ migration_file_name = template_options[
49
+ :migration_file_name] || file_name
50
+ if migration_exists?(migration_file_name)
51
+ puts "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}: Skipping"
52
+ else
53
+ template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
54
+ end
55
+ end
56
+ end # Create
57
+ class Base
58
+ protected
59
+ # the loop through migrations happens so fast
60
+ # that they all have the same timestamp which
61
+ # won't work when you actually try to migrate.
62
+ # All the timestamps MUST be unique.
63
+ def next_migration_string(padding = 3)
64
+ @s = (!@s.nil?)? @s.to_i + 1 : if ActiveRecord::Base.timestamped_migrations
65
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
66
+ else
67
+ "%.#{padding}d" % next_migration_number
68
+ end
69
+ end
70
+ end # Base
71
+ end
@@ -0,0 +1,2 @@
1
+ # From `script/generate simply_taggable` ...
2
+ require 'simply_taggable/autotest'
@@ -0,0 +1,15 @@
1
+ class CreateTaggings < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :taggings do |t|
4
+ t.references :taggable, :polymorphic => true
5
+ t.references :tag
6
+ t.timestamps
7
+ end
8
+ add_index :taggings, [:taggable_id,:taggable_type], :name => 'by_taggable'
9
+ add_index :taggings, :tag_id, :name => 'by_tag_id'
10
+ end
11
+
12
+ def self.down
13
+ drop_table :taggings
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class CreateTags < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :tags do |t|
4
+ t.references :tagger, :polymorphic => true
5
+ t.string :name
6
+ t.integer :taggables_count, :null => false, :default => 0
7
+ t.timestamps
8
+ end
9
+ add_index :tags, [:name,:tagger_id,:tagger_type], :unique => true, :name => 'by_name'
10
+ end
11
+
12
+ def self.down
13
+ drop_table :tags
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ # From `script/generate simply_taggable` ...
2
+ unless Gem.source_index.find_name('jakewendt-simply_taggable').empty?
3
+ gem 'jakewendt-simply_taggable'
4
+ require 'simply_taggable/test_tasks'
5
+ end
@@ -0,0 +1 @@
1
+ require 'simply_taggable'
@@ -0,0 +1,7 @@
1
+ module SimplyTaggable
2
+ # predefined namespace
3
+ end
4
+ require 'simply_taggable/base'
5
+ require 'simply_taggable/assertions'
6
+
7
+ require 'active_support'
@@ -0,0 +1,33 @@
1
+ module SimplyTaggable::Assertions
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+ module ClassMethods
6
+
7
+ def assert_simply_taggable
8
+
9
+ test "should be simply taggable" do
10
+ assert model_name.constantize.new.respond_to?(:tags)
11
+ assert model_name.constantize.new.respond_to?(:taggings)
12
+ # self.class.assert_should_have_many :taggings
13
+ # self.class.assert_should_have_many :tags, :polymorphic => true
14
+ end
15
+
16
+ end
17
+
18
+ def assert_simply_taggable_tagger
19
+
20
+ test "should be simply taggable tagger" do
21
+ # self.class.assert_should_have_many :tags, :polymorphic => true
22
+
23
+ assert model_name.constantize.new.respond_to?(:tags)
24
+ # assert model_name.constantize.new.respond_to?(:taggings)
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ end
31
+ require 'active_support'
32
+ require 'active_support/test_case'
33
+ ActiveSupport::TestCase.send(:include,SimplyTaggable::Assertions)
@@ -0,0 +1,60 @@
1
+ module SimplyTaggable::Base
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
6
+ module ClassMethods
7
+
8
+ def simply_taggable_tagger
9
+
10
+ has_many :tags,
11
+ :as => :tagger,
12
+ :dependent => :destroy
13
+
14
+ end
15
+
16
+ def simply_taggable
17
+
18
+ # add some options like :by => :user
19
+ # in case User isn't the model of choice
20
+
21
+ include SimplyTaggable::Base::InstanceMethods
22
+
23
+ has_many :taggings,
24
+ :as => :taggable,
25
+ :dependent => :destroy
26
+
27
+ has_many :tags,
28
+ :through => :taggings
29
+
30
+ attr_writer :tag_names
31
+ attr_accessible :tag_names
32
+ after_save :assign_tags
33
+
34
+ end
35
+ end
36
+
37
+ module InstanceMethods
38
+
39
+ def tag_names
40
+ @tag_names || tags.map(&:name).join(', ')
41
+ end
42
+
43
+ private
44
+
45
+ def assign_tags
46
+ if @tag_names
47
+ self.tags = @tag_names.names_to_array.map do |name|
48
+ Tag.find_or_create({
49
+ :name => name.squish,
50
+ :tagger => self.tagger
51
+ # :user_id => self.user_id
52
+ }) if !name.blank?
53
+ end
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ require 'active_record'
60
+ ActiveRecord::Base.send(:include, SimplyTaggable::Base)
@@ -0,0 +1 @@
1
+ Dir["#{File.dirname(__FILE__)}/../tasks/**/*.rake"].sort.each { |ext| load ext }
@@ -0,0 +1,48 @@
1
+ module SimplyTaggable;end
2
+ namespace :test do
3
+ namespace :units do
4
+ Rake::TestTask.new(:simply_taggable => "db:test:prepare") do |t|
5
+ t.pattern = File.expand_path(File.join(
6
+ File.dirname(__FILE__),'/../../test/unit/taggable/*_test.rb'))
7
+ t.libs << "test"
8
+ t.verbose = true
9
+ end
10
+ end
11
+ namespace :functionals do
12
+ Rake::TestTask.new(:simply_taggable => "db:test:prepare") do |t|
13
+ t.pattern = File.expand_path(File.join(
14
+ File.dirname(__FILE__),'/../../test/functional/taggable/*_test.rb'))
15
+ t.libs << "test"
16
+ t.verbose = true
17
+ end
18
+ end
19
+ end
20
+ Rake::Task['test:functionals'].prerequisites.unshift(
21
+ "test:functionals:simply_taggable" )
22
+ Rake::Task['test:units'].prerequisites.unshift(
23
+ "test:units:simply_taggable" )
24
+
25
+ # I thought of possibly just including this file
26
+ # but that would make __FILE__ different.
27
+ # Hmmm
28
+
29
+ #
30
+ # used in simply_helpful's rake test:coverage to run gem's
31
+ # tests in the context of the application
32
+ #
33
+ @gem_test_dirs ||= []
34
+ #@gem_test_dirs << File.expand_path(File.join(File.dirname(__FILE__),
35
+ # '/../../test/unit/taggable/'))
36
+ #@gem_test_dirs << File.expand_path(File.join(File.dirname(__FILE__),
37
+ # '/../../test/functional/taggable/'))
38
+
39
+ #
40
+ # More flexible. Find all test files, pick out their dir, uniq 'em and add.
41
+ #
42
+ Dir.glob( File.expand_path(File.join(File.dirname(__FILE__),
43
+ '/../../test/*/taggable/*_test.rb'))
44
+ ).collect{|f|
45
+ File.dirname(f)
46
+ }.uniq.each{ |dir|
47
+ @gem_test_dirs << dir
48
+ }
@@ -0,0 +1,54 @@
1
+ desc "Explaining what the task does"
2
+ namespace :simply_taggable do
3
+
4
+ desc "Install"
5
+ task :install => [:prep, :update] do
6
+ puts "in install"
7
+ end
8
+
9
+ task :prep => :environment do
10
+ puts "in prep" # just once
11
+ # append require 'simply_taggable/tasks' to Rakefile
12
+ end
13
+
14
+ desc "Update"
15
+ task :update => :environment do
16
+ puts "in update"
17
+
18
+ # FileUtils.mkdir_p('db/migrate') unless File.directory?('db/migrate')
19
+ # rsync_command = <<-EOF.gsub(/\s+/,' ').squish!
20
+ # rsync -ruv
21
+ # --exclude='*_test_only_*rb'
22
+ # --exclude='versions'
23
+ # vendor/plugins/ucb_ccls_engine/db/migrate db
24
+ # EOF
25
+ # system rsync_command
26
+ #
27
+ # FileUtils.mkdir_p('public') unless File.directory?('public')
28
+ # rsync_command = <<-EOF.gsub(/\s+/,' ').squish!
29
+ # rsync -ruv
30
+ # --exclude='versions'
31
+ # vendor/plugins/ucb_ccls_engine/public .
32
+ # EOF
33
+ # system rsync_command
34
+ #
35
+ # rsync_command = <<-EOF.gsub(/\s+/,' ').squish!
36
+ # rsync -ruv
37
+ # --exclude='app'
38
+ # --exclude='assets'
39
+ # --exclude='config'
40
+ # --exclude='db'
41
+ # --exclude='extensions'
42
+ # --exclude='fixtures'
43
+ # --exclude='helpers'
44
+ # --exclude='log'
45
+ # --exclude='versions'
46
+ # --exclude='test_helper.rb'
47
+ # --exclude='engine_\*_test.rb'
48
+ # vendor/plugins/ucb_ccls_engine/test .
49
+ # EOF
50
+ # system rsync_command
51
+
52
+ end
53
+
54
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'jakewendt-simply_taggable'
@@ -0,0 +1,11 @@
1
+ class ApplicationController < ActionController::Base
2
+
3
+ def redirections
4
+ @redirections ||= HashWithIndifferentAccess.new({
5
+ :not_be_user => {
6
+ :redirect_to => user_path(current_user)
7
+ }
8
+ })
9
+ end
10
+
11
+ end
@@ -0,0 +1,2 @@
1
+ class Post < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
data/test/factories.rb ADDED
@@ -0,0 +1,6 @@
1
+ Factory.define :tag do |f|
2
+ f.name "Tag Name"
3
+ f.association :tagger
4
+ end
5
+ Factory.define :tagging do |f|
6
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class PostTest < ActiveSupport::TestCase
4
+
5
+ assert_simply_taggable
6
+
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ class SimplyTaggable::TagTest < ActiveSupport::TestCase
4
+
5
+ assert_should_initially_belong_to :tagger, :polymorphic => true
6
+ assert_should_have_many :taggings
7
+
8
+ assert_should_require :name
9
+ assert_should_not_protect_attribute :name
10
+ assert_should_protect_attribute :tagger_id
11
+ assert_should_protect_attribute :tagger_type
12
+
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class SimplyTaggable::TaggingTest < ActiveSupport::TestCase
4
+
5
+ assert_should_belong_to :tag
6
+ assert_should_belong_to :taggable, :polymorphic => true
7
+
8
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class UserTest < ActiveSupport::TestCase
4
+
5
+ assert_simply_taggable_tagger
6
+
7
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jakewendt-simply_taggable
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 2
10
+ version: 0.3.2
11
+ platform: ruby
12
+ authors:
13
+ - George 'Jake' Wendt
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-10 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rails
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 2
32
+ version: "2"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: jakewendt-rails_extension
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: longer description of your gem
50
+ email: github@jake.otherinbox.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files:
56
+ - README.rdoc
57
+ files:
58
+ - app/models/tag.rb
59
+ - app/models/tagging.rb
60
+ - config/routes.rb
61
+ - generators/simply_taggable/USAGE
62
+ - generators/simply_taggable/simply_taggable_generator.rb
63
+ - generators/simply_taggable/templates/autotest_simply_taggable.rb
64
+ - generators/simply_taggable/templates/migrations/create_taggings.rb
65
+ - generators/simply_taggable/templates/migrations/create_tags.rb
66
+ - generators/simply_taggable/templates/simply_taggable.rake
67
+ - lib/jakewendt-simply_taggable.rb
68
+ - lib/simply_taggable.rb
69
+ - lib/simply_taggable/assertions.rb
70
+ - lib/simply_taggable/base.rb
71
+ - lib/simply_taggable/tasks.rb
72
+ - lib/simply_taggable/test_tasks.rb
73
+ - lib/tasks/simply_taggable_tasks.rake
74
+ - rails/init.rb
75
+ - README.rdoc
76
+ - test/app/controllers/application_controller.rb
77
+ - test/app/models/post.rb
78
+ - test/app/models/user.rb
79
+ - test/factories.rb
80
+ - test/unit/post_test.rb
81
+ - test/unit/taggable/tag_test.rb
82
+ - test/unit/taggable/tagging_test.rb
83
+ - test/unit/user_test.rb
84
+ has_rdoc: true
85
+ homepage: http://github.com/jakewendt/simply_taggable
86
+ licenses: []
87
+
88
+ post_install_message:
89
+ rdoc_options: []
90
+
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.6.2
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: one-line summary of your gem
118
+ test_files:
119
+ - test/app/controllers/application_controller.rb
120
+ - test/app/models/post.rb
121
+ - test/app/models/user.rb
122
+ - test/factories.rb
123
+ - test/unit/post_test.rb
124
+ - test/unit/taggable/tag_test.rb
125
+ - test/unit/taggable/tagging_test.rb
126
+ - test/unit/user_test.rb