OSDN Git Service

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