OSDN Git Service

work
[pettanr/pettanr.git] / lib / manifest / list.rb
1
2 module Pettanr
3   class ListManager
4     class BaseList
5       def initialize page, page_size, operators, item_name, list_name, conf, manifest
6         @operators = operators
7         @item_name = item_name
8         @list_name = list_name
9         @conf = conf
10         @manifest = manifest
11         @default_page_size = @conf['default_page_size'] || 25
12         @max_page_size = @conf['max_page_size'] || 100
13         @page = self.page_number(page) 
14         @page_size = self.page_size page_size
15         
16         @model = @item_name.classify.constantize
17         @offset = (@page -1) * @page_size
18         @table_name = @model.table_name
19         if @model.content?
20           @owner_model = @model.owner_model
21           @owner_table_name = @owner_model.table_name if @owner_model
22         end
23       end
24       
25       def page_number prm = nil
26         page = prm.to_i
27         page = 1 if page < 1
28         page
29       end
30       
31       def page_size prm
32         page_size = prm.to_i
33         page_size = @max_page_size if page_size > @max_page_size
34         page_size = @default_page_size if page_size < 1
35         page_size
36       end
37       
38       def where
39         @model.list_where
40       end
41       
42       def includes
43         if @owner_model
44           if @owner_model.owner_model
45             {@owner_model.item_name => {@owner_model.owner_model.item_name => {}}}
46           else
47             {@owner_model.item_name => {}}
48           end
49         else
50           {}
51         end
52       end
53       
54       def order
55         @model.list_order
56       end
57       
58       def items
59         @model.where(self.where()).includes(self.includes).order(self.order).offset(@offset).limit(@page_size)
60       end
61       
62       def paginate
63         c = @model.where(self.where()).includes(self.includes).count
64         Kaminari.paginate_array(Array.new(c, nil)).page(@offset).per(@page_size)
65       end
66       
67     end
68     
69     class PublicList < BaseList
70     end
71     
72     class PrivateList < BaseList
73       def where 
74         case @model.owner_type
75         when :author
76           operator = @operators.author
77         when :artist
78           operator = @operators.artist
79         end
80         t = if @owner_model
81           if @owner_model.owner_model
82             @owner_model.owner_model.table_name
83           else
84             @owner_model.table_name
85           end
86         else
87           @table_name
88         end
89         [t + '.' + @model.owner_type.to_s + '_id = ?', operator.id]
90       end
91     end
92     
93     class SystemResourceList < BaseList
94       def items
95         @model.enable_list
96       end
97       
98     end
99     
100     class HasManyList < BaseList
101       def initialize page, page_size, operators, item_name, list_name, conf, manifest
102         super
103         @association_name = @conf['association_name']
104         @has_many_conf = @manifest.model(@item_name).associations['has_many'] || {}
105         @association_conf = @has_many_conf[@association_name] || {}
106         @association_model_name = @association_conf['model']
107         @association_model = @association_model_name.classify.constantize
108         @foreign_key = @association_conf['foreign_key']
109       end
110       
111       def where parent_item
112         w = @model.list_where
113         w += ' and ' unless w.blank?
114         t = @owner_model ? @owner_table_name : @table_name
115         [w + @association_model_name + '.' + @foreign_key + ' = ?', parent_item.id] 
116       end
117       
118       def includes
119   #   @with_model_name ? {@with_model_name.classify.constantize.table_name => {}} : {}
120         w = @owner_model ? {@owner_model.item_name => {}} : {}
121         w.merge({@association_model.table_name => {} }) 
122       end
123       
124       def items parent_item
125         @model.where(self.where(parent_item)).includes(self.includes).order(self.order).offset(@offset).limit(@page_size)
126       end
127       
128       def paginate parent_item
129         Kaminari.paginate_array(Array.new(@model.where(self.where(parent_item).includes(self.includes)).count, nil)).page(@offset).per(@page_size)
130       end
131       
132     end
133     
134     class FilterList < BaseList
135       def initialize page, page_size, operators, item_name, list_name, conf, manifest
136         super
137         @list_list_conf = @manifest.list(@item_name).lists[list_name] || {}
138         @from = @list_list_conf['from']
139         @filter_key = @list_list_conf['filter_key']
140         @includes = @list_list_conf['includes']
141         
142         @with_model_name = @list_list_conf['with']
143       end
144       
145       def where filter_item
146         w = @model.list_where
147         w += ' and ' unless w.blank?
148         [w + @table_name + '.' + @filter_key + ' = ?', filter_item.id] 
149       end
150       
151       def includes
152         return @includes if @includes
153         w = @owner_model ? {@owner_model.item_name => {}} : {}
154         w.merge({@from => {} }) 
155       end
156       
157       def items filter_item
158         @model.where(self.where(filter_item)).includes(self.includes).order(self.order).offset(@offset).limit(@page_size)
159       end
160       
161       def paginate filter_item
162         Kaminari.paginate_array(Array.new(@model.where(self.where(filter_item).includes(self.includes)).count, nil)).page(@offset).per(@page_size)
163       end
164       
165     end
166     
167     class ThroughFilterList < FilterList
168       def initialize page, page_size, operators, item_name, list_name, conf, manifest
169         super
170         @through = @list_list_conf['through']
171       end
172       
173       def includes
174         {@through => {@from => {}} }
175       end
176       
177       def where filter_item
178         w = @model.list_where
179         w += ' and ' unless w.blank?
180         [w + @through + '.' + @filter_key + ' = ?', filter_item.id] 
181       end
182       
183     end
184     
185     class ElementFilterList < FilterList
186       def includes
187         {@owner_model.item_name => {}}
188       end
189       
190       def where filter_item
191         w = @model.list_where
192         w += ' and ' unless w.blank?
193         [w + @owner_table_name + '.' + @filter_key + ' = ?', filter_item.id] 
194       end
195       
196     end
197     
198     class PlayList
199       attr :params_offset, :params_count, :offset, :count, :limit
200       def initialize params_offset, params_count, operators, item_name, list_name, conf, manifest
201         @operators = operators
202         @item_name = item_name
203         @list_name = list_name
204         @conf = conf
205         @manifest = manifest
206         
207         @default_page_size = @conf['default_page_size'] || 25
208         @max_page_size = @conf['max_page_size'] || 100
209         @params_offset = params_offset
210         @params_count = params_count
211         @list_list_conf = @manifest.list(@item_name).lists[list_name] || {}
212         @model_name = @list_list_conf['model']
213         @filter_key = @list_list_conf['filter_key']
214         @model = @model_name.classify.constantize
215         @table_name = @model.table_name
216         if @model.content?
217           @owner_model = @model.owner_model
218           @owner_table_name = @owner_model.table_name if @owner_model
219         end
220       end
221       
222       def offset cnt, prm = nil
223         offset = prm.to_i
224         offset = cnt - 1 if offset >= cnt
225         offset = cnt - offset.abs if offset < 0
226         offset = 0 if offset < 0
227         offset
228       end
229       
230       def limit prm
231         prm ||= @default_page_size
232         count = prm.to_i
233         count = @max_page_size if count > @max_page_size
234         count = @default_page_size if count < 1
235         count
236       end
237       
238       def count filter_item
239         @count ||= @model.count(:conditions => self.where(filter_item), :include => self.includes).to_i
240       end
241       
242       def where filter_item
243         w = @model.list_where
244         w += ' and ' unless w.blank?
245         [w + @table_name + '.' + @filter_key + ' = ?', filter_item.id] 
246       end
247       
248       def includes
249         {@owner_model.item_name => {}}
250       end
251       
252       def order
253         @table_name + '.t'
254       end
255       
256       def items filter_item
257         c  = @count || self.count(filter_item)
258         o  = self.offset c, @offset
259         l  = self.limit @count
260         @model.where(self.where(filter_item)).includes(self.includes).order(self.order).offset(o).limit(l)
261       end
262       
263       def prev_offset filter_item
264         c  = @count || self.count(filter_item)
265         o  = self.offset c, @offset
266         l  = self.limit @count
267         if o > 0
268           if o - l < 0
269             0
270           else
271             o - l
272           end
273         else
274           nil
275         end
276       end
277       
278       def next_offset filter_item
279         c  = @count || self.count(filter_item)
280         o  = self.offset c, @offset
281         l  = self.limit @count
282         if o + l > c
283           nil
284         else
285           o + l
286         end
287       end
288     end
289     
290     @@types = {
291       'public' => PublicList, 'private' => PrivateList, 'system_resource' => SystemResourceList,
292       'has_many' => HasManyList, 'filter' => FilterList, 
293       'through_filter' => ThroughFilterList, 'element_filter' => ElementFilterList, 
294       'play' => PlayList
295     }
296     def initialize list_manifest
297       @list_manifest = list_manifest
298       @item_name = @list_manifest.item_name
299       @manifest = @list_manifest.manifest
300       @list_conf = @list_manifest.conf
301       @lists = {}
302       @list_manifest.lists.each {|list_name, conf|
303         type = conf['type']
304         @lists[list_name] = @@types[type]
305       }
306     end
307     
308     def open list_name, page, page_size, operators
309       raise "undefined list for #{@item_name}::#{list_name}\nconf:#{@list_conf}\n" unless @lists[list_name]
310       @lists[list_name].new page, page_size, operators, @item_name, list_name, @list_conf, @manifest
311     end
312     
313   end
314 end
315