has_moderated 0.0.21 → 0.0.24
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +48 -9
- data/lib/has_moderated.rb +13 -234
- data/lib/has_moderated/carrier_wave.rb +2 -2
- data/lib/has_moderated/common.rb +129 -0
- data/lib/has_moderated/moderated_associations.rb +59 -0
- data/lib/has_moderated/moderated_attributes.rb +74 -0
- data/lib/has_moderated/moderated_create.rb +48 -0
- data/lib/has_moderated/moderated_destroy.rb +36 -0
- data/lib/has_moderated/moderation_model.rb +64 -23
- data/lib/has_moderated/user_hooks.rb +10 -0
- data/lib/has_moderated/version.rb +1 -1
- data/test/dummy/app/models/hjoin_test.rb +3 -0
- data/test/dummy/app/models/hmanythrough_join.rb +4 -0
- data/test/dummy/app/models/hmanythrough_test.rb +4 -0
- data/test/dummy/app/models/hone_test.rb +3 -0
- data/test/dummy/app/models/photo.rb +1 -1
- data/test/dummy/app/models/subtask.rb +1 -0
- data/test/dummy/app/models/task.rb +7 -2
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20111008195728_create_hone_tests.rb +9 -0
- data/test/dummy/db/migrate/20111008195809_create_hjoin_tests.rb +13 -0
- data/test/dummy/db/migrate/20111009193145_fix_join_table.rb +8 -0
- data/test/dummy/db/migrate/20111009201729_add_title_to_hone_tests.rb +5 -0
- data/test/dummy/db/migrate/20111009205517_create_hmanythrough_tests.rb +9 -0
- data/test/dummy/db/migrate/20111009205545_create_hmanythrough_joins.rb +11 -0
- data/test/dummy/db/schema.rb +33 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +4508 -0
- data/test/dummy/log/test.log +78674 -0
- data/test/dummy/public/test.jpg +0 -0
- data/test/dummy/public/uploads/task_photo/photo/1/test.jpg +0 -0
- data/test/dummy/spec/factories/hjoin_tests.rb +7 -0
- data/test/dummy/spec/factories/hmanythrough_joins.rb +9 -0
- data/test/dummy/spec/factories/hmanythrough_tests.rb +7 -0
- data/test/dummy/spec/factories/hone_tests.rb +7 -0
- data/test/dummy/spec/models/hjoin_test_spec.rb +36 -0
- data/test/dummy/spec/models/hmanythrough_test_spec.rb +99 -0
- data/test/dummy/spec/models/hone_test_spec.rb +36 -0
- data/test/dummy/spec/models/photo_holder_spec.rb +9 -17
- data/test/dummy/spec/models/photo_spec.rb +16 -29
- data/test/dummy/spec/models/task_photo_spec.rb +3 -9
- data/test/dummy/spec/models/task_spec.rb +36 -2
- data/test/dummy/spec/support/photos.rb +28 -0
- metadata +50 -8
- data/test/dummy/falaf/test.rb +0 -0
- data/test/dummy/public/uploads/task_photo/photo/1/logo_arnes.gif +0 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
module HasModerated
|
2
|
+
module ModeratedAssociations
|
3
|
+
module ClassMethods
|
4
|
+
def has_moderated_association *args
|
5
|
+
assocs = []
|
6
|
+
|
7
|
+
unless args.blank?
|
8
|
+
if args == [:all]
|
9
|
+
assocs = self.reflections.keys.reject do |r|
|
10
|
+
r == :moderations
|
11
|
+
end
|
12
|
+
else
|
13
|
+
assocs = args
|
14
|
+
assocs = [assocs] unless assocs.respond_to?("[]")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
#TODO: should add to some class var and clean duplicates
|
19
|
+
|
20
|
+
after_initialize do
|
21
|
+
assocs.each do |assoc_name|
|
22
|
+
assoc = self.association(assoc_name)
|
23
|
+
if assoc.reflection.collection?
|
24
|
+
def assoc.add_to_target_with_moderation record
|
25
|
+
if !owner.new_record? && !owner.has_moderated_updating
|
26
|
+
#TODO: add moderation
|
27
|
+
owner.add_associations_moderated(self.reflection.name => [record])
|
28
|
+
record
|
29
|
+
else
|
30
|
+
add_to_target_without_moderation record
|
31
|
+
end
|
32
|
+
end
|
33
|
+
assoc.class_eval do
|
34
|
+
alias_method_chain :add_to_target, :moderation
|
35
|
+
end
|
36
|
+
else
|
37
|
+
def assoc.replace_with_moderation(record, save = true)
|
38
|
+
if !owner.new_record? && !owner.has_moderated_updating
|
39
|
+
#TODO: add moderation
|
40
|
+
owner.add_associations_moderated(self.reflection.name => [record])
|
41
|
+
record
|
42
|
+
else
|
43
|
+
replace_without_moderation record
|
44
|
+
end
|
45
|
+
end
|
46
|
+
assoc.class_eval do
|
47
|
+
alias_method_chain :replace, :moderation
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module InstanceMethods
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module HasModerated
|
2
|
+
module ModeratedAttributes
|
3
|
+
module ClassMethods
|
4
|
+
def has_moderated *args, &block
|
5
|
+
# Lazily include the instance methods so we don't clutter up
|
6
|
+
# any more ActiveRecord models than we have to.
|
7
|
+
send :include, InstanceMethods
|
8
|
+
|
9
|
+
has_many :moderations, :as => :moderatable, :dependent => :destroy
|
10
|
+
|
11
|
+
cattr_accessor :moderated_attributes
|
12
|
+
cattr_accessor :moderated_options
|
13
|
+
|
14
|
+
self.moderated_attributes ||= []
|
15
|
+
self.moderated_options ||= {}
|
16
|
+
|
17
|
+
args.each do |arg|
|
18
|
+
if arg.respond_to?("[]")
|
19
|
+
self.moderated_options = self.moderated_options.merge(arg)
|
20
|
+
else
|
21
|
+
self.moderated_attributes.push(arg.to_s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# use an attribute to temporarily disable moderation before_save filter
|
26
|
+
attr_accessor :has_moderated_updating
|
27
|
+
|
28
|
+
# send moderated attributes to moderation before saving the model
|
29
|
+
before_save do
|
30
|
+
if self.valid? && @has_moderated_updating != true &&
|
31
|
+
# don't save moderated attributes if create is moderated and it's a new record
|
32
|
+
!(self.class.respond_to?("moderated_create_options") && new_record?)
|
33
|
+
moderations = self.to_moderation
|
34
|
+
if self.id.blank?
|
35
|
+
@pending_moderations ||= []
|
36
|
+
@pending_moderations.concat(moderations)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# when creating a new record, we must update moderations' id after it is known (after create)
|
42
|
+
after_create do
|
43
|
+
if !self.id.blank? && !@pending_moderations.blank?
|
44
|
+
@pending_moderations.each do |m|
|
45
|
+
m.update_attributes(:moderatable_id => self.id)
|
46
|
+
end
|
47
|
+
@pending_moderations.clear
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module InstanceMethods
|
54
|
+
|
55
|
+
def to_moderation
|
56
|
+
moderations = []
|
57
|
+
self.changes.each_pair do |att_name, values|
|
58
|
+
att_name = att_name.to_s
|
59
|
+
if self.class.moderated_attributes.include?(att_name) && !(values[0].blank? && values[1].blank?)
|
60
|
+
moderations.push(create_moderation_with_hooks!({
|
61
|
+
:moderatable_type => self.class.to_s,
|
62
|
+
:moderatable_id => self.id,
|
63
|
+
:attr_name => att_name,
|
64
|
+
:attr_value => self.attributes[att_name].to_yaml
|
65
|
+
}))
|
66
|
+
self.send(att_name+"=", values[0])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
moderations
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module HasModerated
|
2
|
+
module ModeratedCreate
|
3
|
+
module ClassMethods
|
4
|
+
def has_moderated_create *options
|
5
|
+
# Lazily include the instance methods so we don't clutter up
|
6
|
+
# any more ActiveRecord models than we have to.
|
7
|
+
send :include, InstanceMethods
|
8
|
+
|
9
|
+
# use an attribute to temporarily disable moderation before_save filter
|
10
|
+
attr_accessor :has_moderated_updating
|
11
|
+
|
12
|
+
# save options for use later
|
13
|
+
cattr_accessor :moderated_create_options
|
14
|
+
self.moderated_create_options = (options.count > 0) ? options[0] : {}
|
15
|
+
|
16
|
+
alias_method_chain :create_or_update, :moderation
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
def create_or_update_with_moderation *args
|
22
|
+
if valid? && new_record? && @has_moderated_updating != true
|
23
|
+
to_moderation_created
|
24
|
+
true
|
25
|
+
else
|
26
|
+
create_or_update_without_moderation *args
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_moderation_created
|
31
|
+
options = self.class.moderated_create_options
|
32
|
+
assoc_attrs = HasModerated::Common::get_assocs_for_moderation(options[:with_associations], self)
|
33
|
+
|
34
|
+
attr_value = {
|
35
|
+
:main_model => get_moderation_attributes(self),
|
36
|
+
:associations => assoc_attrs
|
37
|
+
}
|
38
|
+
|
39
|
+
create_moderation_with_hooks!({
|
40
|
+
:moderatable_type => self.class.to_s,
|
41
|
+
:moderatable_id => self.id,
|
42
|
+
:attr_name => "-",
|
43
|
+
:attr_value => attr_value.to_yaml
|
44
|
+
})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module HasModerated
|
2
|
+
module ModeratedDestroy
|
3
|
+
module ClassMethods
|
4
|
+
def has_moderated_destroy *options
|
5
|
+
# Lazily include the instance methods so we don't clutter up
|
6
|
+
# any more ActiveRecord models than we have to.
|
7
|
+
send :include, InstanceMethods
|
8
|
+
|
9
|
+
# use an attribute to temporarily disable moderation before_save filter
|
10
|
+
attr_accessor :has_moderated_updating
|
11
|
+
|
12
|
+
alias_method_chain :destroy, :moderation
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module InstanceMethods
|
17
|
+
def destroy_with_moderation *args
|
18
|
+
if @has_moderated_updating == true
|
19
|
+
destroy_without_moderation *args
|
20
|
+
else
|
21
|
+
to_moderation_destroyed
|
22
|
+
true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_moderation_destroyed
|
27
|
+
create_moderation_with_hooks!({
|
28
|
+
:moderatable_type => self.class.to_s,
|
29
|
+
:moderatable_id => self.id,
|
30
|
+
:attr_name => "-",
|
31
|
+
:attr_value => "destroy"
|
32
|
+
})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -24,40 +24,81 @@ module HasModerated
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
27
|
+
def add_assoc_to_record arec, rec, assoc_name
|
28
|
+
return unless rec && arec
|
29
|
+
|
30
|
+
assoc = rec.class.reflections[assoc_name.to_sym]
|
31
|
+
|
32
|
+
if assoc.macro == :has_and_belongs_to_many || !assoc.options[:through].blank?
|
33
|
+
arec.send(rec.class.to_s.underscore.pluralize) << rec
|
34
|
+
elsif assoc.macro == :has_many || assoc.macro == :has_one
|
35
|
+
arec.send(rec.class.to_s.underscore + "=", rec)
|
36
|
+
#fk = if assoc.respond_to?(:foreign_key)
|
37
|
+
# assoc.foreign_key
|
38
|
+
#else # Rails < v3.1
|
39
|
+
# assoc.primary_key_name
|
40
|
+
#end
|
41
|
+
#arec.send(fk.to_s+"=", rec.id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def try_moderatable_updating rec
|
46
|
+
rec.has_moderated_updating = true if rec.respond_to?("has_moderated_updating=")
|
47
|
+
yield(rec)
|
48
|
+
rec.has_moderated_updating = false if rec.respond_to?("has_moderated_updating=")
|
49
|
+
end
|
50
|
+
|
51
|
+
def update_associations_from_value rec, interpreted_assocs = nil
|
52
|
+
interpreted_assocs ||= interpreted_value[:associations]
|
28
53
|
# in case it's empty
|
29
|
-
|
54
|
+
interpreted_assocs ||= {}
|
30
55
|
# loop association types, e.g. :comments
|
31
|
-
|
56
|
+
interpreted_assocs.each_pair do |assoc_name, assoc_records|
|
32
57
|
# read reflections attribute to determine proper class name and primary key
|
33
58
|
assoc_details = rec.class.reflections[assoc_name.to_sym]
|
34
59
|
m = assoc_details.class_name.constantize
|
60
|
+
|
61
|
+
fk = if assoc_details.respond_to?(:foreign_key)
|
62
|
+
assoc_details.foreign_key
|
63
|
+
else # Rails < v3.1
|
64
|
+
assoc_details.primary_key_name
|
65
|
+
end
|
35
66
|
|
36
67
|
# all instances for this association type
|
37
68
|
assoc_records.each do |attrs|
|
38
69
|
next if attrs.blank?
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
70
|
+
if attrs.class != Fixnum && !attrs[:id].blank?
|
71
|
+
attrs = attrs[:id].to_i
|
72
|
+
end
|
73
|
+
try_moderatable_updating(rec) do
|
74
|
+
arec = nil
|
75
|
+
# PARAM = ID
|
76
|
+
if attrs.class == Fixnum
|
77
|
+
arec = m.find_by_id(attrs)
|
78
|
+
add_assoc_to_record(arec, rec, assoc_name)
|
79
|
+
# PARAM = Hash (create)
|
80
|
+
else
|
81
|
+
arec = m.new
|
82
|
+
# set foreign key first, may be required sometimes
|
83
|
+
add_assoc_to_record(arec, rec, assoc_name)
|
84
|
+
attrs && attrs.each_pair do |key, val|
|
85
|
+
next if key.to_s == "associations" || key.to_s == 'id' || key.to_s == fk
|
86
|
+
arec.send(key.to_s+"=", val)
|
87
|
+
end
|
88
|
+
if attrs[:associations]
|
89
|
+
update_associations_from_value arec, attrs[:associations]
|
90
|
+
end
|
52
91
|
end
|
53
|
-
arec
|
54
|
-
|
55
|
-
|
92
|
+
if arec
|
93
|
+
try_moderatable_updating(arec) do
|
94
|
+
arec.save(:validate => false) # don't run validations
|
95
|
+
end
|
96
|
+
if assoc_details.collection?
|
97
|
+
rec.send(assoc_name.to_s) << arec if arec
|
98
|
+
else
|
99
|
+
rec.send(assoc_name.to_s + "=", arec) if arec
|
100
|
+
end
|
56
101
|
end
|
57
|
-
# disable moderation for associated model (if moderated)
|
58
|
-
arec.has_moderated_updating = true if arec.respond_to?("has_moderated_updating=")
|
59
|
-
arec.save(:validate => false) # don't run validations
|
60
|
-
arec.has_moderated_updating = false if arec.respond_to?("has_moderated_updating=")
|
61
102
|
end
|
62
103
|
end
|
63
104
|
end
|
@@ -2,7 +2,12 @@ class Task < ActiveRecord::Base
|
|
2
2
|
attr_accessible :title
|
3
3
|
has_many :subtasks
|
4
4
|
has_many :task_photos
|
5
|
-
|
6
|
-
|
5
|
+
has_and_belongs_to_many :hjoin_tests
|
6
|
+
has_one :hone_test
|
7
|
+
has_many :hmanythrough_join
|
8
|
+
has_many :hmanythrough_test, :through => :hmanythrough_join
|
9
|
+
has_moderated :title, :desc
|
10
|
+
has_moderated_create :with_associations => [:subtasks, :task_photos, :hjoin_tests, :hone_test, :hmanythrough_test, :hmanythrough_join]
|
11
|
+
has_moderated_association :all
|
7
12
|
has_moderated_destroy
|
8
13
|
end
|
Binary file
|