OSDN Git Service

t30350#:fix destroy
[pettanr/pettanr.git] / app / models / story.rb
1 #ストーリー
2 class Story < ActiveRecord::Base
3   belongs_to :author
4   belongs_to :panel
5   belongs_to :comic
6   
7   validates :comic_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.comic_id = nil
14     self.panel_id = nil
15     self.t = nil
16   end
17   
18   def overwrite au
19     return false unless au
20     self.author_id = au.id
21   end
22   
23   def own? au
24     return false unless au.is_a?(Author)
25     self.author_id == au.id
26   end
27   
28   def visible? au
29     if au == nil
30       return false if MagicNumber['run_mode'] == 1
31     elsif au.is_a?(Author)
32       return true if self.comic.own?(au)
33     else
34       return false
35     end
36     self.comic.visible? au
37   end
38   
39   def self.default_panel_size
40     30
41   end
42   
43   def self.max_panel_size
44     200
45   end
46   
47   def self.offset cnt, prm = nil
48     offset = prm.to_i
49     offset = cnt - 1 if offset >= cnt
50     offset = cnt - offset.abs if offset < 0
51     offset = 0 if offset < 0
52     offset
53   end
54   
55   def self.panel_count cnt, prm = self.default_panel_size
56     count = prm.to_i
57     count = self.max_panel_size if count > self.max_panel_size
58     count = self.default_panel_size if count < 1
59     count
60   end
61   
62   def self.play_list comic, author, offset = 0, limit = Story.default_panel_size
63     opt = {}
64     opt.merge!(Story.list_opt)
65     opt.merge!({:offset => offset, :limit => limit}) if limit > 0
66     opt.merge!({:conditions => ['stories.comic_id = ?', comic.id], :order => 'stories.t'})
67     Story.find(:all, opt)
68   end
69   
70   def self.list_opt
71     {:include => {
72       :author => {}, 
73       :comic => {
74         :author => {}
75       }, 
76       :panel => {
77         :author => {}, 
78         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
79         :speech_balloons =>{:balloons => {}, :speeches => {}}
80       }
81     }}
82   end
83   
84   def self.list_json_opt
85     {:include => {
86       :author => {}, 
87       :comic => {
88         :author => {}
89       }, 
90       :panel => {
91         :author => {}, 
92         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
93         :speech_balloons =>{:balloons => {}, :speeches => {}}
94       }
95     }}
96   end
97   
98   def self.default_page_size
99     25
100   end
101   
102   def self.max_page_size
103     100
104   end
105   
106   def self.page prm = nil
107     page = prm.to_i
108     page = 1 if page < 1
109     page
110   end
111   
112   def self.page_size prm = self.default_page_size
113     page_size = prm.to_i
114     page_size = self.max_page_size if page_size > self.max_page_size
115     page_size = self.default_page_size if page_size < 1
116     page_size
117   end
118   
119   def self.list page = 1, page_size = self.default_page_size
120     opt = {}
121     opt.merge!(self.list_opt)
122     opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0
123     opt.merge!({:conditions => ['comics.visible > 0'], :order => 'stories.updated_at desc'})
124     Story.find(:all, opt)
125   end
126   
127   def self.mylist au, page = 1, page_size = Author.default_story_page_size
128     opt = {}
129     opt.merge!(Story.list_opt)
130     opt.merge!({:limit => page_size, :offset => (page -1) * page_size}) if page_size > 0
131     opt.merge!({:conditions => ['stories.author_id = ?', au.id], :order => 'stories.updated_at desc'})
132     Story.find(:all, opt)
133   end
134   
135   def self.show sid, au
136     opt = {}
137     opt.merge!(Story.show_opt)
138     res = Story.find sid, opt
139     raise ActiveRecord::Forbidden unless res.visible?(au)
140     res
141   end
142   
143   def self.edit sid, au
144     opt = {}
145     opt.merge!(Story.show_opt)
146     res = Story.find sid, opt
147     raise ActiveRecord::Forbidden unless res.own?(au)
148     res
149   end
150   
151   def self.show_opt
152     {:include => {
153       :author => {}, 
154       :comic => {
155         :author => {}
156       }, 
157       :panel => {
158         :author => {}, 
159         :panel_pictures => {:picture => {:artist => {}, :license => {}}}, 
160         :speech_balloons =>{:balloons => {}, :speeches => {}}
161       }
162     }}
163   end
164   
165   def elements
166     self.panel.elements
167   end
168   
169   def story_as_json au
170     panel_include = if self.panel and self.panel.visible?(au)
171       {:include => {:author => {}}, :methods => :elements}
172     else
173       {:include => {:author => {}}}
174     end
175     self.to_json({:include => {:comic => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
176   end
177   
178   def self.list_as_json_text ary, au
179     '[' + ary.map {|i| i.story_as_json(au) }.join(',') + ']'
180   end
181   
182   def self.licensed_pictures stories
183     r = {}
184     stories.each do |story|
185       r.merge!(story.panel.licensed_pictures) if story.panel
186     end
187     r
188   end
189   
190   def self.new_t comic_id
191     r = Story.max_t(comic_id)
192     r.blank? ? 0 : r.to_i + 1
193   end
194   
195   def self.max_t comic_id
196     Story.maximum(:t, :conditions => ['comic_id = ?', comic_id])
197   end
198   
199   def self.find_t comic_id, t
200     Story.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t])
201   end
202   
203   def self.collect_t story
204     r = Story.find(:all, :conditions => ['comic_id = ?', story.comic_id], :order => 't')
205     r.map {|s| s.t}
206   end
207   
208   def self.serial? ary
209     i = 0
210     ary.compact.sort.each do |t|
211       break false unless t == i
212       i += 1
213     end
214     ary.compact.size == i
215   end
216   
217   def self.validate_t story
218     Story.serial?(Story.collect_t(story))
219   end
220   
221   def insert_shift
222     Story.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t])
223   end
224   
225   def lesser_shift old_t
226     self.t = 0 if self.t < 0
227     Story.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, self.t, old_t])
228   end
229   
230   def higher_shift old_t
231     nf = Story.find_t(self.comic_id, self.t)
232     max_t = Story.max_t(self.comic_id).to_i
233     self.t = max_t if self.t > max_t
234     Story.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, old_t, self.t])
235   end
236   
237   def update_shift old_t
238     if self.t > old_t
239       higher_shift old_t
240     else
241       lesser_shift old_t
242     end
243   end
244   
245   def rotate old_t = nil
246     if self.new_record?
247       if self.t.blank?
248         self.t = Story.new_t self.comic_id
249       else
250         self.insert_shift
251       end
252     else
253       if self.t.blank?
254       else
255         self.update_shift old_t
256       end
257     end
258   end
259   
260   def allow?
261     c = self.comic
262     pl = self.panel
263     c and c.own?(self.author) and pl and pl.usable?(self.author)
264   end
265   
266   def store old_t = nil
267     res = false
268     raise ActiveRecord::Forbidden unless self.allow?
269     Story.transaction do
270       self.rotate old_t
271       res = self.save
272       raise ActiveRecord::Rollback unless res
273       res = Story.validate_t(self) 
274       unless res
275         self.errors.add :t, 'unserialized'
276         raise ActiveRecord::Rollback 
277       end
278     end
279     res
280   end
281   
282   def destroy_and_shorten
283     res = false
284     Story.transaction do
285       Story.update_all('t = t - 1', ['comic_id = ? and (t > ?)', self.comic_id, self.t])
286       raise ActiveRecord::Rollback unless self.destroy
287       res = true
288     end
289     res
290   end
291   
292   
293 end