OSDN Git Service

pass test
[pettanr/pettanr.git] / app / models / panel.rb
1 #コマ
2 class Panel < ActiveRecord::Base
3   belongs_to :comic
4   belongs_to :author
5   belongs_to :resource_picture
6 #  belongs_to :background_picture, :class_name => 'ResourcePicture'
7   has_many :panel_pictures, :dependent => :destroy
8   has_many :speech_balloons, :dependent => :destroy
9   accepts_nested_attributes_for :panel_pictures, :allow_destroy => true
10   accepts_nested_attributes_for :speech_balloons, :allow_destroy => true
11
12 #  validates :comic_id, :presence => true, :numericality => true, :existence => true, :uniqueness => {:scope => :t} 
13   validates :width, :presence => true, :numericality => true, :natural_number => true
14   validates :height, :presence => true, :numericality => true, :natural_number => true
15   validates :border, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
16   validates :x, :numericality => {:allow_blank => true}
17   validates :y, :numericality => {:allow_blank => true}
18   validates :z, :numericality => {:allow_blank => true, :greater_than => 0}
19   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
20   validates :author_id, :presence => true, :numericality => true, :existence => true
21   
22   def supply_default au
23     return false unless au
24     c = self.comic_id ? Comic.show(self.comic_id, au) : nil
25     if c
26       self.width = c.width if self.width.blank?
27       self.height = c.height if self.height.blank?
28       self.t = Panel.new_t(c.id) if self.t.blank? and self.new_record?
29     end
30     self.border = 0 if self.border.blank?
31     self.author_id = au.id
32   end
33   
34   def self.new_t comic_id
35     r = Panel.max_t(comic_id)
36     r.blank? ? 0 : r.to_i + 1
37   end
38   
39   def self.max_t comic_id
40     Panel.maximum(:t, :conditions => ['comic_id = ?', comic_id])
41   end
42   
43   def self.find_t comic_id, t
44     Panel.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t])
45   end
46
47   def self.collect_element_value elements, name, ex_nil = false
48     e = elements.map {|e|
49       e.map {|o|
50         o[name]
51       }
52     }.flatten
53     e = e.compact if ex_nil
54     e
55   end
56   
57   def self.validate_id ary, pid
58     ary.map {|v|
59       if pid
60         (v == pid or v == nil) ? nil : false
61       else
62         v ? false : nil
63       end
64     }.compact.empty?
65   end
66   
67   def self.validate_element_id elements, name, pid
68     Panel.validate_id(Panel.collect_element_value(elements, name), pid)
69   end
70   
71   def self.validate_elements_id c
72     c.map {|conf|
73       Panel.validate_element_id(conf[:elements], conf[:name], conf[:parent_id]) ? nil : false
74     }.compact.empty?
75   end
76   
77   def self.validate_t ary
78     i = 0
79     ary.compact.sort.each do |t|
80       break false unless t == i
81       i += 1
82     end
83     ary.compact.size == i
84   end
85   
86   def self.validate_element_t elements, name
87     Panel.validate_t(Panel.collect_element_value(elements, name, true))
88   end
89   
90   def self.validate_elements_t c
91     c.map {|conf|
92       Panel.validate_element_t(conf[:elements], conf[:name]) ? nil : false
93     }.compact.empty?
94   end
95   
96   def validate_id_list
97     r = self.speech_balloons.map {|sb|
98       {:elements => [sb.speeches, sb.balloons], :name => :speech_balloon_id, :parent_id => sb.id}
99     }
100     r.unshift({:elements => [self.panel_pictures, self.speech_balloons], :name => :panel_id, :parent_id => self.id})
101     r
102   end
103   
104   def validate_child
105     r1 = Panel.validate_elements_id validate_id_list
106     r2 = Panel.validate_elements_t [
107       {:elements => [self.panel_pictures, self.speech_balloons], :name => :t}
108     ]
109     r1 and r2
110   end
111   
112   def store
113     res = false
114     Panel.transaction do
115       raise ActiveRecord::Rollback unless validate_child
116       f = nil
117       f = Panel.find_t(self.comic_id, self.t) if self.t
118       if f
119         Panel.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t])
120       else
121         self.t = Panel.new_t self.comic_id
122       end
123       res = self.save
124     end
125   end
126   
127   def move_to new_t
128     return true if self.t == new_t
129     if self.t > new_t
130       Panel.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, new_t, self.t])
131     else
132       nf = Panel.find_t(self.comic_id, new_t)
133       max_t = Panel.max_t.to_i self.comic_id
134       new_t = max_t if new_t > max_t
135       Panel.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, self.t, new_t])
136     end
137     self.t = new_t
138     self.save
139   end
140   
141   def destroy_and_shorten
142     Panel.update_all('t = t - 1', ['comic_id = ? and (t > ?)', self.comic_id, self.t])
143     self.destroy
144   end
145   
146   def self.default_page_size
147     25
148   end
149   
150   def self.max_page_size
151     100
152   end
153   
154   def self.page prm = nil
155     page = prm.to_i
156     page = 1 if page < 1
157     page
158   end
159   
160   def self.page_size prm = self.default_page_size
161     page_size = prm.to_i
162     page_size = self.max_page_size if page_size > self.max_page_size
163     page_size = self.default_page_size if page_size < 1
164     page_size
165   end
166   
167   def self.offset cnt, prm = nil
168     offset = prm.to_i
169     offset = cnt - 1 if offset >= cnt
170     offset = cnt - offset.abs if offset < 0
171     offset = 0 if offset < 0
172     offset
173   end
174   
175   def self.list opt = {}, page = 1, page_size = self.default_page_size
176     opt.merge!(self.list_opt) unless opt[:include]
177     opt.merge!({:order => 'updated_at desc', :limit => page_size, :offset => (page -1) * page_size})
178     Panel.find(:all, opt)
179   end
180   
181   def self.list_opt
182     {:include => {
183       :comic => :author, 
184       :panel_pictures => {
185         :resource_picture => {:artist => {}, :license => {}}
186       }, 
187       :speech_balloons => {:balloons => {}, :speeches => {}},
188       :author => {}
189     }}
190   end
191   
192   def self.list_json_opt
193     {:include => {
194       :comic => {:author => {}}, 
195       :panel_pictures => {
196         :resource_picture => {:artist => {}, :license => {}}
197       }, 
198       :speech_balloons => {:balloons => {}, :speeches => {}},
199       :author => {}
200     }}
201   end
202   
203   def self.show rid, au, opt = {}
204     r = Panel.find(rid, :include => self.show_include_opt(opt))
205     raise ActiveRecord::Forbidden unless r.visible?(au)
206     r
207   end
208   
209   def self.show_include_opt opt = {}
210     res = {
211       :comic => :author, 
212       :panel_pictures => {
213         :resource_picture => {:artist => {}, :license => {}}
214       }, 
215       :speech_balloons => {:balloons => {}, :speeches => {}},
216       :author => {}
217     }
218     res.merge!(opt[:include]) if opt[:include]
219     res
220   end
221   
222   def self.show_json_include_opt
223     {:include => {
224       :comic => {:author => {}}, 
225       :panel_pictures => {
226         :resource_picture => {:artist => {}, :license => {}}
227       }, 
228       :speech_balloons => {:balloons => {}, :speeches => {}},
229       :author => {}
230     }}
231   end
232   
233   def visible? au
234     return false unless au
235     return false unless self.comic
236     self.comic.visible?(au) or self.author_id == au.id
237   end
238   
239   def own? author
240     return false unless author
241     self.author_id == author.id
242   end
243   
244   def sort_by_time
245     pe = []
246     self.panel_pictures.each do |picture|
247       pe[picture.t] = picture
248     end
249     self.speech_balloons.each do |sb|
250       pe[sb.t] = sb
251     end
252     pe
253   end
254   
255   def each_element
256     self.sort_by_time.each do |e|
257       yield e
258     end
259   end
260   
261   def panel_elements
262     res = []
263     self.each_element do |elm|
264       if elm.kind_of?(PanelPicture)
265         res[elm.t] = elm.to_json({:include => :resource_picture})
266       end
267       if elm.kind_of?(SpeechBalloon)
268         res[elm.t] = elm.to_json({:include => {:balloons => {}, :speeches => {}}})
269       end
270     end
271     res
272   end
273   
274   def to_json_play
275     self.to_json :methods => :panel_elements
276   end
277   
278   def self.visible_count
279     Panel.count
280   end
281   
282 end