Class: Spider::Model::UnitOfWork

Inherits:
Object
  • Object
show all
Includes:
TSort
Defined in:
lib/spiderfw/model/unit_of_work.rb

Instance Method Summary collapse

Constructor Details

#initialize(&proc) ⇒ UnitOfWork

Returns a new instance of UnitOfWork.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/spiderfw/model/unit_of_work.rb', line 8

def initialize(&proc)
    @objects = {}
    @actions = {}
    @to_delete = {}
    @new_objects = []
    if (proc)
        prev_uow = Spider.current[:unit_of_work]
        start
        yield self
        stop
        Spider.current[:unit_of_work] = prev_uow
    end
end

Instance Method Details

#add(obj, action = :save, params = {}) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/spiderfw/model/unit_of_work.rb', line 119

def add(obj, action = :save, params = {})
    raise "Objects can't be added to the UnitOfWork while it is running" if @running
    if [:insert, :update].include?(action)
        params[:force] = action
        action = :save
    end
    if obj.class == QuerySet
        obj.each do |item|
            add(item, action, params)
        end
        return
    end
    curr = @actions[obj.object_id]
    if curr && (curr_act = curr.select{ |c| c[0] == action }).length > 0
        curr_act.each{ |c| c[1].merge!(params)}
        return
    end
    if action == :delete # FIXME: abstract
        @actions[obj.object_id] = []
    end
    @actions[obj.object_id] ||= []
    @actions[obj.object_id] << [action, params]
    @objects[obj.object_id] = obj
    @new_objects << obj unless curr
    if action == :save
        children = obj.mapper.children_for_unit_of_work(obj, action)
        prms = params.clone
        prms.delete(:force)
        children.each do |child|
            add(child, action, prms)
        end
    end
end

#find_dependencies(model_task) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/spiderfw/model/unit_of_work.rb', line 93

def find_dependencies(model_task)
    return if (@processed_tasks[model_task])
    @processed_tasks[model_task] = true
    dependencies = model_task.object.mapper.get_dependencies(model_task)
    dependencies.each do |dep|
        had0 = @tasks[dep[0]]
        @tasks[dep[0]] = dep[0] unless had0
        had1 = @tasks[dep[1]]
        @tasks[dep[1]] = dep[1] unless had1
        @tasks[dep[0]] << @tasks[dep[1]]
        find_dependencies(dep[0]) unless had0
        find_dependencies(dep[1]) unless had1
    end
end

#has?(obj) ⇒ Boolean

Returns:

  • (Boolean)


108
109
110
111
112
113
114
115
116
# File 'lib/spiderfw/model/unit_of_work.rb', line 108

def has?(obj)
    if obj.class == QuerySet
        obj.each do |item|
            return false unless has?(item)
        end
        return true
    end
    @actions[obj.object_id] && !@actions[obj.object_id].empty?
end

#new_objectsObject



158
159
160
161
162
# File 'lib/spiderfw/model/unit_of_work.rb', line 158

def new_objects
    objects = @new_objects.clone
    @new_objects = []
    objects.length > 0 ? objects : nil
end

#runObject Also known as: commit

(&proc)



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/spiderfw/model/unit_of_work.rb', line 30

def run #(&proc)
    #proc.call
    prev_uow = Spider.current[:unit_of_work]
    Spider.current[:unit_of_work] = self
    @tasks = {}
    @processed_tasks = {}
    while objs = new_objects
        objs.each do |obj|
            @actions[obj.object_id].each do |action, params|
                if action == :save
                    next unless obj.mapper && obj.mapper.class.write?
                    next unless obj.modified?
                    obj.save_mode do
                        obj.before_save
                    end
                elsif action == :delete
                    obj.before_delete
                end
            end
        end
    end
    @running = true
    @objects.each do |obj_id, obj|
        @actions[obj_id].each do |action, params|
            task = Spider::Model::MapperTask.new(obj, action, params)
            @tasks[task] = task
        end
    end
    @tasks.clone.each do |k, task|
        find_dependencies(task)
    end
    tasks = tsort()
    
    if Spider.logger.debug?
        Spider.logger.debug("Tasks:")
        tasks.each do |task| 
            debug_str = "-- #{task.action} on #{task.object.class} #{task.object.primary_keys}"
            debug_str += " #{task.params.inspect}" unless task.params.blank?
            Spider.logger.debug debug_str
        end
    end
                
    tasks.each do |task|
        obj = task.object
        if task.action == :save
            next unless obj.mapper && obj.mapper.class.write?
            next if task.params[:force] != :insert && !obj.modified? && obj.primary_keys_set?
        end
        #Spider::Logger.debug("Executing task #{task.inspect}")
        task.execute()
    end
    @objects = {}
    @new_objects = []
    @running = false
    Spider.current[:unit_of_work] = prev_uow
end

#running?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/spiderfw/model/unit_of_work.rb', line 87

def running?
    @running
end

#startObject



22
23
24
# File 'lib/spiderfw/model/unit_of_work.rb', line 22

def start
    Spider.current[:unit_of_work] = self
end

#stopObject



26
27
28
# File 'lib/spiderfw/model/unit_of_work.rb', line 26

def stop
    Spider.current[:unit_of_work] = nil
end

#to_delete(obj) ⇒ Object



154
155
156
# File 'lib/spiderfw/model/unit_of_work.rb', line 154

def to_delete(obj)
    
end

#tsort_each_child(node, &block) ⇒ Object



169
170
171
# File 'lib/spiderfw/model/unit_of_work.rb', line 169

def tsort_each_child(node, &block)
    node.dependencies.each(&block)
end

#tsort_each_node(&block) ⇒ Object



165
166
167
# File 'lib/spiderfw/model/unit_of_work.rb', line 165

def tsort_each_node(&block)
    @tasks.values.each(&block)
end