OSDN Git Service

Merge branch 'v06' of git.sourceforge.jp:/gitroot/pettanr/pettanr into v06
[pettanr/pettanr.git] / app / models / story.rb
1 #ストーリー
2 class Story < Pettanr::Content
3   has_many :story_sheets
4   belongs_to :comic
5   
6   validates :comic_id, :presence => true, :numericality => true, :existence => {:both => false}
7   validates :title, :presence => true, :length => {:maximum => 100}
8   validates :visible, :presence => true, :numericality => true, :inclusion => {:in => 0..1}
9   validates :t, :presence => true, :numericality => {:greater_than_or_equal_to => 0}
10   
11   def self.owner_model
12     Comic
13   end
14   
15   def self.valid_encode_columns
16     super + ['title', 'description']
17   end
18   
19   def supply_default
20     self.comic_id = nil
21     self.visible = 0 if self.visible.blank?
22     self.t = nil
23   end
24   
25   def overwrite
26   end
27   
28   def visible? operators
29     return false unless super
30     self.owner_model.visible? operators
31   end
32   
33   def disp_t
34     self.t + 1
35   end
36   
37   def disp_t_by_text
38     I18n.t('stories.show.t', :t => self.disp_t)
39   end
40   
41   def title_with_t
42     self.disp_t_by_text  + ':' + self.title
43   end
44   
45   def story_sheets_count
46     StorySheet.where(['story_sheets.story_id = ?', self.id]).count
47   end
48   
49   def self.list_where
50     'stories.visible > 0'
51   end
52   
53   def self.list_order
54     'stories.updated_at desc'
55   end
56   
57   def self.list_opt
58     {:comic => {:author => {}} }
59   end
60   
61   def self.list_json_opt
62     {:include => {:comic => {:include => {:author => {}}} }}
63   end
64   
65   def self.show_opt
66     {:include => {:comic => {:author => {}} }}
67   end
68   
69   def self.show_json_opt
70     {:include => {:comic => {:include => {:author => {}}} }}
71   end
72   
73   def self.visible_count
74     Story.count 'visible > 0'
75   end
76   
77   def destroy_with_story_sheet
78     res = false
79     Story.transaction do
80       self.story_sheets.each do |story_sheet|
81         raise ActiveRecord::Rollback unless story_sheet.destroy
82       end
83       raise ActiveRecord::Rollback unless self.destroy
84       res = true
85     end
86     res
87   end
88   
89   def self.new_t comic_id
90     r = Story.max_t(comic_id)
91     r.blank? ? 0 : r.to_i + 1
92   end
93   
94   def self.max_t comic_id
95     Story.maximum(:t, :conditions => ['comic_id = ?', comic_id])
96   end
97   
98   def self.find_t comic_id, t
99     Story.find(:first, :conditions => ['comic_id = ? and t = ?', comic_id, t])
100   end
101   
102   def self.collect_t story
103     r = Story.find(:all, :conditions => ['comic_id = ?', story.comic_id], :order => 't')
104     r.map {|s| s.t}
105   end
106   
107   def self.serial? ary
108     i = 0
109     ary.compact.sort.each do |t|
110       break false unless t == i
111       i += 1
112     end
113     ary.compact.size == i
114   end
115   
116   def self.validate_t story
117     Story.serial?(Story.collect_t(story))
118   end
119   
120   def insert_shift
121     Story.update_all('t = t + 1', ['comic_id = ? and t >= ?', self.comic_id, self.t])
122   end
123   
124   def lesser_shift old_t
125     self.t = 0 if self.t < 0
126     Story.update_all('t = t + 1', ['comic_id = ? and (t >= ? and t < ?)', self.comic_id, self.t, old_t])
127   end
128   
129   def higher_shift old_t
130     nf = Story.find_t(self.comic_id, self.t)
131     max_t = Story.max_t(self.comic_id).to_i
132     self.t = max_t if self.t > max_t
133     Story.update_all('t = t - 1', ['comic_id = ? and (t > ? and t <= ?)', self.comic_id, old_t, self.t])
134   end
135   
136   def update_shift old_t
137     if self.t > old_t
138       higher_shift old_t
139     else
140       lesser_shift old_t
141     end
142   end
143   
144   def rotate old_t = nil
145     if self.new_record?
146       if self.t.blank?
147         self.t = Story.new_t self.comic_id
148       else
149         self.insert_shift
150       end
151     else
152       if self.t.blank?
153       else
154         self.update_shift old_t
155       end
156     end
157   end
158   
159   def allow? operators
160     return nil if self.comic_id == nil
161     self.comic.own?(operators)
162   end
163   
164   def store operators, old_t = nil
165     res = false
166     Story.transaction do
167       case self.allow? operators
168       when true
169         self.rotate old_t
170       when false
171         raise ActiveRecord::Forbidden
172       else
173       end
174       res = self.save
175       raise ActiveRecord::Rollback unless res
176       res = Story.validate_t(self) 
177       unless res
178         self.errors.add :t, 'unserialized'
179         raise ActiveRecord::Rollback 
180       end
181     end
182     res
183   end
184   
185   def destroy_and_shorten
186     res = false
187     Story.transaction do
188       Story.update_all('t = t - 1', ['comic_id = ? and (t > ?)', self.comic_id, self.t])
189       raise ActiveRecord::Rollback unless self.destroy_with_story_sheet
190       res = true
191     end
192     res
193   end
194   
195   
196 end