OSDN Git Service

temp
[pettanr/pettanr.git] / app / models / story_sheet.rb
1 class StorySheet < Pettanr::Content
2   belongs_to :author
3   belongs_to :story
4   belongs_to :sheet
5   
6   validates :story_id, :presence => true, :numericality => true, :existence => {:both => false}
7   validates :sheet_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
9   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
10   
11   def owner_model
12     self.story
13   end
14   
15   def supply_default
16     self.story_id = nil
17     self.sheet_id = nil
18     self.t = nil
19   end
20   
21   def overwrite au
22     return false unless au
23     self.author_id = au.id
24   end
25   
26   def visible? operators
27     return false unless super
28     self.owner_model.visible? operators
29   end
30   
31   def self.list_where
32     'stories.visible > 0'
33   end
34   
35   def self.list_order
36     'story_sheets.updated_at desc'
37   end
38   
39   def self.play_sheet_where sid
40     ['story_sheets.story_id = ?', sid]
41   end
42   
43   def self.play_sheet story, au, page = 1
44     ss = StorySheet.where(self.play_sheet_where(story.id)).includes(StorySheet.list_opt).order('story_sheets.t').offset(page -1).limit(1).first
45     if ss 
46       if ss.sheet
47         Sheet.show(ss.sheet.id, au)
48       else
49         nil
50       end
51     else
52       nil
53     end
54   end
55   
56   def self.play_paginate story, page
57     Kaminari.paginate_array(Array.new(StorySheet.where(self.play_sheet_where(story.id)).includes(StorySheet.list_opt).count, nil)).page(page).per(1)
58   end
59   
60   def self.list_opt
61     {
62       :author => {}, 
63       :story => {
64       }, 
65       :sheet => {
66         :author => {},
67       }
68     }
69   end
70   
71   def self.list_json_opt
72     {:include => {
73       :author => {}, 
74       :story => {} ,
75       :sheet => {:include => {:author => {}}} 
76     }}
77   end
78   
79   def self.show_opt
80     {:include => {
81       :author => {}, 
82       :story => {}, 
83       :sheet => {
84         :author => {} 
85       }
86     }}
87   end
88   
89   def self.show_json_opt
90     {:include => {
91       :author => {}, 
92       :story => {} ,
93       :sheet => {:include => {:author => {}}} 
94     }}
95   end
96   
97   def elements
98     self.panel.elements
99   end
100   
101   def story_sheet_as_json au
102     panel_include = if self.panel and self.panel.visible?(au)
103       {:include => {:author => {}}, :methods => :elements}
104     else
105       {:include => {:author => {}}}
106     end
107     self.to_json({:include => {:scroll => {:include => {:author => {}}}, :author => {}, :panel => panel_include}})
108   end
109   
110   def self.list_as_json_text ary, au
111     '[' + ary.map {|i| i.story_sheet_as_json(au) }.join(',') + ']'
112   end
113   
114   def self.new_t story_id
115     r = StorySheet.max_t(story_id)
116     r.blank? ? 0 : r.to_i + 1
117   end
118   
119   def self.top_sheet story, author
120     StorySheet.play_list(story, author).first
121   end
122   
123   def self.max_t story_id
124     StorySheet.maximum(:t, :conditions => ['story_id = ?', story_id])
125   end
126   
127   def self.find_t story_id, t
128     StorySheet.find(:first, :conditions => ['story_id = ? and t = ?', story_id, t])
129   end
130   
131   def self.collect_t story_sheet
132     r = StorySheet.find(:all, :conditions => ['story_id = ?', story_sheet.story_id], :order => 't')
133     r.map {|sp| sp.t}
134   end
135   
136   def self.serial? ary
137     i = 0
138     ary.compact.sort.each do |t|
139       break false unless t == i
140       i += 1
141     end
142     ary.compact.size == i
143   end
144   
145   def self.validate_t story_sheet
146     StorySheet.serial?(StorySheet.collect_t(story_sheet))
147   end
148   
149   def insert_shift
150     StorySheet.update_all('t = t + 1', ['story_id = ? and t >= ?', self.story_id, self.t])
151   end
152   
153   def lesser_shift old_t
154     self.t = 0 if self.t < 0
155     StorySheet.update_all('t = t + 1', ['story_id = ? and (t >= ? and t < ?)', self.story_id, self.t, old_t])
156   end
157   
158   def higher_shift old_t
159     nf = StorySheet.find_t(self.story_id, self.t)
160     max_t = StorySheet.max_t(self.story_id).to_i
161     self.t = max_t if self.t > max_t
162     StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ? and t <= ?)', self.story_id, old_t, self.t])
163   end
164   
165   def update_shift old_t
166     if self.t > old_t
167       higher_shift old_t
168     else
169       lesser_shift old_t
170     end
171   end
172   
173   def rotate old_t = nil
174     if self.new_record?
175       if self.t.blank?
176         self.t = StorySheet.new_t self.story_id
177       else
178         self.insert_shift
179       end
180     else
181       if self.t.blank?
182       else
183         self.update_shift old_t
184       end
185     end
186   end
187   
188   def allow?
189     return nil if self.story_id == nil or self.sheet_id == nil
190     self.story.own?(self.author) and self.sheet.usable?(self.author)
191   end
192   
193   def store old_t = nil
194     res = false
195     StorySheet.transaction do
196       case self.allow?
197       when true
198         self.rotate old_t
199       when false
200         raise ActiveRecord::Forbidden
201       else
202       end
203       res = self.save
204       raise ActiveRecord::Rollback unless res
205       res = StorySheet.validate_t(self) 
206       unless res
207         self.errors.add :t, 'unserialized'
208         raise ActiveRecord::Rollback 
209       end
210     end
211     res
212   end
213   
214   def destroy_and_shorten
215     res = false
216     StorySheet.transaction do
217       StorySheet.update_all('t = t - 1', ['story_id = ? and (t > ?)', self.story_id, self.t])
218       raise ActiveRecord::Rollback unless self.destroy
219       res = true
220     end
221     res
222   end
223   
224 end