OSDN Git Service

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