OSDN Git Service

add comic story
[pettanr/pettanr.git] / app / models / comic_story.rb
1 class ComicStory < Peta::Leaf
2   load_manifest
3   belongs_to :author
4   belongs_to :comic
5   belongs_to :story
6   
7   validates :comic_id, :presence => true, :numericality => true, :existence => {:both => false}
8   validates :story_id, :presence => true, :numericality => true, :existence => {:both => false}
9   validates :author_id, :presence => true, :numericality => true, :existence => {:both => false}
10   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
11   
12   def supply_default
13     self.comic_id = nil
14     self.story_id = nil
15     self.t = nil
16   end
17   
18   def overwrite operators
19     return false unless operators.author
20     self.author_id = operators.author.id
21   end
22   
23   def self.public_list_order
24     'comic_stories.updated_at desc'
25   end
26   
27   def self.list_where
28     'comics.visible > 0'
29   end
30   
31   def self.by_author_list_includes
32     {
33       :comic => {
34         :author => {}
35       }
36     }
37   end
38   
39   def self.play_list_where cid
40     ['comic_stories.comic_id = ?', cid]
41   end
42   
43   def self.play_list scroll, author, offset = 0, limit = ScrollPanel.default_panel_size
44     ScrollPanel.where(self.play_list_where(scroll.id)).includes(ScrollPanel.list_opt).order('scroll_panels.t').offset(offset).limit(limit)
45   end
46   
47   def self.list_opt
48     {
49       :comic => {
50         :author => {}, 
51       }
52     }
53   end
54   
55   def self.list_json_opt
56     {:include => {
57       :comic => {
58         :author => {}, 
59       }
60     }}
61   end
62   
63   def self.show_opt
64     {:include => {
65       :comic => {
66       }
67     }}
68   end
69   
70   def self.new_t comic_id
71     r = Story.max_t(comic_id)
72     r.blank? ? 0 : r.to_i + 1
73   end
74   
75   def self.max_t comic_id
76     Story.maximum(:t, :conditions => ['comic_id = ?', comic_id])
77   end
78   
79   def self.find_t comic_id, t
80     Story.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t])
81   end
82   
83   def self.collect_t story
84     r = Story.find(:all, :conditions => ['comic_id = ?', story.comic_id], :order => 't')
85     r.map {|s| s.t}
86   end
87   
88   def self.serial? ary
89     i = 0
90     ary.compact.sort.each do |t|
91       break false unless t == i
92       i += 1
93     end
94     ary.compact.size == i
95   end
96   
97   def self.validate_t story
98     Story.serial?(Story.collect_t(story))
99   end
100   
101   def insert_shift
102     Story.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t])
103   end
104   
105   def lesser_shift old_t
106     self.t = 0 if self.t < 0
107     Story.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, self.t, old_t])
108   end
109   
110   def higher_shift old_t
111     nf = Story.find_t(self.comic_id, self.t)
112     max_t = Story.max_t(self.comic_id).to_i
113     self.t = max_t if self.t > max_t
114     Story.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, old_t, self.t])
115   end
116   
117   def update_shift old_t
118     if self.t > old_t
119       higher_shift old_t
120     else
121       lesser_shift old_t
122     end
123   end
124   
125   def rotate old_t = nil
126     if self.new_record?
127       if self.t.blank?
128         self.t = Story.new_t self.comic_id
129       else
130         self.insert_shift
131       end
132     else
133       if self.t.blank?
134       else
135         self.update_shift old_t
136       end
137     end
138   end
139   
140   def allow? operators
141     return nil if self.story_id == nil or self.comic_id == nil
142     self.comic.own?(operators) and self.comic.usable?(operators)
143   end
144   
145   def store operators, old_t = nil
146     res = false
147     ScrollPanel.transaction do
148       case self.allow? operators
149       when true
150         self.rotate old_t
151       when false
152         raise ActiveRecord::Forbidden
153       else
154       end
155       res = self.save
156       raise ActiveRecord::Rollback unless res
157       res = ScrollPanel.validate_t(self.comic_id) 
158       unless res
159         self.errors.add :t, 'unserialized'
160         raise ActiveRecord::Rollback 
161       end
162     end
163     res
164   end
165   
166 end