OSDN Git Service

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