Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

per user tagging, without breaking not per user tagging, needs a bit …

…of cleanup and testing

git-svn-id: http://svn.devjavu.com/geemus/rails/plugins/acts_as_taggable_redux@3 89c3609e-b12b-0410-95a9-e792c7af2e16
  • Loading branch information...
commit bd348cbda136334911ac0194d16a3324f7e57c37 1 parent 5347683
monki@geemus.com authored
11 README
View
@@ -1,13 +1,14 @@
ActsAsTaggableRedux
===================
-Allows for tags to be added to multiple classes, and adds functionality to make tags easier to work with. Note: The example and helper use RESTful routes, which require using EDGE rails. Please install that first if you want to use this functionality.
-
+Allows for user owned tags to be added to multiple classes, and makes tags easier to work with.
Prerequisites
=============
+Install Edge Rails before you get started so you get RESTful routing.
+
ActsAsTaggableRedux depends on database tables to store tagging information. Create the migration for these tables with this command:
rake acts_as_taggable:db:create
@@ -16,6 +17,9 @@ Then run the migration to create the tables with this command:
rake db:migrate
+Also you will need to add this to your user model:
+ acts_as_tagger
+
OPTIONAL: To pretty up tag clouds and lists you can generate an example stylesheet with this command:
rake acts_as_taggable:stylesheet:create
@@ -47,6 +51,9 @@ app/views/items/new.erb
<% end -%>
+if you want users to own taggings add this into the form
+ <%= f.hidden_field :user_id, :value => user.id -%>
+
app/views/items/show.erb
Item tagged with:
<% item.tags.each do |tag| -%>
9 generators/acts_as_taggable_tables/templates/migration.rb
View
@@ -10,13 +10,16 @@ def self.up
create_table :taggings do |t|
t.column :tag_id, :integer
t.column :taggable_id, :integer
- t.column :taggable_type, :string
+ t.column :taggable_type, :string
+ t.column :user_id, :integer
end
- # Find objects for a tag
+ # Find objects for a tag
add_index :taggings, [:tag_id, :taggable_type]
+ add_index :taggings, [:user_id, :tag_id, :taggable_type]
# Find tags for an object
- add_index :taggings, [:taggable_id, :taggable_type, :tag_id]
+ add_index :taggings, [:taggable_id, :taggable_type]
+ add_index :taggings, [:user_id, :taggable_id, :taggable_type]
end
def self.down
2  init.rb
View
@@ -1,5 +1,7 @@
require 'acts_as_taggable'
+require 'acts_as_tagger'
ActiveRecord::Base.send(:include, ActiveRecord::Acts::Taggable)
+ActiveRecord::Base.send(:include, ActiveRecord::Acts::Tagger)
ActionView::Base.send(:include, ActsAsTaggableHelper)
require File.dirname(__FILE__) + '/lib/tagging'
32 lib/acts_as_taggable.rb
View
@@ -12,8 +12,8 @@ def acts_as_taggable(options = {})
after_save :update_tags
+ extend ActiveRecord::Acts::Taggable::SingletonMethods
include ActiveRecord::Acts::Taggable::InstanceMethods
- extend ActiveRecord::Acts::Taggable::SingletonMethods
end
end
@@ -23,7 +23,7 @@ module SingletonMethods
# Options:
# :match - Match taggables matching :all or :any of the tags, defaults to :any
def find_tagged_with(tags, options = {})
- options.assert_valid_keys([:match])
+ options.assert_valid_keys([:match, :user])
tags = Tag.parse(tags)
return [] if tags.empty?
@@ -39,6 +39,28 @@ def find_tagged_with(tags, options = {})
:group => group
})
end
+
+ # Pass a tag string, returns taggables that match the tag string for a particular user.
+ #
+ # Options:
+ # :match - Match taggables matching :all or :any of the tags, defaults to :any
+ def find_tagged_with_by_user(tags, user, options = {})
+ options.assert_valid_keys([:match])
+
+ tags = Tag.parse(tags)
+ return [] if tags.empty?
+
+ group = "#{table_name}_taggings.taggable_id HAVING COUNT(#{table_name}_taggings.taggable_id) = #{tags.size}" if options[:match] == :all
+
+ find(:all,
+ {
+ :select => "DISTINCT #{table_name}.*",
+ :joins => "LEFT OUTER JOIN taggings #{table_name}_taggings ON #{table_name}_taggings.taggable_id = #{table_name}.#{primary_key} AND #{table_name}_taggings.taggable_type = '#{name}' " +
+ "LEFT OUTER JOIN tags #{table_name}_tags ON #{table_name}_tags.id = #{table_name}_taggings.tag_id",
+ :conditions => sanitize_sql(["#{table_name}_tags.name IN (?) AND #{table_name}_taggings.user_id = ?", tags, user]),
+ :group => group
+ })
+ end
end
module InstanceMethods
@@ -48,6 +70,10 @@ def tag_list=(new_tag_list)
end
end
+ def user_id=(new_user_id)
+ @new_user = User.find(new_user_id)
+ end
+
def tag_list
tags.collect { |tag| tag.name.include?(" ") ? %("#{tag.name}") : tag.name }.join(" ")
end
@@ -58,7 +84,7 @@ def update_tags
taggings.destroy_all
Tag.parse(@new_tag_list).each do |name|
- Tag.find_or_create_by_name(name).tag(self)
+ Tag.find_or_create_by_name(name).tag(self, @new_user)
end
tags.reset
25 lib/acts_as_tagger.rb
View
@@ -0,0 +1,25 @@
+module ActiveRecord
+ module Acts #:nodoc:
+ module Tagger #:nodoc:
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def acts_as_tagger(options = {})
+ has_many :taggings
+ has_many :tags, :through => :taggings, :select => "DISTINCT tags.*"
+
+ extend ActiveRecord::Acts::Tagger::SingletonMethods
+ include ActiveRecord::Acts::Tagger::InstanceMethods
+ end
+ end
+
+ module SingletonMethods
+ end
+
+ module InstanceMethods
+ end
+ end
+ end
+end
6 lib/tag.rb
View
@@ -28,9 +28,9 @@ def self.parse(list)
return tag_names
end
- # Tag a taggable with this tag
- def tag(taggable)
- taggings.create :taggable => taggable
+ # Tag a taggable with this tag, optionally add user to add owner to tagging
+ def tag(taggable, user = nil)
+ taggings.create :taggable => taggable, :user => user
taggings.reset
@tagged = nil
end
1  lib/tagging.rb
View
@@ -1,4 +1,5 @@
class Tagging < ActiveRecord::Base
belongs_to :tag, :counter_cache => true
belongs_to :taggable, :polymorphic => true
+ belongs_to :user
end
1  test/acts_as_taggable_test.rb
View
@@ -25,6 +25,7 @@ def test_tag_list
end
def test_update_tags
+ current_user = users(:monki)
assert_equal things(:bear).tag_list, "animal \"not green\""
things(:bear).tag_list = 'animal "not green" favorite'
assert_equal things(:bear).tag_list, "animal \"not green\""
3  test/fixtures/user.rb
View
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ acts_as_tagger
+end
3  test/fixtures/users.yml
View
@@ -0,0 +1,3 @@
+monki:
+ id: 1
+ username: monki
9 test/schema.rb
View
@@ -10,11 +10,18 @@
t.column :tag_id, :integer
t.column :taggable_id, :integer
t.column :taggable_type, :string
+ t.column :user_id, :integer
end
add_index :taggings, [:tag_id, :taggable_type]
- add_index :taggings, [:taggable_id, :taggable_type, :tag_id]
+ add_index :taggings, [:user_id, :tag_id, :taggable_type]
+ add_index :taggings, [:taggable_id, :taggable_type]
+ add_index :taggings, [:user_id, :taggable_id, :taggable_type]
create_table :things, :force => true do |t|
t.column :name, :string
end
+
+ create_table :users, :force => true do |t|
+ t.column :username, :string
+ end
end
2  test/tag_test.rb
View
@@ -1,8 +1,6 @@
require File.dirname(__FILE__) + "/test_helper"
class TagTest < Test::Unit::TestCase
- fixtures :taggings, :tags, :things
-
def test_taggings
assert_equal [taggings(:bear_animal), taggings(:frog_animal)], tags(:animal).taggings
assert_not_equal [taggings(:cactus_plant), taggings(:orange_plant)], tags(:animal).taggings
2  test/tagging_test.rb
View
@@ -1,8 +1,6 @@
require File.dirname(__FILE__) + "/test_helper"
class TaggingTest < Test::Unit::TestCase
- fixtures :taggings, :tags, :things
-
def test_taggable
assert_equal things(:bear), taggings(:bear_animal).taggable
assert_not_equal things(:frog), taggings(:bear_animal).taggable
Please sign in to comment.
Something went wrong with that request. Please try again.