OSDN Git Service

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