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.
- data/MIT-LICENSE +20 -0
- data/README +62 -0
- data/lib/can_flag.rb +140 -0
- data/lib/can_flag/rails_commands.rb +30 -0
- data/lib/flag.rb +65 -0
- data/test/can_be_flagged_options_test.rb +27 -0
- data/test/content_association_test.rb +20 -0
- data/test/content_attributes_test.rb +21 -0
- data/test/database.yml +18 -0
- data/test/flag_test.rb +36 -0
- data/test/schema.rb +20 -0
- data/test/test_helper.rb +40 -0
- data/test/user_association_test.rb +32 -0
- metadata +117 -0
data/MIT-LICENSE
ADDED
@@ -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
|
data/lib/can_flag.rb
ADDED
@@ -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
|
data/lib/flag.rb
ADDED
@@ -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
|
data/test/database.yml
ADDED
@@ -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
|
data/test/flag_test.rb
ADDED
@@ -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
|
data/test/schema.rb
ADDED
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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
|