OSDN Git Service

fix foreign_filter list includes
[pettanr/pettanr.git] / app / models / scroll_panel.rb
1 class ScrollPanel < Peta::Leaf
2   load_manifest
3   belongs_to :author
4   belongs_to :panel
5   belongs_to :scroll
6   
7   validates :scroll_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :panel_id, :presence => true, :numericality => true, :existence => {:both => false}
9   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
10   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
11   
12   def supply_default
13     self.scroll_id = nil
14     self.panel_id = nil
15     self.t = nil
16   end
17   
18   def overwrite operators
19     return false unless operators.author
20     self.author_id = operators.author.id
21   end
22   
23   def visible? operators
24     return false unless super
25     self.owner_model.visible? operators
26   end
27   
28   def self.list_order
29     'scroll_panels.updated_at desc'
30   end
31   
32   def self.list_where
33     'scrolls.visible > 0'
34   end
35   
36   def self.by_author_list_includes
37     {
38       :scroll => {
39         :author => {}
40       }
41     }
42   end
43   
44   def self.play_list_where cid
45     ['scroll_panels.scroll_id = ?', cid]
46   end
47   
48   def self.play_list scroll, author, offset = 0, limit = ScrollPanel.default_panel_size
49     ScrollPanel.where(self.play_list_where(scroll.id)).includes(ScrollPanel.list_opt).order('scroll_panels.t').offset(offset).limit(limit)
50   end
51   
52   def self.list_opt
53     {
54       :author => {}, 
55       :scroll => {
56         :author => {}
57       }, 
58       :panel => {
59         :author => {}, 
60         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
61         :speech_balloons =>{:balloon => {}, :speech => {}}
62       }
63     }
64   end
65   
66   def self.list_json_opt
67     {:include => {
68       :author => {}, 
69       :scroll => {
70         :author => {}
71       }, 
72       :panel => {
73         :author => {}, 
74         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
75         :speech_balloons =>{:balloon => {}, :speech => {}}
76       }
77     }}
78   end
79   
80   def self.show_opt
81     {:include => {
82       :author => {}, 
83       :scroll => {
84         :author => {}
85       }, 
86       :panel => {
87         :author => {}, 
88         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
89         :speech_balloons =>{:balloon => {}, :speech => {}}
90       }
91     }}
92   end
93   
94   def elements
95     self.panel.elements
96   end
97   
98   def scroll_panel_as_json au
99     panel_include = if self.panel and self.panel.visible?(au)
100       {:include => {:author => {}}, :methods => :elements}
101     else
102       {:include => {:author => {}}}
103     end
104     self.to_json({:include => {:scroll => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
105   end
106   
107   def self.list_as_json_text ary, au
108     '[' + ary.map {|i| i.scroll_panel_as_json(au) }.join(',') + ']'
109   end
110   
111   def self.licensed_pictures scroll_panels
112     r = {}
113     scroll_panels.each do |scroll_panel|
114       r.merge!(scroll_panel.panel.licensed_pictures) if scroll_panel.panel
115     end
116     r
117   end
118   
119   def self.new_t scroll_id
120     r = ScrollPanel.max_t(scroll_id)
121     r.blank? ? 0 : r.to_i + 1
122   end
123   
124   def self.max_t scroll_id
125     ScrollPanel.maximum(:t, :conditions => ['scroll_id = ?', scroll_id])
126   end
127   
128   def self.find_t scroll_id, t
129     ScrollPanel.find(:first, :conditions => ['scroll_id = ? and t = ?', scroll_id, t])
130   end
131   
132   def self.collect_t scroll_panel
133     r = ScrollPanel.find(:all, :conditions => ['scroll_id = ?', scroll_panel.scroll_id], :order => 't')
134     r.map {|sp| sp.t}
135   end
136   
137   def self.serial? ary
138     i = 0
139     ary.compact.sort.each do |t|
140       break false unless t == i
141       i += 1
142     end
143     ary.compact.size == i
144   end
145   
146   def self.validate_t scroll_panel
147     ScrollPanel.serial?(ScrollPanel.collect_t(scroll_panel))
148   end
149   
150   def insert_shift
151     ScrollPanel.update_all('t = t + 1', ['scroll_id = ? and t >= ?', self.scroll_id, self.t])
152   end
153   
154   def lesser_shift old_t
155     self.t = 0 if self.t < 0
156     ScrollPanel.update_all('t = t + 1', ['scroll_id = ? and (t >= ? and t < ?)', self.scroll_id, self.t, old_t])
157   end
158   
159   def higher_shift old_t
160     nf = ScrollPanel.find_t(self.scroll_id, self.t)
161     max_t = ScrollPanel.max_t(self.scroll_id).to_i
162     self.t = max_t if self.t > max_t
163     ScrollPanel.update_all('t = t - 1', ['scroll_id = ? and (t > ? and t <= ?)', self.scroll_id, old_t, self.t])
164   end
165   
166   def update_shift old_t
167     if self.t > old_t
168       higher_shift old_t
169     else
170       lesser_shift old_t
171     end
172   end
173   
174   def rotate old_t = nil
175     if self.new_record?
176       if self.t.blank?
177         self.t = ScrollPanel.new_t self.scroll_id
178       else
179         self.insert_shift
180       end
181     else
182       if self.t.blank?
183       else
184         self.update_shift old_t
185       end
186     end
187   end
188   
189   def allow? operators
190     return nil if self.scroll_id == nil or self.panel_id == nil
191     self.scroll.own?(operators) and self.panel.usable?(operators)
192   end
193   
194   def store operators, old_t = nil
195     res = false
196     ScrollPanel.transaction do
197       case self.allow? operators
198       when true
199         self.rotate old_t
200       when false
201         raise ActiveRecord::Forbidden
202       else
203       end
204       res = self.save
205       raise ActiveRecord::Rollback unless res
206       res = ScrollPanel.validate_t(self) 
207       unless res
208         self.errors.add :t, 'unserialized'
209         raise ActiveRecord::Rollback 
210       end
211     end
212     res
213   end
214   
215   def destroy_and_shorten
216     res = false
217     ScrollPanel.transaction do
218       ScrollPanel.update_all('t = t - 1', ['scroll_id = ? and (t > ?)', self.scroll_id, self.t])
219       raise ActiveRecord::Rollback unless self.destroy
220       res = true
221     end
222     res
223   end
224   
225 end