lolita-menu 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,6 +22,6 @@ class CreateLolitaMenuItems < ActiveRecord::Migration
22
22
  end
23
23
 
24
24
  def self.down
25
- drop_table :menu_items
25
+ drop_table :lolita_menu_items
26
26
  end
27
27
  end
@@ -4,103 +4,103 @@ require "lolita-menu/nested_tree/branch_builder"
4
4
  require "lolita-menu/nested_tree/tree_builder"
5
5
 
6
6
  module Lolita
7
- module Menu
8
- module NestedTree
9
- def self.included(base_class)
10
- base_class.extend(Lolita::Menu::NestedTree::ClassMethods)
11
- base_class.class_eval do
12
- include Lolita::Menu::NestedTree::InstanceMethods
13
- attr_accessor :place
14
- before_create :set_default_positions
15
- after_create :put_in_place
16
- end
17
- if base_class.respond_to?(:after_lolita_loaded)
18
- base_class.after_lolita_loaded do
19
- if self.lolita_nested_tree.scope_classes.any?
20
- parent_scope_columns = self.lolita_nested_tree.scope_classes.first.lolita.list.columns
21
- parent_scope_actions = self.lolita_nested_tree.scope_classes.first.lolita.list.actions
22
- #parent_scope_columns.actions = self.lolita.list.columns.actions
23
- self.lolita.list.columns = parent_scope_columns
24
- self.lolita.list.instance_variable_set(:@temp_actions, parent_scope_actions)
25
- end
26
- self.lolita.list.pagination_method ||= :paginate_nested_tree
27
- self.lolita.list.builder = {:name => "/lolita/menu/nested_tree", :state => :display, :if =>{:state =>:display}}
28
- end
29
- end
30
- end
31
-
32
- def self.is_tree?(klass)
33
- klass.respond_to?(:lolita_nested_tree) && klass.lolita_nested_tree
34
- end
35
-
36
- module ClassMethods
37
-
38
- def paginate_nested_tree(page,per_page,options)
39
- if scope_class = self.lolita_nested_tree.scope_classes.first
40
- scope_class.page(page).per(per_page)
41
- else
42
- where(nil)
43
- end
44
- end
45
-
46
- def create_root!
47
- new_branch = self.build_empty_branch(default_root_position)
48
- new_branch.save!
49
- new_branch
50
- end
51
-
52
- def find_or_create_root(attributes = {})
53
- if root = self.with_tree_scope(attributes).root
54
- root
55
- else
56
- root = nil
57
- self.with_tree_scope(attributes) do
58
- root = create_root!
59
- end
60
- root
61
- end
62
- end
63
-
64
- def default_root_position
65
- {
66
- :lft=>1,
67
- :rgt=>2,
68
- :depth=>0,
69
- :parent_id=>nil
70
- }
71
- end
72
-
73
- def root
74
- where(with_tree_scope.merge(:parent_id=>nil)).where("lft>0").order("lft asc").first
75
- end
76
-
77
- def with_tree_scope(record_or_hash=nil, &block)
78
- if record_or_hash
79
- scope_hash = record_or_hash.respond_to?(:to_scope_hash) ? record_or_hash.to_scope_hash : record_or_hash
80
- if block_given?
81
- begin
82
- @lolita_menu_nested_tree_scope = scope_hash
83
- instance_eval(&block)
84
- ensure
85
- @lolita_menu_nested_tree_scope = nil
86
- end
87
- else
88
- where(scope_hash)
89
- end
90
- else
91
- @lolita_menu_nested_tree_scope || {}
92
- end
93
- end
94
-
95
- def update_whole_tree(items, params = {})
96
- begin
97
- self.transaction do
98
- tree_builder = Lolita::Menu::NestedTree::TreeBuilder.new(self, items, params)
99
- tree_builder.update_items
100
- true
101
- end
102
- end
103
- end
7
+ module Menu
8
+ module NestedTree
9
+ def self.included(base_class)
10
+ base_class.extend(Lolita::Menu::NestedTree::ClassMethods)
11
+ base_class.class_eval do
12
+ include Lolita::Menu::NestedTree::InstanceMethods
13
+ attr_accessor :place
14
+ before_create :set_default_positions
15
+ after_create :put_in_place
16
+ end
17
+ if base_class.respond_to?(:after_lolita_loaded)
18
+ base_class.after_lolita_loaded do
19
+ if self.lolita_nested_tree.scope_classes.any?
20
+ parent_scope_columns = self.lolita_nested_tree.scope_classes.first.lolita.list.columns
21
+ parent_scope_actions = self.lolita_nested_tree.scope_classes.first.lolita.list.actions
22
+ #parent_scope_columns.actions = self.lolita.list.columns.actions
23
+ self.lolita.list.columns = parent_scope_columns
24
+ self.lolita.list.instance_variable_set(:@temp_actions, parent_scope_actions)
25
+ end
26
+ self.lolita.list.pagination_method ||= :paginate_nested_tree
27
+ self.lolita.list.builder = {:name => "/lolita/menu/nested_tree", :state => :display, :if =>{:state =>:display}}
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.is_tree?(klass)
33
+ klass.respond_to?(:lolita_nested_tree) && klass.lolita_nested_tree
34
+ end
35
+
36
+ module ClassMethods
37
+
38
+ def paginate_nested_tree(page,per_page,options)
39
+ if scope_class = self.lolita_nested_tree.scope_classes.first
40
+ scope_class.page(page).per(per_page)
41
+ else
42
+ where(nil)
43
+ end
44
+ end
45
+
46
+ def create_root!
47
+ new_branch = self.build_empty_branch(default_root_position)
48
+ new_branch.save!
49
+ new_branch
50
+ end
51
+
52
+ def find_or_create_root(attributes = {})
53
+ if root = self.with_tree_scope(attributes).root
54
+ root
55
+ else
56
+ root = nil
57
+ self.with_tree_scope(attributes) do
58
+ root = create_root!
59
+ end
60
+ root
61
+ end
62
+ end
63
+
64
+ def default_root_position
65
+ {
66
+ :lft=>1,
67
+ :rgt=>2,
68
+ :depth=>0,
69
+ :parent_id=>nil
70
+ }
71
+ end
72
+
73
+ def root
74
+ where(with_tree_scope.merge(:parent_id=>nil)).where("lft>0").order("lft asc").first
75
+ end
76
+
77
+ def with_tree_scope(record_or_hash=nil, &block)
78
+ if record_or_hash
79
+ scope_hash = record_or_hash.respond_to?(:to_scope_hash) ? record_or_hash.to_scope_hash : record_or_hash
80
+ if block_given?
81
+ begin
82
+ @lolita_menu_nested_tree_scope = scope_hash
83
+ instance_eval(&block)
84
+ ensure
85
+ @lolita_menu_nested_tree_scope = nil
86
+ end
87
+ else
88
+ where(scope_hash)
89
+ end
90
+ else
91
+ @lolita_menu_nested_tree_scope || {}
92
+ end
93
+ end
94
+
95
+ def update_whole_tree(items, params = {})
96
+ begin
97
+ self.transaction do
98
+ tree_builder = Lolita::Menu::NestedTree::TreeBuilder.new(self, items, params)
99
+ tree_builder.update_items
100
+ true
101
+ end
102
+ end
103
+ end
104
104
 
105
105
  def build_empty_branch(attributes)
106
106
  if self.lolita_nested_tree.build_method && self.respond_to?(self.lolita_nested_tree.build_method)
@@ -110,166 +110,166 @@ module Lolita
110
110
  end
111
111
  end
112
112
 
113
- def update_item(item)
114
- self.where(:id => item.value_for(:item_id)).update_all(item.attribute_value_pairs_hash)
115
- end
113
+ def update_item(item)
114
+ self.where(:id => item.value_for(:item_id)).update_all(item.attribute_value_pairs_hash)
115
+ end
116
116
 
117
- def remove_items(ids)
118
- self.where(:id => ids).delete_all
119
- end
117
+ def remove_items(ids)
118
+ self.where(:id => ids).delete_all
119
+ end
120
120
 
121
- def all_tree_item_ids
122
- self.all.map(&:id)
123
- end
121
+ def all_tree_item_ids
122
+ self.all.map(&:id)
123
+ end
124
124
 
125
125
  def only_children
126
126
  where("rgt-lft=1")
127
127
  end
128
- end
129
-
130
- module InstanceMethods
131
- def root?
132
- self.parent_id.nil?
133
- end
134
-
135
- def parent
136
- @parent ||= self.class.find_by_id(self.parent_id)
137
- end
138
-
139
- def parent=(parent_item)
140
- @parent = parent_item
141
- end
142
-
143
- def children
144
- @children ||= self.class.where(:parent_id => self.id).with_tree_scope(self).order("lft asc")
145
- end
146
-
147
- def self_and_descendants
148
- @self_and_descendants ||= self.class.where("lft>=:left AND rgt<=:right",{
149
- :left => self.lft,:right => self.rgt
150
- }).with_tree_scope(self).order("lft asc")
151
- end
152
-
153
- def descendants
154
- @descendants ||= self.class.where("lft>:left AND rgt<:right",{
155
- :left => self.lft, :right => self.rgt
156
- }).with_tree_scope(self).order("lft asc")
157
- end
158
-
159
- def ancestors
160
- @ancestors ||= self.class.where("lft<:left AND rgt>:right AND parent_id IS NOT NULL",{
161
- :left => self.lft, :right => self.rgt
162
- }).with_tree_scope(self).order("lft asc")
163
- end
164
-
165
- def parents
166
- unless @parent
167
- current_parent_id = self.parent_id
168
- @parents = self.ancestors.reverse.inject([]){|results,item|
169
- if item.parent_id && item.id == current_parent_id
170
- current_parent_id = item.parent_id
171
- [item] + results
172
- else
173
- results
174
- end
175
- }
176
- end
177
- @parents
178
- end
179
-
180
- def only_children
181
- @only_children ||= self.class.with_tree_scope(self).order("lft asc")
182
- end
183
-
184
- def root
185
- if self.parent_id.nil?
186
- self
187
- else
188
- self.class.root
189
- end
190
- end
191
-
192
- def append(item)
193
- raise ArgumentError, "can't append itself" if self == item
194
- append_item(item)
195
- recalculate_positions_after(:append)
196
- end
197
-
198
- def to_scope_hash
199
- self.class.lolita_nested_tree.scope_keys.inject({}) do |result, key|
200
- result[key] = self.send(key)
201
- result
202
- end
203
- end
204
-
205
- private
206
-
207
- def set_default_positions
208
- if am_i_new_root? #|| !scope_ids.all?
209
- set_root_position
210
- else
211
- self.place=:append
212
- end
213
- end
214
-
215
- def am_i_new_root?
216
- #scope_ids.all? && scope_records.all? &&
217
- !(self.class.with_tree_scope(self) do
218
- root
219
- end)
220
- end
221
-
222
- #def scope_ids
223
- # self.class.lolita_nested_tree.scope_keys.map do |key|
224
- # self.send(key)
225
- # end
226
- #end
227
-
228
- #def scope_records
229
- # self.class.lolita_nested_tree.scope_keys.map do |scope|
230
- # scope.constantize.exists?(self.send(scope.foreign_key.to_sym))
231
- # end
232
- #end
233
-
234
- def put_in_place
235
- if place==:append
236
- item = self
237
- self.class.with_tree_scope(self) do
238
- root.append(item)
239
- end
240
- end
241
- end
242
-
243
- def set_root_position
244
- self.class.default_root_position.each do |method,value|
245
- unless self.send(method)
246
- self.send(:"#{method}=",value)
247
- end
248
- end
249
- end
250
-
251
- def append_item(item)
252
- attributes = self.class.with_tree_scope.merge(position_for_append)
253
- builder = Lolita::Menu::NestedTree::BranchBuilder.new(nil, attributes)
254
- self.class.where(:id => item.id).update_all(builder.attribute_value_pairs_hash)
255
- end
256
-
257
- def recalculate_positions_after(action)
258
- if action==:append
259
- self.class.update_all("rgt=#{self.rgt+2}","id=#{self.id}")
260
- end
261
- end
262
-
263
- def position_for_append
264
- {
265
- :left => self.rgt,
266
- :right => self.rgt+1,
267
- :depth => self.depth+1,
268
- :parent_id => self.id
269
- }
270
- end
271
- end
272
-
273
- end
274
- end
128
+ end
129
+
130
+ module InstanceMethods
131
+ def root?
132
+ self.parent_id.nil?
133
+ end
134
+
135
+ def parent
136
+ @parent ||= self.class.find_by_id(self.parent_id)
137
+ end
138
+
139
+ def parent=(parent_item)
140
+ @parent = parent_item
141
+ end
142
+
143
+ def children
144
+ @children ||= self.class.where(:parent_id => self.id).with_tree_scope(self).order("lft asc")
145
+ end
146
+
147
+ def self_and_descendants
148
+ @self_and_descendants ||= self.class.where("lft>=:left AND rgt<=:right",{
149
+ :left => self.lft,:right => self.rgt
150
+ }).with_tree_scope(self).order("lft asc")
151
+ end
152
+
153
+ def descendants
154
+ @descendants ||= self.class.where("lft>:left AND rgt<:right",{
155
+ :left => self.lft, :right => self.rgt
156
+ }).with_tree_scope(self).order("lft asc")
157
+ end
158
+
159
+ def ancestors
160
+ @ancestors ||= self.class.where("lft<:left AND rgt>:right AND parent_id IS NOT NULL",{
161
+ :left => self.lft, :right => self.rgt
162
+ }).with_tree_scope(self).order("lft asc")
163
+ end
164
+
165
+ def parents
166
+ unless @parent
167
+ current_parent_id = self.parent_id
168
+ @parents = self.ancestors.reverse.inject([]){|results,item|
169
+ if item.parent_id && item.id == current_parent_id
170
+ current_parent_id = item.parent_id
171
+ [item] + results
172
+ else
173
+ results
174
+ end
175
+ }
176
+ end
177
+ @parents
178
+ end
179
+
180
+ def only_children
181
+ @only_children ||= self.class.with_tree_scope(self).order("lft asc")
182
+ end
183
+
184
+ def root
185
+ if self.parent_id.nil?
186
+ self
187
+ else
188
+ self.class.root
189
+ end
190
+ end
191
+
192
+ def append(item)
193
+ raise ArgumentError, "can't append itself" if self == item
194
+ append_item(item)
195
+ recalculate_positions_after(:append)
196
+ end
197
+
198
+ def to_scope_hash
199
+ self.class.lolita_nested_tree.scope_keys.inject({}) do |result, key|
200
+ result[key] = self.send(key)
201
+ result
202
+ end
203
+ end
204
+
205
+ private
206
+
207
+ def set_default_positions
208
+ if am_i_new_root? #|| !scope_ids.all?
209
+ set_root_position
210
+ else
211
+ self.place=:append
212
+ end
213
+ end
214
+
215
+ def am_i_new_root?
216
+ #scope_ids.all? && scope_records.all? &&
217
+ !(self.class.with_tree_scope(self) do
218
+ root
219
+ end)
220
+ end
221
+
222
+ #def scope_ids
223
+ # self.class.lolita_nested_tree.scope_keys.map do |key|
224
+ # self.send(key)
225
+ # end
226
+ #end
227
+
228
+ #def scope_records
229
+ # self.class.lolita_nested_tree.scope_keys.map do |scope|
230
+ # scope.constantize.exists?(self.send(scope.foreign_key.to_sym))
231
+ # end
232
+ #end
233
+
234
+ def put_in_place
235
+ if place==:append
236
+ item = self
237
+ self.class.with_tree_scope(self) do
238
+ root.append(item)
239
+ end
240
+ end
241
+ end
242
+
243
+ def set_root_position
244
+ self.class.default_root_position.each do |method,value|
245
+ unless self.send(method)
246
+ self.send(:"#{method}=",value)
247
+ end
248
+ end
249
+ end
250
+
251
+ def append_item(item)
252
+ attributes = self.class.with_tree_scope.merge(position_for_append)
253
+ builder = Lolita::Menu::NestedTree::BranchBuilder.new(nil, attributes)
254
+ self.class.where(:id => item.id).update_all(builder.attribute_value_pairs_hash)
255
+ end
256
+
257
+ def recalculate_positions_after(action)
258
+ if action==:append
259
+ self.class.update_all("rgt=#{self.rgt+2}","id=#{self.id}")
260
+ end
261
+ end
262
+
263
+ def position_for_append
264
+ {
265
+ :left => self.rgt,
266
+ :right => self.rgt+1,
267
+ :depth => self.depth+1,
268
+ :parent_id => self.id
269
+ }
270
+ end
271
+ end
272
+
273
+ end
274
+ end
275
275
  end