can_flag 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,20 @@
1
+ Copyright (c) 2006 Cosmin Radoi
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,62 @@
1
+ Can Flag
2
+ =================
3
+ Strongly inspired by acts_as_flaggable.
4
+ Intended to allow your users to flag content as inappropriate, and set up some ways for you
5
+ to deal with the content.
6
+
7
+ == Resources
8
+
9
+ Install
10
+
11
+ 1. Download the tarball from github, or, clone the repository and symlink it into your application.
12
+ Yes, I'm serious.
13
+
14
+ 2. $ script/generate can_flag flags
15
+
16
+ This will create the following files:
17
+ app/controllers/flags_controller.rb
18
+ spec/helpers/flags_controller_spec.rb
19
+ app/helpers/flags_helper
20
+ db/migrate/flags_migration.rb
21
+
22
+ 3. Modify any content model with
23
+
24
+ class Article < ActiveRecord::Base
25
+ can_be_flagged
26
+ end
27
+
28
+ You can also add a callback
29
+
30
+ class Article
31
+ can_be_flagged
32
+ def after_flagged
33
+ # send an email
34
+ # delete this post
35
+ # suspend the owner of the post if the flags.size > 3
36
+ # suspend the owner of the post if their total flags count > 5
37
+ end
38
+ end
39
+
40
+ 4. Modify your user model with
41
+
42
+ class User < ActiveRecord::Base
43
+ can_flag
44
+ end
45
+
46
+ 5. Usage
47
+
48
+ article = Article.find(4)
49
+ current_user.flags.create :flaggable => article
50
+
51
+
52
+
53
+ * When a flag is added via add_flag, flagged(flag, flag_count) is called
54
+ on the flaggable model. This allows the model to perform certain
55
+ operations if the number of flags reaches a certain point. For example,
56
+ you may want to mark a Post as deleted if a Post receives too many "spam"
57
+ flags
58
+
59
+ * Each flag reference flaggable object
60
+
61
+ model = Model.find(1)
62
+ model.flags.get(0).commtable == model
@@ -0,0 +1,140 @@
1
+ # CanFlag
2
+ module Caboose
3
+ module Can
4
+ module Flag
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ if defined?(::ActiveSupport::Callbacks)
8
+ base.define_callbacks :after_flagged
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+ # Call can_be_flagged from your content model, or from anything
14
+ # you want to flag.
15
+ def can_be_flagged(opts={})
16
+ has_many :flags, :as => :flaggable, :dependent => :destroy
17
+ validates_associated :flags, :message => 'failed to validate'
18
+ include Caboose::Can::Flag::InstanceMethods
19
+ extend Caboose::Can::Flag::SingletonMethods
20
+ cattr_accessor :reasons
21
+ self.reasons = opts[:reasons] || [:inappropriate]
22
+ (::Flag.flaggable_models ||= []) << self
23
+ end
24
+
25
+ # Call can_flag from your user model, or anything that can own a flagging.
26
+ # That's a paddlin!
27
+ # Limitation for now: you should only allow one model to own flags.
28
+ # This is ridiculously easy to make polymorphic, but no ponies yet.
29
+ def can_flag
30
+ # has_many :flaggables, :foreign_key => "user_id"
31
+ # User created these flags
32
+ has_many :flags, :foreign_key => "user_id", :order => "id desc"
33
+
34
+ # User was responsible for creating this filth
35
+ has_many :flaggings, :foreign_key => "flaggable_user_id", :class_name => "Flag"
36
+ include CanFlagInstanceMethods
37
+
38
+ # Associate the flag back here
39
+ # Flag.belongs_to :user
40
+ # Flag.belongs_to :owner, :foreign_key => flaggable_user_id
41
+ ::Flag.class_eval "belongs_to :#{name.underscore}, :foreign_key => :user_id;
42
+ belongs_to :owner, :foreign_key => :flaggable_user_id, :class_name => '#{name}'"
43
+ end
44
+ end
45
+
46
+ # This module contains class methods
47
+ module SingletonMethods
48
+ # # Helper method to lookup for flags for a given object.
49
+ # # This method is equivalent to obj.flags.
50
+ # def find_flags_for(obj)
51
+ # flaggable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
52
+ #
53
+ # Flag.find(:all,
54
+ # :conditions => ["flaggable_id = ? and flaggable_type = ?", obj.id, flaggable],
55
+ # :order => "created_at DESC"
56
+ # )
57
+ # end
58
+ #
59
+ # # Helper class method to lookup flags for
60
+ # # the mixin flaggable type written by a given user.
61
+ # # This method is NOT equivalent to Flag.find_flags_for_user
62
+ # def find_flags_by_user(user)
63
+ # flaggable = ActiveRecord::Base.send(:class_name_of_active_record_descendant, self).to_s
64
+ #
65
+ # Flag.find(:all,
66
+ # :conditions => ["user_id = ? and flaggable_type = ?", user.id, flaggable],
67
+ # :order => "created_at DESC"
68
+ # )
69
+ # end
70
+ end
71
+
72
+ module CanFlagInstanceMethods
73
+ def flagged?(content)
74
+ logger.warn "Looking for flags with #{content.inspect} #{content.class.name}"
75
+ ::Flag.find(:first,
76
+ :conditions => { :flaggable_type => content.class.name, :flaggable_id => content[:id] })
77
+ end
78
+
79
+ def flagged_by?(content, user)
80
+ ::Flag.find(:first,
81
+ :conditions => { :flaggable_type => content.class.name, :flaggable_id => content[:id], :flaggable_user_id => user.id })
82
+ end
83
+ end
84
+
85
+ ## This module contains instance methods
86
+ module InstanceMethods
87
+
88
+ def flagged?
89
+ flags.size > 0
90
+ end
91
+
92
+ # Flag content with a mass-updater; sets the flagging user.
93
+ # article.update_attributes { 'flagged' => current_user.id }
94
+ def flagged=(by_who)
95
+ flags.build :user_id => by_who
96
+ end
97
+ #
98
+ # # Check to see if the passed in user has flagged this object before.
99
+ # # Optionally you can test to see if this user has flagged this object
100
+ # # with a specific flag
101
+ # def user_has_flagged?(user, flag = nil)
102
+ # conditions = flag.nil? ? {} : {:flag => flag}
103
+ # conditions.merge!({:user_id => user.id})
104
+ # return flags.count(:conditions =>conditions) > 0
105
+ # end
106
+ #
107
+ # # Count the number of flags tha have this specific
108
+ # # flag set
109
+ # def count_flags_with_flag(flag)
110
+ # flags.count(:conditions => ["flag = ?", flag])
111
+ # end
112
+ #
113
+ # # Add a flag. You can either pass in an
114
+ # # instance of a flag or pass in a hash of attributes to be used to
115
+ # # instantiate a new flag object
116
+ # def add_flag(options)
117
+ # if options.kind_of?(Hash)
118
+ # flag = Flag.new(options)
119
+ # elsif options.kind_of?(Flag)
120
+ # flag = options
121
+ # else
122
+ # raise "Invalid options"
123
+ # end
124
+ #
125
+ # flags << flag
126
+ #
127
+ # # Call flagged to allow model to handle the act of being
128
+ # # flagged
129
+ # flagged(flag.flag, count_flags_with_flag(flag.flag))
130
+ # end
131
+ #
132
+ # # Meant to be overriden
133
+ # protected
134
+ # def flagged(flag, flag_count)
135
+ # end
136
+ end
137
+
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,30 @@
1
+ # Stolen from Technoweenie's restful_authentication
2
+ Rails::Generator::Commands::Create.class_eval do
3
+ def route_resource(*resources)
4
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
5
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
6
+
7
+ logger.route "map.resource #{resource_list}"
8
+ unless options[:pretend]
9
+ gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
10
+ "#{match}\n map.resource #{resource_list}\n"
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ Rails::Generator::Commands::Destroy.class_eval do
17
+ def route_resource(*resources)
18
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
19
+ look_for = "\n map.resource #{resource_list}\n"
20
+ logger.route "map.resource #{resource_list}"
21
+ gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
22
+ end
23
+ end
24
+
25
+ Rails::Generator::Commands::List.class_eval do
26
+ def route_resource(*resources)
27
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
28
+ logger.route "map.resource #{resource_list}"
29
+ end
30
+ end
@@ -0,0 +1,65 @@
1
+ class Flag < ActiveRecord::Base
2
+ # serialize :flag, Symbol
3
+ belongs_to :flaggable, :polymorphic => true
4
+
5
+ # This will contain the names of all models that can_be_flagged
6
+ cattr_accessor :flaggable_models
7
+
8
+ # This line is dynamically generated when you call "can_flag" in your user/account model.
9
+ # It assumes that content is owned by the same class as flaggers.
10
+ # belongs_to :owner, :through => :flaggable, :class_name => ??
11
+
12
+ # This is set dynamically in the plugin.
13
+ # define "can_flag" in your user/account model.
14
+ # belongs_to :user
15
+
16
+ validates_presence_of :flaggable_id, :flaggable_type
17
+
18
+ # requires all your content to have a user_id. if not, then
19
+ validates_presence_of :flaggable_user_id, :on => :create,
20
+ # :message => "error - your content must be owned by a user.",
21
+ :if => Proc.new { |c| c.flaggable and c.flaggable.user_id }
22
+
23
+ # A user can flag a specific flaggable with a specific flag once
24
+ validates_uniqueness_of :user_id, :scope => [:flaggable_id, :flaggable_type]
25
+
26
+ after_create :callback_flaggable
27
+ # Pings the 'after_flagged' callback in the content model, if it exists.
28
+ def callback_flaggable
29
+ flaggable.callback :after_flagged
30
+ end
31
+
32
+ before_validation_on_create :set_owner_id
33
+ def set_owner_id
34
+ self.flaggable_user_id = flaggable.user_id
35
+ end
36
+
37
+ validates_each :reason do |record,attr,value|
38
+ record.errors.add(attr, "don't include '#{value}' as an option") if value and !record.flaggable.reasons.include?(value.to_sym)
39
+ end
40
+
41
+ # UNTESTED
42
+ # # Helper class method to lookup all flags assigned
43
+ # # to all flaggable types for a given user.
44
+ # def self.find_flags_by_user(user)
45
+ # find(:all,
46
+ # :conditions => ["user_id = ?", user.id],
47
+ # :order => "created_at DESC"
48
+ # )
49
+ # end
50
+ #
51
+ # # Helper class method to look up all flags for
52
+ # # flaggable class name and flaggable id.
53
+ # def self.find_flags_for_flaggable(flaggable_str, flaggable_id)
54
+ # find(:all,
55
+ # :conditions => ["flaggable_type = ? and flaggable_id = ?", flaggable_str, flaggable_id],
56
+ # :order => "created_at DESC"
57
+ # )
58
+ # end
59
+ #
60
+ # # Helper class method to look up a flaggable object
61
+ # # given the flaggable class name and id
62
+ # def self.find_flaggable(flaggable_str, flaggable_id)
63
+ # flaggable_str.constantize.find(flaggable_id)
64
+ # end
65
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class Article < ActiveRecord::Base
4
+ end
5
+ class Content < ActiveRecord::Base
6
+ set_table_name 'articles' # cheater
7
+ end
8
+
9
+ class CanBeFlaggedOptionsTest < Test::Unit::TestCase
10
+ def setup
11
+ Article.class_eval do
12
+ can_be_flagged :reasons => [:porn, :troll]
13
+ end
14
+ end
15
+
16
+ def test_sets_options_as_class_var
17
+ assert_equal [:porn, :troll], Article.reasons
18
+ end
19
+
20
+ def test_does_not_leak_reasons_betwixt_classes
21
+ Content.class_eval do
22
+ can_be_flagged :reasons => [:spam]
23
+ end
24
+ assert_equal [:porn, :troll], Article.reasons
25
+ assert_equal [:spam], Content.reasons
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class Article < ActiveRecord::Base
4
+ end
5
+
6
+ class ContentAssociationTest < Test::Unit::TestCase
7
+
8
+ def test_article_can_has_flag
9
+ Article.class_eval {
10
+ can_be_flagged
11
+ }
12
+ assert_not_nil Article.reflect_on_association(:flags)
13
+ assert_equal :has_many, Article.reflect_on_association(:flags).macro,
14
+ "Should create the 'flags' association"
15
+ #assert_not_nil Article.reflect_on_association(:flaggable)
16
+ #assert_equal :has_many, Article.reflect_on_association(:flaggable).macro,
17
+ # "Should create the 'flaggable' association"
18
+ end
19
+
20
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class Article < ActiveRecord::Base
4
+ can_be_flagged
5
+ end
6
+
7
+ class ContentAttributesTest < Test::Unit::TestCase
8
+ def test_article_cab_has_attributes_like_states
9
+ a = Article.new
10
+ assert a.respond_to?(:flagged?), "Should have the 'flagged?' method defined"
11
+ assert a.respond_to?(:flagged=), "Should have the 'flagged=' writer defined"
12
+ end
13
+
14
+ def test_article_can_has_writer
15
+ a = Article.new
16
+ assert ! a.flagged?, "Article should not be flagged by default"
17
+ a.attributes = { 'flagged' => true }
18
+ assert a.flagged?
19
+ end
20
+
21
+ end
@@ -0,0 +1,18 @@
1
+ sqlite:
2
+ :adapter: sqlite
3
+ :dbfile: can_flag_plugin.sqlite.db
4
+ sqlite3:
5
+ :adapter: sqlite3
6
+ :dbfile: can_flag_plugin.sqlite3.db
7
+ postgresql:
8
+ :adapter: postgresql
9
+ :username: postgres
10
+ :password: postgres
11
+ :database: can_flag_plugin_test
12
+ :min_messages: ERROR
13
+ mysql:
14
+ :adapter: mysql
15
+ :host: localhost
16
+ :username: rails
17
+ :password:
18
+ :database: can_flag_plugin_test
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class Article < ActiveRecord::Base
4
+ can_be_flagged
5
+ attr_accessor :called_back
6
+
7
+ def after_flagged
8
+ @called_back = true
9
+ end
10
+ end
11
+
12
+ class FlagTest < Test::Unit::TestCase
13
+
14
+ def test_calls_back_to_article
15
+ article = Article.create :title => "My article", :body => "Five five five", :user_id => 1
16
+ assert ! article.called_back
17
+ flag = Flag.create! :flaggable => article
18
+ assert article.called_back, "Article should call 'after_flagged' callback"
19
+ end
20
+
21
+ def test_sets_flaggable_user_id
22
+ article = Article.create :title => "My article", :body => "Five five five", :user_id => 1
23
+ flag = Flag.create :flaggable => article
24
+ flag.save!
25
+ assert_equal 1, flag.flaggable_user_id
26
+ end
27
+
28
+ def test_only_allows_valid_reasons
29
+ Article.class_eval { can_be_flagged :reasons => [ :foolish ] }
30
+ article = Article.create :title => "My article", :body => "Five five five", :user_id => 1
31
+ flag = Flag.create :flaggable => article, :reason => "foolish"
32
+ assert flag.save!
33
+ flag.reason = "Monkeys"
34
+ assert ! flag.save
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+
3
+ create_table :articles do |t|
4
+ t.string :title
5
+ t.string :body
6
+ t.string :user_id
7
+ end
8
+
9
+ create_table :users do |t|
10
+ t.string :login
11
+ end
12
+
13
+ create_table :flags do |t|
14
+ t.integer :user_id
15
+ t.integer :flaggable_id
16
+ t.string :flaggable_type
17
+ t.integer :flaggable_user_id
18
+ t.string :reason
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ ENV['RAILS_ENV'] = 'test'
4
+ ENV['RAILS_ROOT'] ||= '~/dev/oss/altered_beast/' #File.dirname(__FILE__) + '/../../../..'
5
+
6
+ require 'test/unit'
7
+ require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
8
+ require 'active_record/fixtures'
9
+ require 'action_controller/test_process'
10
+
11
+ config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
12
+ ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
13
+
14
+ # Cargo culted from attachment_fu!
15
+ db_adapter = ENV['DB']
16
+
17
+ # no db passed, try one of these fine config-free DBs before bombing.
18
+ db_adapter ||=
19
+ begin
20
+ require 'rubygems'
21
+ require 'sqlite'
22
+ 'sqlite'
23
+ rescue MissingSourceFile
24
+ begin
25
+ require 'sqlite3'
26
+ 'sqlite3'
27
+ rescue MissingSourceFile
28
+ end
29
+ end
30
+
31
+ if db_adapter.nil?
32
+ raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
33
+ end
34
+
35
+ ActiveRecord::Base.establish_connection(config[db_adapter])
36
+
37
+ load(File.dirname(__FILE__) + "/schema.rb")
38
+
39
+ # Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures"
40
+ # $LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class User<ActiveRecord::Base; end
4
+
5
+ class UserAssociationTest < Test::Unit::TestCase
6
+ def test_creates_user_association_in_flag
7
+ assert_nil Flag.reflect_on_association(:user)
8
+ User.class_eval do
9
+ can_flag
10
+ end
11
+ assert_not_nil Flag.reflect_on_association(:user)
12
+ end
13
+ end
14
+
15
+ class User2<ActiveRecord::Base; set_table_name :users; end
16
+
17
+ class UserFlagAssociationTest < Test::Unit::TestCase
18
+
19
+ def test_creates_flaggable_associations_in_user
20
+ assert_nil User2.reflect_on_association(:flaggable)
21
+ User2.class_eval do
22
+ can_flag
23
+ end
24
+ assert_not_nil User2.reflect_on_association(:flaggings)
25
+ assert_equal :has_many, User2.reflect_on_association(:flaggings).macro
26
+ assert_nothing_raised { User2.new.flaggings }
27
+ assert_not_nil User2.reflect_on_association(:flags)
28
+ assert_equal :has_many, User2.reflect_on_association(:flags).macro
29
+ assert_nothing_raised { User2.new.flags }
30
+ end
31
+
32
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: can_flag
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Courtenay Gasking
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-09 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 15
29
+ segments:
30
+ - 2
31
+ - 0
32
+ - 0
33
+ version: 2.0.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: activerecord
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 15
45
+ segments:
46
+ - 2
47
+ - 0
48
+ - 0
49
+ version: 2.0.0
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ description:
53
+ email:
54
+ - courtenay@entp.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - MIT-LICENSE
61
+ files:
62
+ - lib/can_flag/rails_commands.rb
63
+ - lib/can_flag.rb
64
+ - lib/flag.rb
65
+ - test/can_be_flagged_options_test.rb
66
+ - test/content_association_test.rb
67
+ - test/content_attributes_test.rb
68
+ - test/database.yml
69
+ - test/flag_test.rb
70
+ - test/schema.rb
71
+ - test/test_helper.rb
72
+ - test/user_association_test.rb
73
+ - MIT-LICENSE
74
+ - README
75
+ has_rdoc: true
76
+ homepage: http://github.com/courtenay/can_flag
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --main
82
+ - README.md
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ requirements: []
104
+
105
+ rubyforge_project:
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Rails plugin to allow users to flag content for review
110
+ test_files:
111
+ - test/can_be_flagged_options_test.rb
112
+ - test/content_association_test.rb
113
+ - test/content_attributes_test.rb
114
+ - test/flag_test.rb
115
+ - test/schema.rb
116
+ - test/test_helper.rb
117
+ - test/user_association_test.rb