can_be_flagged 0.0.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/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rails-brochure.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'sqlite3'
8
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ can_be_flagged (0.0.2)
5
+ activerecord (>= 3.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activemodel (3.0.7)
11
+ activesupport (= 3.0.7)
12
+ builder (~> 2.1.2)
13
+ i18n (~> 0.5.0)
14
+ activerecord (3.0.7)
15
+ activemodel (= 3.0.7)
16
+ activesupport (= 3.0.7)
17
+ arel (~> 2.0.2)
18
+ tzinfo (~> 0.3.23)
19
+ activesupport (3.0.7)
20
+ arel (2.0.10)
21
+ builder (2.1.2)
22
+ i18n (0.5.0)
23
+ sqlite3 (1.3.3)
24
+ tzinfo (0.3.27)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ can_be_flagged!
31
+ sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Dan Hixon
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.rdoc ADDED
@@ -0,0 +1,84 @@
1
+ Can Be Flagged
2
+ =================
3
+
4
+ Allows for flags to be added to multiple and different models.
5
+
6
+ == Resources
7
+
8
+ Install
9
+
10
+ * To install as a gem (recommended):
11
+ ** gem install can_be_flagged or
12
+ ** Just add "gem 'can_be_flagged'" to your Gemfile and "bundle install"
13
+
14
+ Generate your flag model:
15
+
16
+ ** Rails 3: rails g flags
17
+
18
+ Then migrate your database:
19
+
20
+ ** rake db:migrate
21
+
22
+ == Usage
23
+
24
+ * Mark your ActiveRecord model can_be_flagged.
25
+
26
+ class Post < ActiveRecord::Base
27
+ can_be_flagged
28
+ end
29
+
30
+ * Add a flag to a model instance
31
+
32
+ flaggable = Post.create(:text => "Don't be offended by this.")
33
+ flaggable.flags.create(:comment => "I am offended by that!")
34
+
35
+ * I like to add a counter cache column to my flaggable types:
36
+
37
+ add_column :posts, :flags_count, :integer
38
+
39
+ class Flag < ActiveRecord::Base
40
+ belongs_to :flaggable, :polymorphic=>true, :counter_cache=>true
41
+ end
42
+
43
+ * You can have different types of flags
44
+
45
+ class Article
46
+ can_be_flagged :offensive, :spam
47
+ end
48
+
49
+ * This gives you methods like this:
50
+ @article.offensive_flags.create(:comment => "gross!")
51
+ @article.spam_flags.create(:comment => "Don't sell your pharmaceuticals on this site!")
52
+ Aricle.find_spam_flags_for(@article)
53
+
54
+ * You can also add a callback
55
+
56
+ class Article
57
+ can_be_flagged :after_add => :flagged
58
+
59
+ def flagged
60
+ # send an email
61
+ # maybe delete this article if there are too many flags
62
+ end
63
+
64
+ end
65
+
66
+ * In fact you can pass any options that are accepted by has_many:
67
+
68
+ class Article
69
+ can_be_flagged :dependent=>:nullify
70
+ end
71
+
72
+ == Credits
73
+
74
+ Juxie - The code for this plugin is heavily influenced by Acts As Commentable.
75
+
76
+ Bacon Bear? - Frankenstien'd some features from acts_as_flaggable
77
+
78
+ == Contributors
79
+
80
+ Dan Hixon
81
+
82
+ == License
83
+
84
+ Flag This is Copyright © 2010-2011 Dan Hixon. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{can_be_flagged}
7
+ s.version = FlagThis::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dan Hixon"]
12
+ #s.autorequire = %q{can_be_flagged}
13
+ s.date = %q{2011-05-23}
14
+ s.summary = %q{Gem that provides flagging functionality for active record objects}
15
+ s.description = %q{Gem that provides flagging functionality for active record objects, just add can_be_flagged to your models.}
16
+ s.email = %q{danhixon@gmail.com}
17
+ s.homepage = "http://github.com/danhixon/can_be_flagged"
18
+
19
+ s.add_dependency('activerecord', '>= 3.0.0')
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'rails', 'init')
data/install.rb ADDED
@@ -0,0 +1,2 @@
1
+ puts "To create the flag model please run:"
2
+ puts "rails g flag"
@@ -0,0 +1,2 @@
1
+ require 'can_be_flagged_methods'
2
+ require 'flag_methods'
@@ -0,0 +1,59 @@
1
+ require 'active_record'
2
+ module ActiveRecord
3
+ module FlagThis #:nodoc:
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def can_be_flagged(options = {})
11
+ roles = options.delete(:roles)
12
+ flag_roles = roles.to_a.compact.map(&:to_sym)
13
+ write_inheritable_attribute(:flag_types, (flag_roles.blank? ? [:abuse] : flag_roles))
14
+ class_inheritable_reader(:flag_types)
15
+
16
+ #options = ((args.blank? or args[0].blank?) ? {} : args[0])
17
+
18
+ if !flag_roles.blank?
19
+ flag_roles.each do |role|
20
+ has_many "#{role.to_s}_flags".to_sym,
21
+ { :class_name => "Flag",
22
+ :as => :flaggable,
23
+ :dependent => :destroy,
24
+ :conditions => ["role = ?", role.to_s],
25
+ :before_add => Proc.new { |x, c| c.role = role.to_s }}.merge(options)
26
+ end
27
+ else
28
+ has_many :flags, {:as => :flaggable, :dependent => :destroy}.merge(options)
29
+ end
30
+
31
+ flag_types.each do |role|
32
+ method_name = (role == :abuse ? "flags" : "#{role.to_s}_flags").to_s
33
+ class_eval %{
34
+ def self.find_#{method_name}_for(obj)
35
+ flaggable = self.base_class.name
36
+ Flag.find_flags_for_flaggable(flaggable, obj.id, "#{role.to_s}")
37
+ end
38
+
39
+ def self.find_#{method_name}_by_user(user)
40
+ flaggable = self.base_class.name
41
+ Flag.where(["user_id = ? and flaggable_type = ? and role = ?", user.id, flaggable, "#{role.to_s}"]).order("created_at DESC")
42
+ end
43
+
44
+ def #{method_name}_ordered_by_submitted
45
+ Flag.find_flags_for_flaggable(self.class.name, id, "#{role.to_s}")
46
+ end
47
+
48
+ def add_#{method_name.singularize}(flag)
49
+ flag.role = "#{role.to_s}"
50
+ #{method_name} << flag
51
+ end
52
+ }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ ActiveRecord::Base.send(:include, ActiveRecord::FlagThis)
@@ -0,0 +1,41 @@
1
+ module FlagThis
2
+ # including this module into your Flag model will give you finders and named scopes
3
+ # useful for working with Flags.
4
+ module Flag
5
+
6
+ def self.included(flag_model)
7
+ flag_model.extend ClassMethods
8
+ flag_model.scope :in_order, flag_model.order('created_at ASC')
9
+ flag_model.scope :recent, flag_model.order('created_at DESC')
10
+ end
11
+
12
+ def is_flag_type?(type)
13
+ type.to_s == role.singularize.to_s
14
+ end
15
+
16
+ module ClassMethods
17
+ def this_is_a_flag
18
+ #after_create :callback_flaggable
19
+
20
+ end
21
+ # Helper class method to lookup all flags assigned
22
+ # to all flaggable types for a given user.
23
+ def find_flags_by_user(user, role = "abuse")
24
+ where(["user_id = ? and role = ?", user.id, role]).order("created_at DESC")
25
+ end
26
+
27
+ # Helper class method to look up all flags for
28
+ # flaggable class name and flaggable id.
29
+ def find_flags_for_flaggable(flaggable_str, flaggable_id, role = "abuse")
30
+ where(["flaggable_type = ? and flaggable_id = ? and role = ?", flaggable_str, flaggable_id, role]).order("created_at DESC")
31
+ end
32
+
33
+ # Helper class method to look up a flaggable object
34
+ # given the flaggable class name and id
35
+ def find_flaggable(flaggable_str, flaggable_id)
36
+ model = flaggable_str.constantize
37
+ model.respond_to?(:find_flags_for) ? model.find(flaggable_id) : nil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Copies flag.rb to app/models/.
3
+ Copies create_flags.rb to db/migrate
4
+
5
+ Examples:
6
+ `rails generate flags`
@@ -0,0 +1,18 @@
1
+ require 'rails/generators/migration'
2
+
3
+ class FlagsGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ def self.source_root
7
+ @_can_be_flagged_source_root ||= File.expand_path("../templates", __FILE__)
8
+ end
9
+
10
+ def self.next_migration_number(path)
11
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
12
+ end
13
+
14
+ def create_model_file
15
+ template "flag.rb", "app/models/flag.rb"
16
+ migration_template "create_flags.rb", "db/migrate/create_flags.rb"
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ class CreateFlags < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :flags do |t|
4
+ t.text :comment
5
+ t.references :flaggable, :polymorphic => true
6
+ t.references :user
7
+ # other roles could be spam, inappropriate, etc.
8
+ t.string :role, :default => "abuse"
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :flags, [:flaggable_type, :flaggable_id]
13
+ add_index :flags, :user_id
14
+ end
15
+
16
+ def self.down
17
+ drop_table :flags
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ class Flag < ActiveRecord::Base
2
+ include FlagThis::Flag
3
+ this_is_a_flag
4
+
5
+ belongs_to :flaggable, :polymorphic => true
6
+ # Flags belong to a user
7
+ belongs_to :user
8
+
9
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module FlagThis
2
+ VERSION = "0.0.2"
3
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'can_be_flagged')
2
+
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :can_be_flagged do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,142 @@
1
+ require 'test/unit'
2
+ require 'logger'
3
+ require File.expand_path(File.dirname(__FILE__) + '/../rails/init')
4
+
5
+ ActiveRecord::Migration.verbose = false
6
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
7
+
8
+ class FlagThisTest < Test::Unit::TestCase
9
+
10
+ def setup_flags
11
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/generators/flags/templates/create_flags')
12
+ CreateFlags.up
13
+ load(File.expand_path(File.dirname(__FILE__) + '/../lib/generators/flags/templates/flag.rb'))
14
+ end
15
+
16
+ def setup_test_models
17
+ load(File.expand_path(File.dirname(__FILE__) + '/schema.rb'))
18
+ load(File.expand_path(File.dirname(__FILE__) + '/models.rb'))
19
+ end
20
+
21
+ def setup
22
+ setup_flags
23
+ setup_test_models
24
+ end
25
+
26
+ def teardown
27
+ ActiveRecord::Base.connection.tables.each do |table|
28
+ ActiveRecord::Base.connection.drop_table(table)
29
+ end
30
+ end
31
+
32
+ def test_create_flag
33
+ post = Post.create(:text => "Awesome post !")
34
+ assert_not_nil post.flags.create().id
35
+
36
+ reply = Reply.create(:text => "I want you to buy some enlarging products.")
37
+ assert_not_nil reply.spam_flags.create(:comment => "this is definately spam.").id
38
+ assert_not_nil reply.offensive_flags.create(:comment => "this is offensive to me.").id
39
+ assert_raise NoMethodError do
40
+ reply.flags.create(:comment=>"unspecific flag")
41
+ end
42
+ end
43
+
44
+ def test_fetch_flags
45
+ post = Post.create(:text => "Awesome post !")
46
+ post.flags.create(:comment => "This is the first flag.")
47
+ flaggable = Post.find(1)
48
+ assert_equal 1, flaggable.flags.length
49
+ assert_equal "This is the first flag.", flaggable.flags.first.comment
50
+
51
+ reply = Reply.create(:text => "You should check out my website instead!")
52
+ offensive_flag = reply.offensive_flags.create(:comment => "I am so offended!")
53
+ assert_equal [offensive_flag], reply.offensive_flags
54
+ spam_flag = reply.spam_flags.create(:comment => "I can't stand the spam!")
55
+ assert_equal [spam_flag], reply.spam_flags
56
+ end
57
+
58
+ def test_find_flags_for_flaggable
59
+ post = Post.create(:text => "Awesome Post Part Deux.")
60
+ flag = post.flags.create(:comment => "This is the first flag.")
61
+ assert_equal [flag], Flag.find_flags_for_flaggable(post.class.name, post.id)
62
+ end
63
+
64
+ def test_find_flaggable
65
+ post = Post.create(:text => "Awesome post Parte Two")
66
+ flag = post.flags.create(:comment => "This is the first flag.")
67
+ assert_equal post, Flag.find_flaggable(post.class.name, post.id)
68
+ end
69
+
70
+ def test_find_flags_for
71
+ post = Post.create(:text => "Awesome post !")
72
+ flag = post.flags.create(:comment => "This is the first flag.")
73
+ assert_equal [flag], Post.find_flags_for(post)
74
+
75
+ reply = Reply.create(:text => "Shimmering Splendorous Sausage")
76
+ offensive_flag = reply.offensive_flags.create(:comment => "gross!")
77
+ assert_equal [offensive_flag], Reply.find_offensive_flags_for(reply)
78
+
79
+ spam_flag = reply.spam_flags.create(:comment => "I'm sick of sausage ads")
80
+ assert_equal [spam_flag], Reply.find_spam_flags_for(reply)
81
+ end
82
+
83
+ def test_find_flags_by_user
84
+ user = User.create(:name => "Mike")
85
+ user2 = User.create(:name => "Fake")
86
+ post = Post.create(:text => "Awesome post!")
87
+ flag = post.flags.create(:comment => "This is the first flag.", :user => user)
88
+ assert_equal true, Post.find_flags_by_user(user).include?(flag)
89
+ assert_equal false, Post.find_flags_by_user(user2).include?(flag)
90
+
91
+ reply = Reply.create(:text => "What would thousands of new visitors mean for your business?")
92
+ spam_flag = reply.spam_flags.create(:comment => "Stop selling stuff in replies!", :user => user)
93
+ assert_equal [spam_flag], Reply.find_spam_flags_by_user(user)
94
+
95
+ offensive_flag = reply.offensive_flags.create(:comment => "Offended!!", :user => user)
96
+ assert_equal [offensive_flag], Reply.find_offensive_flags_by_user(user)
97
+ end
98
+
99
+ def test_add_flag
100
+ post = Post.create(:text => "Super Post of a Post")
101
+ flag = Flag.new(:comment => 'I am not happy about this.')
102
+ post.add_flag(flag)
103
+ assert_equal [flag], post.flags
104
+
105
+ reply = Reply.create(:text => "I am so eager to try something else right now.")
106
+ spam_flag = Flag.new(:comment => 'super spammy')
107
+ reply.add_spam_flag(spam_flag)
108
+ assert_equal [spam_flag], reply.spam_flags
109
+
110
+ offensive_flag = Flag.new(:comment => 'super offensive')
111
+ reply.add_offensive_flag(offensive_flag)
112
+ assert_equal [offensive_flag], reply.offensive_flags
113
+ end
114
+
115
+ def test_is_flag_type
116
+ post = Post.create(:text => "Terrible Post")
117
+ flag = Flag.new(:comment => 'Super flag')
118
+ post.add_flag(flag)
119
+ assert_equal true, flag.is_flag_type?(:abuse)
120
+
121
+ reply = Reply.create(:text => "Happy people live longer")
122
+
123
+ flag = Flag.new(:comment => "That is unfounded and thereby offensive.")
124
+ reply.add_offensive_flag(flag)
125
+ assert_equal true, flag.is_flag_type?(:offensive)
126
+
127
+ spam = Flag.new(:comment => 'Stop trying to sell happiness. It not work.')
128
+ reply.add_spam_flag(spam)
129
+ assert_equal true, spam.is_flag_type?(:spam)
130
+ assert_equal false, spam.is_flag_type?(:abuse)
131
+
132
+ end
133
+
134
+ def test_after_flagged_callback
135
+ post = Post.create(:text => "Terrible Post")
136
+ post.flags.create(:comment => 'I wish to report this post.')
137
+ post.reload
138
+ assert_equal 1, post.flags_count
139
+
140
+ end
141
+
142
+ end
data/test/models.rb ADDED
@@ -0,0 +1,18 @@
1
+ class Post < ActiveRecord::Base
2
+ can_be_flagged :after_add=>:flagged
3
+
4
+ private
5
+ def flagged(flag)
6
+ self.flags_count += 1
7
+ self.save
8
+ end
9
+
10
+ end
11
+
12
+ class User < ActiveRecord::Base
13
+
14
+ end
15
+
16
+ class Reply < ActiveRecord::Base
17
+ can_be_flagged :roles => [:offensive, :spam]
18
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,17 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :posts do |t|
3
+ t.text :text
4
+ t.datetime
5
+ t.text :type
6
+ t.integer :flags_count, :default => 0
7
+ end
8
+
9
+ create_table :users do |u|
10
+ u.string :name
11
+ end
12
+
13
+ create_table :replies do |w|
14
+ w.string :text
15
+ end
16
+
17
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: can_be_flagged
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.2
6
+ platform: ruby
7
+ authors:
8
+ - Dan Hixon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-23 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activerecord
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 3.0.0
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: Gem that provides flagging functionality for active record objects, just add can_be_flagged to your models.
28
+ email: danhixon@gmail.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - MIT-LICENSE
39
+ - README.rdoc
40
+ - Rakefile
41
+ - can_be_flagged.gemspec
42
+ - init.rb
43
+ - install.rb
44
+ - lib/can_be_flagged.rb
45
+ - lib/can_be_flagged_methods.rb
46
+ - lib/flag_methods.rb
47
+ - lib/generators/flags/USAGE
48
+ - lib/generators/flags/flags_generator.rb
49
+ - lib/generators/flags/templates/create_flags.rb
50
+ - lib/generators/flags/templates/flag.rb
51
+ - lib/version.rb
52
+ - rails/init.rb
53
+ - tasks/flag_this_tasks.rake
54
+ - test/can_be_flagged_test.rb
55
+ - test/models.rb
56
+ - test/schema.rb
57
+ has_rdoc: true
58
+ homepage: http://github.com/danhixon/can_be_flagged
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.5.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Gem that provides flagging functionality for active record objects
85
+ test_files:
86
+ - test/can_be_flagged_test.rb
87
+ - test/models.rb
88
+ - test/schema.rb