has_moderated 1.0.rc6 → 1.0.rc7

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Add it to your project's Gemfile
7
7
 
8
- gem "has_moderated", ">=1.0.rc6"
8
+ gem "has_moderated", ">=1.0.rc7"
9
9
 
10
10
  and run
11
11
 
@@ -125,7 +125,19 @@ It also supports dirty tracking through ActiveModel, so you can use all its func
125
125
  preview.some_attr_change # => ["old value", "new value"]
126
126
  preview.some_association.first # => #<HasModerated::FakeTask @fake_of_model=Task, @attributes={"id"=>1, "title"=>"Task 1", "desc"=>nil, "created_at"=>"2012-06-08 15:49:56.726646", "updated_at"=>"2012-06-08 15:49:56.726646"}, @changed_attributes={}, reflections.keys => [:assoc1, :assoc2]>
127
127
 
128
- This preview is cached from applying the moderation in a transaction and then rolling it back (so it does not *really* affect the database).
128
+ This preview is cached from applying the moderation in a transaction and then rolling it back (so it does not affect the database).
129
+
130
+ === Using the fake object to modify the moderation
131
+
132
+ The fake object described above has a nifty feature (1.0.rc7+) that allows you to update attributes in the moderation by manipulating the fake object. Right now it can only handle attributes and not associations, but that might change in the future. See example below on how to use this feature.
133
+
134
+ moderation.parsed_data # => {:attributes=>{"title"=>"Task 1"}}
135
+ preview = moderation.preview(:saveable => true)
136
+ preview.title = "Task 2"
137
+ preview.update_moderation
138
+ moderation.parsed_data # => {:attributes=>{"title"=>"Task 2"}}
139
+ moderation.apply
140
+ Task.first.title # => "Task 2"
129
141
 
130
142
  === Get a real ActiveRecord preview
131
143
 
@@ -139,6 +151,25 @@ This way, you will get a real ActiveRecord object that is really in the database
139
151
  preview.some_association.first # => ActiveRecord object
140
152
  end
141
153
 
154
+ Note that since a transaction is used in both cases, all the changes made to the database to produce the preview are only in effect inside the transaction, so the changes are only visible inside the transaction. For example, if a second database query comes from another Rails instance, it will not see the changes that are in effect in the transaction, even if the transaction is still in process.
155
+
156
+ === Example of using preview in your show action
157
+
158
+ In this example I allow admin users to add a preview parameter to the URL to see the preview of how the record will look after applying a moderation, without having to change code in the views.
159
+
160
+ def show
161
+ @doctor = Doctor.find_by_slug(params[:id])
162
+
163
+ if current_admin_user && params[:preview]
164
+ @doctor.moderations.find_by_id(params[:preview]).live_preview do |preview|
165
+ @doctor = preview
166
+ render :action => "show"
167
+ end
168
+ else
169
+ render :action => "show"
170
+ end
171
+ end
172
+
142
173
  == Which kind of moderation is it?
143
174
 
144
175
  You can call the following convenience methods to determine the type of moderation
@@ -44,18 +44,24 @@ module HasModerated
44
44
  end
45
45
 
46
46
  def live_preview
47
- ActiveRecord::Base.transaction do
47
+ self.transaction do
48
48
  record = accept
49
49
  yield(record)
50
50
  raise ActiveRecord::Rollback
51
51
  end
52
+ # self.frozen? now became true
53
+ # since we don't actually commit to database, we don't need the freeze
54
+ # only way I found to unfreeze is to dup attributes
55
+ @attributes = @attributes.dup
56
+
52
57
  nil
53
58
  end
54
59
 
55
- def preview
60
+ def preview(options = {})
61
+ options[:saveable] ||= false
56
62
  fake_record = nil
57
63
  live_preview do |record|
58
- fake_record = HasModerated::Preview::from_live(record)
64
+ fake_record = HasModerated::Preview::from_live(record, self, options[:saveable])
59
65
  end
60
66
  fake_record
61
67
  end
@@ -1,6 +1,25 @@
1
1
  require 'ostruct'
2
2
  module HasModerated
3
3
  module Preview
4
+ module Saveable
5
+ def update_moderation
6
+ if @based_on_moderation.present?
7
+ data = @based_on_moderation.parsed_data
8
+
9
+ # attributes
10
+ data[:attributes] ||= Hash.new
11
+ @attributes.each_pair do |key, value|
12
+ if value != @attributes_initial[key]
13
+ data[:attributes][key.to_s] = value
14
+ end
15
+ end
16
+
17
+ @based_on_moderation.data = data
18
+ @based_on_moderation.save
19
+ end
20
+ end
21
+ end
22
+
4
23
  class FakeRecord
5
24
  extend ActiveModel::Naming
6
25
  include ActiveModel::Conversion
@@ -8,8 +27,9 @@ module HasModerated
8
27
 
9
28
  attr_accessor :attributes
10
29
 
11
- def initialize(fake_of_model)
12
- @fake_of_model = fake_of_model
30
+ def initialize(based_on_model, based_on_moderation)
31
+ @based_on_model = based_on_model
32
+ @based_on_moderation = based_on_moderation
13
33
  end
14
34
 
15
35
  def persisted?
@@ -25,7 +45,7 @@ module HasModerated
25
45
  end
26
46
 
27
47
  def to_s
28
- "#<HasModerated::Fake#{@fake_of_model.to_s}>"
48
+ "#<HasModerated::Fake#{@based_on_model.to_s}>"
29
49
  end
30
50
 
31
51
  def inspect
@@ -47,15 +67,16 @@ module HasModerated
47
67
  if cache[record.class][record.id].present?
48
68
  cache[record.class][record.id]
49
69
  else
50
- cache[record.class][record.id] = from_live(record, cache)
70
+ cache[record.class][record.id] = from_live(record, nil, false, cache)
51
71
  end
52
72
  end
53
73
 
54
- def self.from_live(record, object_cache = nil)
74
+ def self.from_live(record, moderation = nil, saveable = false, object_cache = nil)
55
75
  return nil if record.blank?
56
- obj = FakeRecord.new(record.class)
76
+ obj = FakeRecord.new(record.class, moderation)
57
77
  eigenclass = (class << obj ; self ; end)
58
78
 
79
+ # attributes
59
80
  obj.instance_variable_set(:@attributes, record.instance_variable_get(:@attributes))
60
81
  changed_attributes = Hash.new
61
82
  record.previous_changes.each_pair do |attr_name, values|
@@ -63,6 +84,17 @@ module HasModerated
63
84
  end
64
85
  obj.instance_variable_set(:@changed_attributes, changed_attributes)
65
86
 
87
+ # saveable
88
+ if saveable
89
+ obj.instance_variable_set(:@attributes_initial, record.instance_variable_get(:@attributes).dup)
90
+ eigenclass.send(:include, Saveable)
91
+ obj.attributes.keys.each do |attr_name|
92
+ eigenclass.send(:define_method, "#{attr_name}=") do |value|
93
+ self.attributes[attr_name.to_s] = value
94
+ end
95
+ end
96
+ end
97
+
66
98
  # associations
67
99
  object_cache ||= Hash.new
68
100
  object_cache[record.class] ||= Hash.new
@@ -1,3 +1,3 @@
1
1
  module HasModerated
2
- VERSION = "1.0.rc6"
2
+ VERSION = "1.0.rc7"
3
3
  end