lolita-menu 0.3.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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