OSDN Git Service

a736a719aeb4002678bf67697f214e74b5b1f83c
[pettanr/pettanr.git] / lib / peta / leaf.rb
1 module Peta
2   class Leaf < Content
3     self.abstract_class = true
4     
5     # Dynamic ClassMethods
6     
7     def self.load_manifest
8       super
9       return nil if self._skip_load?
10       # Class Methods
11       pm = Manifest.manifest.models[self.my_peta.parent_item_name].classify
12       define_singleton_method("parent_model") do 
13         pm
14       end
15       destm = Manifest.manifest.models[self.my_peta.destination_item_name].classify
16       define_singleton_method("destination_model") do 
17         destm
18       end
19       pfk = self.my_peta.parent_item_name + '_id'
20       define_singleton_method("binder_key") do 
21         pfk
22       end
23       dest_key = if self.my_peta.destination_item_name
24         self.my_peta.destination_item_name + '_id'
25       else
26         nil
27       end
28       define_singleton_method("destination_key") do 
29         dest_key
30       end
31       # Instance Methods
32     end
33     
34     def self.element?
35       true
36     end
37     
38     def self.root_model
39       self.parent_model
40     end
41     
42     def self.binder_model
43       self.parent_model
44     end
45     
46     def self.destination_model
47       self.parent_model
48     end
49     
50     def root
51       self.__send__ self.class.root_model.item_name
52     end
53     
54     def own? operators
55       self.root.own? operators
56     end
57     
58     # super return if my item
59     def visible? operators
60       return false if super == false
61       self.root.visible? operators
62     end
63     
64     def self.play_list_order
65       self.table_name + '.t'
66     end
67     
68     def self.new_t binder_id
69       r = self.max_t(binder_id)
70       r.blank? ? 0 : r.to_i + 1
71     end
72     
73     def self.max_t binder_id
74       self.where([self.binder_key + ' = ?', binder_id]).maximum(:t)
75     end
76     
77     def self.find_t binder_id, t
78       self.where([self.binder_key + ' = ? and t = ?', binder_id, t]).first
79     end
80     
81     def self.collect_t binder_id
82       r = self.where([self.binder_key + ' = ?', binder_id]).order('t')
83       r.map {|sp| sp.t}
84     end
85     
86     def self.serial? ary
87       i = 0
88       ary.compact.sort.each do |t|
89         break false unless t == i
90         i += 1
91       end
92       ary.compact.size == i
93     end
94     
95     def self.validate_t binder_id
96       self.serial?(self.collect_t(binder_id))
97     end
98     
99     def binder_key
100       self.class.binder_key
101     end
102     
103     def destination_key
104       self.class.destination_key
105     end
106     
107     def binder_id
108       self.attributes[self.binder_key]
109     end
110     
111     def destination_id
112       if self.destination_key
113         self.attributes[self.destination_key]
114       else
115         nil
116       end
117     end
118     
119     def insert_shift
120       self.class.update_all('t = t + 1', 
121         [self.binder_key + ' = ? and t >= ?', self.binder_id, self.t]
122       )
123     end
124     
125     def lesser_shift old_t
126       self.t = 0 if self.t < 0
127       self.class.update_all('t = t + 1', 
128         [self.binder_key + ' = ? and (t >= ? and t < ?)', self.binder_id, self.t, old_t]
129       )
130     end
131     
132     def higher_shift old_t
133       nf = self.class.find_t(self.binder_id, self.t)
134       max_t = self.class.max_t(self.binder_id).to_i
135       self.t = max_t if self.t > max_t
136       self.class.update_all('t = t - 1', 
137         [self.binder_key + ' = ? and (t > ? and t <= ?)', self.binder_id, old_t, self.t]
138       )
139     end
140     
141     def update_shift old_t
142       if self.t > old_t
143         higher_shift old_t
144       else
145         lesser_shift old_t
146       end
147     end
148     
149     def rotate old_t = nil
150       if self.new_record?
151         if self.t.blank?
152           self.t = self.class.new_t self.binder_id
153         else
154           self.insert_shift
155         end
156       else
157         if self.t.blank?
158         else
159           self.update_shift old_t
160         end
161       end
162     end
163     
164     def store operators, old_t = nil
165       res = false
166       self.class.transaction do
167         case self.allow? operators
168         when true
169           self.rotate old_t
170         when false
171           raise ActiveRecord::Forbidden
172         else
173         end
174         res = self.save
175         raise ActiveRecord::Rollback unless res
176         res = self.class.validate_t(self.binder_id) 
177         unless res
178           self.errors.add :t, 'unserialized'
179           raise ActiveRecord::Rollback 
180         end
181       end
182       res
183     end
184     
185     # destroy and shorten
186     def destroy
187       res = false
188       self.class.transaction do
189         # renumber t
190         self.class.update_all('t = t - 1', 
191           [self.binder_key + ' = ? and (t > ?)', self.binder_id, self.t]
192         )
193         res = super
194         raise ActiveRecord::Rollback unless res
195       end
196       res
197     end
198     
199   end
200 end
201