has_moderated 0.0.34 → 1.0.alpha
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/README.rdoc +17 -0
- data/lib/generators/has_moderated/install/templates/migration.rb +4 -3
- data/lib/has_moderated/adapters/active_record.rb +109 -0
- data/lib/has_moderated/adapters/proxy.rb +23 -0
- data/lib/has_moderated/associations/base.rb +157 -0
- data/lib/has_moderated/associations/collection.rb +123 -0
- data/lib/has_moderated/associations/has_many.rb +15 -0
- data/lib/has_moderated/associations/has_one.rb +58 -0
- data/lib/has_moderated/carrier_wave.rb +3 -3
- data/lib/has_moderated/common.rb +62 -113
- data/lib/has_moderated/moderated_attributes.rb +24 -11
- data/lib/has_moderated/moderated_create.rb +22 -14
- data/lib/has_moderated/moderated_destroy.rb +11 -10
- data/lib/has_moderated/moderation_model.rb +6 -200
- data/lib/has_moderated/user_hooks.rb +3 -2
- data/lib/has_moderated/version.rb +1 -1
- data/lib/has_moderated.rb +15 -7
- data/test/dummy/app/models/moderation.rb +0 -0
- data/test/dummy/app/models/subtask.rb +0 -1
- data/test/dummy/app/models/task.rb +0 -13
- data/test/dummy/app/models/task_connection.rb +4 -0
- data/test/dummy/db/migrate/20120515155730_create_moderations2.rb +20 -0
- data/test/dummy/db/migrate/20120515174306_prepare_for_new_tests.rb +36 -0
- data/test/dummy/db/migrate/20120515175621_remove_photo_relateds.rb +8 -0
- data/test/dummy/db/schema.rb +17 -96
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +35 -0
- data/test/dummy/log/test.log +81290 -0
- data/test/dummy/spec/models/task_spec.rb +414 -247
- data/test/dummy/spec/spec_helper.rb +4 -0
- metadata +26 -57
- data/lib/has_moderated/moderated_associations.rb +0 -69
- data/test/dummy/app/models/habtm_name_test.rb +0 -3
- data/test/dummy/app/models/hjoin_test.rb +0 -3
- data/test/dummy/app/models/hmany_fk_test.rb +0 -3
- data/test/dummy/app/models/hmanythrough_join.rb +0 -4
- data/test/dummy/app/models/hmanythrough_test.rb +0 -4
- data/test/dummy/app/models/hone_as_test.rb +0 -3
- data/test/dummy/app/models/hone_test.rb +0 -3
- data/test/dummy/app/models/hook_test.rb +0 -9
- data/test/dummy/app/models/photo.rb +0 -8
- data/test/dummy/app/models/photo_holder.rb +0 -4
- data/test/dummy/app/models/photo_related.rb +0 -3
- data/test/dummy/app/models/task_all.rb +0 -4
- data/test/dummy/app/models/task_photo.rb +0 -5
- data/test/dummy/spec/models/habtm_name_test_spec.rb +0 -22
- data/test/dummy/spec/models/hjoin_test_spec.rb +0 -54
- data/test/dummy/spec/models/hmany_fk_test_spec.rb +0 -36
- data/test/dummy/spec/models/hmanythrough_test_spec.rb +0 -99
- data/test/dummy/spec/models/hone_as_test_spec.rb +0 -36
- data/test/dummy/spec/models/hone_test_spec.rb +0 -36
- data/test/dummy/spec/models/hooks_spec.rb +0 -30
- data/test/dummy/spec/models/photo_holder_spec.rb +0 -21
- data/test/dummy/spec/models/photo_spec.rb +0 -69
- data/test/dummy/spec/models/task_photo_spec.rb +0 -25
data/lib/has_moderated/common.rb
CHANGED
|
@@ -4,140 +4,89 @@ module HasModerated
|
|
|
4
4
|
base.send :include, InstanceMethods
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
+
def self.init(klass)
|
|
8
|
+
unless klass.class_variable_defined? "@@moderation_disabled"
|
|
9
|
+
klass.class_eval do
|
|
10
|
+
attr_accessor :moderation_disabled
|
|
11
|
+
@@moderation_disabled = false
|
|
12
|
+
end
|
|
13
|
+
HasModerated::Adapters::Proxy::add_moderations_association klass
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.try_without_moderation rec
|
|
18
|
+
# TODO: fix this, this method should only be avail. to moderated models
|
|
19
|
+
if rec.respond_to?(:moderation_disabled)
|
|
20
|
+
rec.without_moderation(true) { |rec| yield(rec) }
|
|
21
|
+
else
|
|
22
|
+
yield(rec)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# calls user hooks for creation of a new moderation
|
|
27
|
+
def self.call_creating_hook model, moderation
|
|
28
|
+
#todo use model.class.moderation_hooks[:creating_moderation]
|
|
29
|
+
if model.class.respond_to?(:moderation_hooks)
|
|
30
|
+
model.class.moderation_hooks[:creating] ||= []
|
|
31
|
+
model.class.moderation_hooks[:creating].each do |hook|
|
|
32
|
+
model.instance_exec moderation, &hook
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
7
37
|
module InstanceMethods
|
|
8
|
-
def
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
38
|
+
def without_moderation(do_disable = true)
|
|
39
|
+
raise "moderation already disabled - illegal nesting" if self.moderation_disabled && do_disable
|
|
40
|
+
self.moderation_disabled = true if do_disable
|
|
41
|
+
yield(self)
|
|
42
|
+
self.moderation_disabled = false if do_disable
|
|
13
43
|
end
|
|
14
44
|
|
|
15
|
-
def
|
|
16
|
-
self
|
|
17
|
-
yield(self)
|
|
18
|
-
self.has_moderated_updating = false if disable_moderation
|
|
45
|
+
def get_moderation_attributes
|
|
46
|
+
HasModerated::Adapters::Proxy::get_default_moderation_attributes(self)
|
|
19
47
|
end
|
|
20
48
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
49
|
+
def create_moderation_with_hooks!(*args)
|
|
50
|
+
m = self.moderations.build(:data => args.first)
|
|
51
|
+
HasModerated::Common::call_creating_hook(self, m)
|
|
52
|
+
m.save!
|
|
53
|
+
m
|
|
27
54
|
end
|
|
28
55
|
|
|
29
|
-
def add_associations_moderated
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
through_assocs[join_model].push(assoc)
|
|
56
|
+
def add_associations_moderated assocs_data
|
|
57
|
+
# convert associations data so it can be serialized
|
|
58
|
+
assocs_processed = Hash.new
|
|
59
|
+
assocs_data.each_pair do |assoc_name, assoc_data_array|
|
|
60
|
+
assocs_processed[assoc_name] = []
|
|
61
|
+
assoc_data_array.each do |assoc_data|
|
|
62
|
+
# convert assoc data to either ID or, if it's a new record, hash of its attributes
|
|
63
|
+
pdata = HasModerated::Adapters::Proxy::hashize_association(self, assoc_name, assoc_data)
|
|
64
|
+
assocs_processed[assoc_name].push(pdata)
|
|
39
65
|
end
|
|
40
66
|
end
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
assocs.each_pair do |assoc_name, assoc|
|
|
44
|
-
one_assoc = []
|
|
45
|
-
assoc.each do |m|
|
|
46
|
-
if m.class == Fixnum
|
|
47
|
-
one_assoc.push(m)
|
|
48
|
-
elsif m.new_record?
|
|
49
|
-
one_assoc.push(from_record.get_moderation_attributes(m))
|
|
50
|
-
else
|
|
51
|
-
one_assoc.push(m.id)
|
|
52
|
-
end
|
|
53
|
-
if through_assocs[assoc_name.to_sym]
|
|
54
|
-
one_assoc.last[:associations] = HasModerated::Common::get_assocs_for_moderation(through_assocs[assoc_name.to_sym], m)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
assoc_attrs[assoc_name] = one_assoc unless one_assoc.empty?
|
|
58
|
-
end
|
|
59
|
-
|
|
67
|
+
|
|
68
|
+
# create moderation for adding the associations and return it
|
|
60
69
|
moderations = []
|
|
61
|
-
|
|
62
|
-
moderations.push(create_moderation_with_hooks!(
|
|
63
|
-
:
|
|
64
|
-
|
|
65
|
-
:attr_name => "-",
|
|
66
|
-
:attr_value => { :associations => assoc_attrs }
|
|
67
|
-
}))
|
|
70
|
+
unless assocs_processed.empty?
|
|
71
|
+
moderations.push(create_moderation_with_hooks!(
|
|
72
|
+
:associations => assocs_processed
|
|
73
|
+
))
|
|
68
74
|
end
|
|
69
75
|
|
|
70
76
|
moderations
|
|
71
77
|
end
|
|
72
78
|
|
|
79
|
+
# moderate removing associations
|
|
73
80
|
def delete_associations_moderated(assocs)
|
|
74
81
|
moderations = []
|
|
75
|
-
|
|
76
|
-
moderations.push(create_moderation_with_hooks!(
|
|
77
|
-
:
|
|
78
|
-
|
|
79
|
-
:attr_name => "-",
|
|
80
|
-
:attr_value => { :delete_associations => assocs }
|
|
81
|
-
}))
|
|
82
|
+
unless assocs.empty?
|
|
83
|
+
moderations.push(create_moderation_with_hooks!(
|
|
84
|
+
:delete_associations => assocs
|
|
85
|
+
))
|
|
82
86
|
end
|
|
83
87
|
|
|
84
88
|
moderations
|
|
85
89
|
end
|
|
86
90
|
end
|
|
87
|
-
|
|
88
|
-
def self.get_assocs_for_moderation assocs, from_record = nil
|
|
89
|
-
from_record ||= self
|
|
90
|
-
return if assocs.blank?
|
|
91
|
-
|
|
92
|
-
if assocs == :all
|
|
93
|
-
assocs = from_record.class.reflections.keys.reject do |r|
|
|
94
|
-
r == :moderations
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
assocs = [assocs] unless assocs.respond_to?("[]")
|
|
99
|
-
|
|
100
|
-
# check for through assocs
|
|
101
|
-
assocs = assocs.dup
|
|
102
|
-
through_assocs = {}
|
|
103
|
-
assocs.each do |assoc|
|
|
104
|
-
join_model = from_record.class.reflections[assoc.to_sym].options[:through]
|
|
105
|
-
if join_model
|
|
106
|
-
join_model = join_model.to_sym
|
|
107
|
-
through_assocs[join_model] ||= []
|
|
108
|
-
through_assocs[join_model].push(assoc)
|
|
109
|
-
assocs.push(join_model) unless assocs.include?(join_model)
|
|
110
|
-
#assocs.delete(assoc)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
assoc_attrs = {}
|
|
115
|
-
assocs.each do |assoc|
|
|
116
|
-
one_assoc = []
|
|
117
|
-
assoc_value = from_record.send(assoc)
|
|
118
|
-
# if it's has_one it won't be an array
|
|
119
|
-
assoc_value = [assoc_value] if assoc_value && assoc_value.class != Array
|
|
120
|
-
assoc_value ||= []
|
|
121
|
-
assoc_value.each do |m|
|
|
122
|
-
if m.new_record?
|
|
123
|
-
one_assoc.push(from_record.get_moderation_attributes(m))
|
|
124
|
-
else
|
|
125
|
-
one_assoc.push(m.id)
|
|
126
|
-
end
|
|
127
|
-
if through_assocs[assoc.to_sym]
|
|
128
|
-
one_assoc.last[:associations] = get_assocs_for_moderation(through_assocs[assoc.to_sym], m)
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
assoc_attrs[assoc] = one_assoc unless one_assoc.empty?
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
assoc_attrs
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def self.call_creating_hook model, moderation
|
|
138
|
-
if model.class.respond_to?(:moderation_creating_hook)
|
|
139
|
-
model.instance_exec moderation, &(model.class.moderation_creating_hook)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
91
|
end
|
|
143
92
|
end
|
|
@@ -2,12 +2,11 @@ module HasModerated
|
|
|
2
2
|
module ModeratedAttributes
|
|
3
3
|
module ClassMethods
|
|
4
4
|
def has_moderated *args, &block
|
|
5
|
+
HasModerated::Common::init(self)
|
|
5
6
|
# Lazily include the instance methods so we don't clutter up
|
|
6
7
|
# any more ActiveRecord models than we have to.
|
|
7
8
|
send :include, InstanceMethods
|
|
8
9
|
|
|
9
|
-
has_many :moderations, :as => :moderatable, :dependent => :destroy
|
|
10
|
-
|
|
11
10
|
cattr_accessor :moderated_attributes
|
|
12
11
|
cattr_accessor :moderated_options
|
|
13
12
|
|
|
@@ -23,11 +22,11 @@ module HasModerated
|
|
|
23
22
|
end
|
|
24
23
|
|
|
25
24
|
# use an attribute to temporarily disable moderation before_save filter
|
|
26
|
-
attr_accessor :
|
|
25
|
+
attr_accessor :moderation_disabled
|
|
27
26
|
|
|
28
27
|
# send moderated attributes to moderation before saving the model
|
|
29
28
|
before_save do
|
|
30
|
-
if self.valid? && @
|
|
29
|
+
if self.valid? && @moderation_disabled != true &&
|
|
31
30
|
# don't save moderated attributes if create is moderated and it's a new record
|
|
32
31
|
!(self.class.respond_to?("moderated_create_options") && new_record?)
|
|
33
32
|
moderations = self.to_moderation
|
|
@@ -39,6 +38,7 @@ module HasModerated
|
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
# when creating a new record, we must update moderations' id after it is known (after create)
|
|
41
|
+
# TODO is this even necessary when using assoc.create ?
|
|
42
42
|
after_create do
|
|
43
43
|
if !self.id.blank? && !@pending_moderations.blank?
|
|
44
44
|
@pending_moderations.each do |m|
|
|
@@ -50,19 +50,32 @@ module HasModerated
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
module
|
|
53
|
+
module ApplyModeration
|
|
54
|
+
def self.apply(moderation, value)
|
|
55
|
+
if value[:attributes].present?
|
|
56
|
+
rec = moderation.moderatable
|
|
57
|
+
rec.without_moderation do
|
|
58
|
+
value[:attributes].each_pair do |attr_name, attr_value|
|
|
59
|
+
# bypass attr_accessible protection
|
|
60
|
+
rec.send(attr_name.to_s+"=", attr_value)
|
|
61
|
+
end
|
|
62
|
+
rec.save(:validate => false) # don't run validations
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
54
67
|
|
|
68
|
+
module InstanceMethods
|
|
55
69
|
def to_moderation
|
|
56
70
|
moderations = []
|
|
57
71
|
self.changes.each_pair do |att_name, values|
|
|
58
72
|
att_name = att_name.to_s
|
|
59
73
|
if self.class.moderated_attributes.include?(att_name) && !(values[0].blank? && values[1].blank?)
|
|
60
|
-
moderations.push(create_moderation_with_hooks!(
|
|
61
|
-
:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}))
|
|
74
|
+
moderations.push(create_moderation_with_hooks!(
|
|
75
|
+
:attributes => {
|
|
76
|
+
att_name => self.attributes[att_name]
|
|
77
|
+
}
|
|
78
|
+
))
|
|
66
79
|
self.send(att_name+"=", values[0])
|
|
67
80
|
end
|
|
68
81
|
end
|
|
@@ -2,13 +2,11 @@ module HasModerated
|
|
|
2
2
|
module ModeratedCreate
|
|
3
3
|
module ClassMethods
|
|
4
4
|
def has_moderated_create *options
|
|
5
|
+
HasModerated::Common::init(self)
|
|
5
6
|
# Lazily include the instance methods so we don't clutter up
|
|
6
7
|
# any more ActiveRecord models than we have to.
|
|
7
8
|
send :include, InstanceMethods
|
|
8
9
|
|
|
9
|
-
# use an attribute to temporarily disable moderation before_save filter
|
|
10
|
-
attr_accessor :has_moderated_updating
|
|
11
|
-
|
|
12
10
|
# save options for use later
|
|
13
11
|
cattr_accessor :moderated_create_options
|
|
14
12
|
self.moderated_create_options = (options.count > 0) ? options[0] : {}
|
|
@@ -17,9 +15,26 @@ module HasModerated
|
|
|
17
15
|
end
|
|
18
16
|
end
|
|
19
17
|
|
|
18
|
+
module ApplyModeration
|
|
19
|
+
def self.apply(moderation, value)
|
|
20
|
+
if value[:create].present?
|
|
21
|
+
# create the main record
|
|
22
|
+
rec = moderation.moderatable_type.constantize.new
|
|
23
|
+
attrs = value[:create][:attributes]
|
|
24
|
+
# bypass attr_accessible protection
|
|
25
|
+
attrs && attrs.each_pair do |key, val|
|
|
26
|
+
rec.send(key.to_s+"=", val) unless key.to_s == 'id'
|
|
27
|
+
end
|
|
28
|
+
rec.without_moderation { rec.save(:validate => false) }
|
|
29
|
+
moderation.moderatable = rec
|
|
30
|
+
HasModerated::Associations::Base::ApplyModeration::apply(moderation, value[:create])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
20
35
|
module InstanceMethods
|
|
21
36
|
def create_or_update_with_moderation *args
|
|
22
|
-
if valid? && new_record? && @
|
|
37
|
+
if valid? && new_record? && @moderation_disabled != true
|
|
23
38
|
to_moderation_created
|
|
24
39
|
true
|
|
25
40
|
else
|
|
@@ -29,18 +44,11 @@ module HasModerated
|
|
|
29
44
|
|
|
30
45
|
def to_moderation_created
|
|
31
46
|
options = self.class.moderated_create_options
|
|
32
|
-
assoc_attrs = HasModerated::
|
|
47
|
+
assoc_attrs = HasModerated::Adapters::ActiveRecord::get_assocs_for_moderation(options[:with_associations], self)
|
|
33
48
|
|
|
34
|
-
|
|
35
|
-
:
|
|
49
|
+
create_moderation_with_hooks!(:create => {
|
|
50
|
+
:attributes => get_moderation_attributes,
|
|
36
51
|
: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
52
|
})
|
|
45
53
|
end
|
|
46
54
|
end
|
|
@@ -2,20 +2,26 @@ module HasModerated
|
|
|
2
2
|
module ModeratedDestroy
|
|
3
3
|
module ClassMethods
|
|
4
4
|
def has_moderated_destroy *options
|
|
5
|
+
HasModerated::Common::init(self)
|
|
5
6
|
# Lazily include the instance methods so we don't clutter up
|
|
6
7
|
# any more ActiveRecord models than we have to.
|
|
7
8
|
send :include, InstanceMethods
|
|
8
9
|
|
|
9
|
-
# use an attribute to temporarily disable moderation before_save filter
|
|
10
|
-
attr_accessor :has_moderated_updating
|
|
11
|
-
|
|
12
10
|
alias_method_chain :destroy, :moderation
|
|
13
11
|
end
|
|
14
12
|
end
|
|
15
13
|
|
|
14
|
+
module ApplyModeration
|
|
15
|
+
def self.apply(moderation, value)
|
|
16
|
+
if value.to_s == "destroy"
|
|
17
|
+
moderation.moderatable.without_moderation { |m| m.destroy }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
16
22
|
module InstanceMethods
|
|
17
23
|
def destroy_with_moderation *args
|
|
18
|
-
if @
|
|
24
|
+
if @moderation_disabled == true
|
|
19
25
|
destroy_without_moderation *args
|
|
20
26
|
else
|
|
21
27
|
to_moderation_destroyed
|
|
@@ -24,12 +30,7 @@ module HasModerated
|
|
|
24
30
|
end
|
|
25
31
|
|
|
26
32
|
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
|
+
create_moderation_with_hooks!(:destroy)
|
|
33
34
|
end
|
|
34
35
|
end
|
|
35
36
|
end
|
|
@@ -1,206 +1,12 @@
|
|
|
1
1
|
module HasModerated
|
|
2
2
|
module ModerationModel
|
|
3
|
-
|
|
4
|
-
def interpreted_value
|
|
5
|
-
@interpreted_value ||= if attr_name == '-'
|
|
6
|
-
YAML::load(attr_value)
|
|
7
|
-
else
|
|
8
|
-
attr_value
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def create_from_value
|
|
13
|
-
if moderatable_id.blank?
|
|
14
|
-
# create the main record
|
|
15
|
-
rec = moderatable_type.constantize.new
|
|
16
|
-
attrs = interpreted_value[:main_model]
|
|
17
|
-
# bypass attr_accessible protection
|
|
18
|
-
attrs && attrs.each_pair do |key, val|
|
|
19
|
-
rec.send(key.to_s+"=", val) unless key.to_s == 'id'
|
|
20
|
-
end
|
|
21
|
-
rec
|
|
22
|
-
else
|
|
23
|
-
nil
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def delete_assoc_from_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? || assoc.macro == :has_many
|
|
33
|
-
rec.send(assoc_name).delete(arec)
|
|
34
|
-
else
|
|
35
|
-
raise "Cannot delete association for this type of associations!"
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def delete_associations_from_value rec, interpreted_assocs = nil
|
|
40
|
-
interpreted_assocs ||= interpreted_value[:delete_associations]
|
|
41
|
-
# in case it's empty
|
|
42
|
-
interpreted_assocs ||= {}
|
|
43
|
-
|
|
44
|
-
interpreted_assocs.each_pair do |assoc_name, assoc_records|
|
|
45
|
-
# read reflections attribute to determine proper class name and primary key
|
|
46
|
-
assoc_details = rec.class.reflections[assoc_name.to_sym]
|
|
47
|
-
m = assoc_details.class_name.constantize
|
|
48
|
-
|
|
49
|
-
fk = if assoc_details.respond_to?(:foreign_key)
|
|
50
|
-
assoc_details.foreign_key
|
|
51
|
-
else # Rails < v3.1
|
|
52
|
-
assoc_details.primary_key_name
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# all instances for this association type
|
|
56
|
-
assoc_records.each do |attrs|
|
|
57
|
-
next if attrs.blank?
|
|
58
|
-
next if attrs.class != Fixnum
|
|
59
|
-
try_moderatable_updating(rec) do
|
|
60
|
-
arec = nil
|
|
61
|
-
# PARAM = ID
|
|
62
|
-
arec = m.find_by_id(attrs)
|
|
63
|
-
delete_assoc_from_record(arec, rec, assoc_name)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def add_assoc_to_record arec, rec, assoc_name
|
|
70
|
-
return unless rec && arec
|
|
71
|
-
|
|
72
|
-
assoc = rec.class.reflections[assoc_name.to_sym]
|
|
73
|
-
|
|
74
|
-
if assoc.macro == :has_and_belongs_to_many || !assoc.options[:through].blank?
|
|
75
|
-
field = if !assoc.options[:join_table].blank?
|
|
76
|
-
jointable = assoc.options[:join_table].to_s
|
|
77
|
-
results = arec.class.reflections.reject do |assoc_name, assoc|
|
|
78
|
-
!(assoc.options[:join_table] && assoc.options[:join_table].to_s == jointable)
|
|
79
|
-
end
|
|
80
|
-
if results.blank?
|
|
81
|
-
raise "has_moderated: Cannot determine join table for a Habtm association!"
|
|
82
|
-
end
|
|
83
|
-
results.first[1].name.to_s
|
|
84
|
-
else
|
|
85
|
-
rec.class.to_s.underscore.pluralize
|
|
86
|
-
end
|
|
87
|
-
arec.send(field) << rec
|
|
88
|
-
elsif assoc.macro == :has_many || assoc.macro == :has_one
|
|
89
|
-
field = if !assoc.options[:as].blank?
|
|
90
|
-
assoc.options[:as].to_s
|
|
91
|
-
elsif !assoc.options[:foreign_key].blank?
|
|
92
|
-
fk = assoc.options[:foreign_key].to_s
|
|
93
|
-
results = arec.class.reflections.reject do |assoc_name, assoc|
|
|
94
|
-
!(assoc.options[:foreign_key] && assoc.options[:foreign_key].to_s == fk)
|
|
95
|
-
end
|
|
96
|
-
if results.blank?
|
|
97
|
-
raise "Please set foreign_key for both belongs_to and has_one/has_many!"
|
|
98
|
-
end
|
|
99
|
-
results.first[1].name.to_s
|
|
100
|
-
else
|
|
101
|
-
rec.class.to_s.underscore
|
|
102
|
-
end
|
|
103
|
-
arec.send(field + "=", rec)
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def try_moderatable_updating rec
|
|
108
|
-
rec.has_moderated_updating = true if rec.respond_to?("has_moderated_updating=")
|
|
109
|
-
yield(rec)
|
|
110
|
-
rec.has_moderated_updating = false if rec.respond_to?("has_moderated_updating=")
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def update_associations_from_value rec, interpreted_assocs = nil
|
|
114
|
-
interpreted_assocs ||= interpreted_value[:associations]
|
|
115
|
-
# in case it's empty
|
|
116
|
-
interpreted_assocs ||= {}
|
|
117
|
-
# loop association types, e.g. :comments
|
|
118
|
-
interpreted_assocs.each_pair do |assoc_name, assoc_records|
|
|
119
|
-
# read reflections attribute to determine proper class name and primary key
|
|
120
|
-
assoc_details = rec.class.reflections[assoc_name.to_sym]
|
|
121
|
-
m = assoc_details.class_name.constantize
|
|
122
|
-
|
|
123
|
-
fk = if assoc_details.respond_to?(:foreign_key)
|
|
124
|
-
assoc_details.foreign_key
|
|
125
|
-
else # Rails < v3.1
|
|
126
|
-
assoc_details.primary_key_name
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
# all instances for this association type
|
|
130
|
-
assoc_records.each do |attrs|
|
|
131
|
-
next if attrs.blank?
|
|
132
|
-
if attrs.class != Fixnum && !attrs[:id].blank?
|
|
133
|
-
attrs = attrs[:id].to_i
|
|
134
|
-
end
|
|
135
|
-
try_moderatable_updating(rec) do
|
|
136
|
-
arec = nil
|
|
137
|
-
# PARAM = ID
|
|
138
|
-
if attrs.class == Fixnum
|
|
139
|
-
arec = m.find_by_id(attrs)
|
|
140
|
-
add_assoc_to_record(arec, rec, assoc_name)
|
|
141
|
-
# PARAM = Hash (create)
|
|
142
|
-
else
|
|
143
|
-
arec = m.new
|
|
144
|
-
# set foreign key first, may be required sometimes
|
|
145
|
-
add_assoc_to_record(arec, rec, assoc_name)
|
|
146
|
-
attrs && attrs.each_pair do |key, val|
|
|
147
|
-
next if key.to_s == "associations" || key.to_s == 'id' || key.to_s == fk
|
|
148
|
-
arec.send(key.to_s+"=", val)
|
|
149
|
-
end
|
|
150
|
-
if attrs[:associations]
|
|
151
|
-
update_associations_from_value arec, attrs[:associations]
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
if arec
|
|
155
|
-
try_moderatable_updating(arec) do
|
|
156
|
-
arec.save(:validate => false) # don't run validations
|
|
157
|
-
end
|
|
158
|
-
if assoc_details.collection?
|
|
159
|
-
rec.send(assoc_name.to_s) << arec if arec
|
|
160
|
-
else
|
|
161
|
-
rec.send(assoc_name.to_s + "=", arec) if arec
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
3
|
def accept
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
elsif attr_name == '-'
|
|
177
|
-
loaded_val = YAML::load(attr_value)
|
|
178
|
-
# case: moderated existance (new record)
|
|
179
|
-
if moderatable_id.blank?
|
|
180
|
-
rec = create_from_value
|
|
181
|
-
# save, don't run validations
|
|
182
|
-
rec.moderatable_updating { rec.save(:validate => false) }
|
|
183
|
-
# case: moderated associations (existing record)
|
|
184
|
-
else
|
|
185
|
-
rec = moderatable
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# check for saved associated records
|
|
189
|
-
update_associations_from_value rec
|
|
190
|
-
delete_associations_from_value rec
|
|
191
|
-
|
|
192
|
-
self.destroy # destroy this moderation since it has been applied
|
|
193
|
-
rec
|
|
194
|
-
|
|
195
|
-
# CHANGE ATTRIBUTE
|
|
196
|
-
else
|
|
197
|
-
moderatable.moderatable_updating do
|
|
198
|
-
# bypass attr_accessible protection
|
|
199
|
-
moderatable.send(attr_name.to_s+"=", YAML::load(attr_value))
|
|
200
|
-
moderatable.save(:validate => false) # don't run validations
|
|
201
|
-
end
|
|
202
|
-
self.destroy # destroy this moderation since it has been applied
|
|
203
|
-
end
|
|
4
|
+
loaded_val = YAML::load(data)
|
|
5
|
+
HasModerated::Associations::Base::ApplyModeration::apply(self, loaded_val)
|
|
6
|
+
HasModerated::ModeratedAttributes::ApplyModeration::apply(self, loaded_val)
|
|
7
|
+
HasModerated::ModeratedCreate::ApplyModeration::apply(self, loaded_val)
|
|
8
|
+
HasModerated::ModeratedDestroy::ApplyModeration::apply(self, loaded_val)
|
|
9
|
+
self.destroy
|
|
204
10
|
end
|
|
205
11
|
|
|
206
12
|
def discard
|
|
@@ -2,8 +2,9 @@ module HasModerated
|
|
|
2
2
|
module UserHooks
|
|
3
3
|
module ClassMethods
|
|
4
4
|
def moderation_creating &block
|
|
5
|
-
cattr_accessor :
|
|
6
|
-
self.
|
|
5
|
+
cattr_accessor :moderation_hooks
|
|
6
|
+
self.moderation_hooks ||= { :creating => [] }
|
|
7
|
+
self.moderation_hooks[:creating].push(block)
|
|
7
8
|
end
|
|
8
9
|
end
|
|
9
10
|
end
|
data/lib/has_moderated.rb
CHANGED
|
@@ -1,21 +1,29 @@
|
|
|
1
|
-
require 'has_moderated/moderation_model'
|
|
2
|
-
require 'has_moderated/carrier_wave'
|
|
3
1
|
require 'has_moderated/common'
|
|
4
2
|
require 'has_moderated/user_hooks'
|
|
3
|
+
require 'has_moderated/moderation_model'
|
|
4
|
+
|
|
5
|
+
require 'has_moderated/adapters/proxy'
|
|
6
|
+
require 'has_moderated/adapters/active_record'
|
|
7
|
+
require 'has_moderated/associations/base'
|
|
8
|
+
require 'has_moderated/associations/has_one'
|
|
9
|
+
require 'has_moderated/associations/collection'
|
|
10
|
+
require 'has_moderated/associations/has_many'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
require 'has_moderated/moderated_attributes'
|
|
5
14
|
require 'has_moderated/moderated_create'
|
|
6
15
|
require 'has_moderated/moderated_destroy'
|
|
7
|
-
require 'has_moderated/moderated_attributes'
|
|
8
|
-
require 'has_moderated/moderated_associations'
|
|
9
16
|
|
|
10
17
|
module HasModerated
|
|
11
18
|
def self.included(base)
|
|
12
|
-
#base.send :extend, HasModerated::Common
|
|
13
19
|
HasModerated::Common::included(base)
|
|
14
20
|
base.send :extend, HasModerated::UserHooks::ClassMethods
|
|
21
|
+
|
|
22
|
+
# TODO: only include class methods that can be called, lazy load everything else
|
|
23
|
+
base.send :extend, HasModerated::Associations::Base::ClassMethods
|
|
24
|
+
base.send :extend, HasModerated::ModeratedAttributes::ClassMethods
|
|
15
25
|
base.send :extend, HasModerated::ModeratedCreate::ClassMethods
|
|
16
26
|
base.send :extend, HasModerated::ModeratedDestroy::ClassMethods
|
|
17
|
-
base.send :extend, HasModerated::ModeratedAssociations::ClassMethods
|
|
18
|
-
base.send :extend, HasModerated::ModeratedAttributes::ClassMethods
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
|
|
File without changes
|
|
@@ -1,16 +1,3 @@
|
|
|
1
1
|
class Task < ActiveRecord::Base
|
|
2
2
|
attr_accessible :title
|
|
3
|
-
has_many :subtasks
|
|
4
|
-
has_many :task_photos
|
|
5
|
-
has_and_belongs_to_many :hjoin_tests
|
|
6
|
-
has_and_belongs_to_many :habtms, :class_name => "HabtmNameTest"
|
|
7
|
-
has_one :hone_test
|
|
8
|
-
has_one :hone_as_test, :as => :testable
|
|
9
|
-
has_many :hmanythrough_join
|
|
10
|
-
has_many :hmanythrough_test, :through => :hmanythrough_join
|
|
11
|
-
has_many :lalas, :class_name => "HmanyFkTest", :foreign_key => "something_id"
|
|
12
|
-
has_moderated :title, :desc
|
|
13
|
-
has_moderated_create :with_associations => [:subtasks, :task_photos, :hjoin_tests, :hone_test, :hmanythrough_test, :hmanythrough_join, :hone_as_test, :lalas]
|
|
14
|
-
has_moderated_association :all
|
|
15
|
-
has_moderated_destroy
|
|
16
3
|
end
|