smart_list 0.0.1

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.
Files changed (3) hide show
  1. data/lib/add_order_bit.rb +10 -0
  2. data/lib/smart_list.rb +204 -0
  3. metadata +47 -0
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+ class AddOrderBit < ActiveRecord::Migration
3
+
4
+ ORDER_BIT_DEFAULT = 100
5
+
6
+ def self.add_to_table(table_name)
7
+ add_column table_name, :order_bit, :integer, :default => ORDER_BIT_DEFAULT
8
+ end
9
+
10
+ end
data/lib/smart_list.rb ADDED
@@ -0,0 +1,204 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require "smart_list"
4
+ require "add_order_bit"
5
+ require "smart_list_helper"
6
+ require "digest/sha1"
7
+
8
+ $active_smart_lists = {}
9
+
10
+ module SmartList
11
+
12
+ def self.included(base)
13
+ base.extend ClassMethods
14
+ end
15
+
16
+ module ClassMethods
17
+ def smart_list(options = {:order_bit => "order_bit", :group => nil, :scope_conditions => nil})
18
+ # Check if order_bit exists
19
+ options[:order_bit] ||= "order_bit"
20
+ options[:fixed] ||= false
21
+ if self.column_names.index(options[:order_bit].to_s).nil?
22
+ ::AddOrderBit.add_to_table(self.table_name)
23
+ else
24
+ unless is_smart_list?
25
+ cattr_accessor :group_col, :order_bit_name, :base_class, :fixed_list
26
+ send :include, InstanceMethods
27
+
28
+ $active_smart_lists.merge!(Digest::SHA1.hexdigest(self.name) => self.name)
29
+ end
30
+ self.send(:default_scope, :order => "#{options[:order_bit].to_s} ASC")
31
+ self.send(:before_create, :set_order_bit)
32
+ self.group_col = (options[:group].to_sym) rescue nil
33
+ self.order_bit_name = options[:order_bit].to_sym
34
+ self.base_class = options[:base_class].constantize rescue self.name.constantize
35
+ self.fixed_list = options[:fixed]
36
+ end
37
+ end
38
+
39
+ def grouped_list(group_name)
40
+ if self.group_col.nil? || self.group_col.blank?
41
+ self.find(:all)
42
+ else
43
+ self.find(:all, :conditions => {self.group_col => group_name})
44
+ end
45
+ end
46
+
47
+ def groups
48
+ if self.group_col.nil? || self.group_col.blank?
49
+ raise "This is not a grouped list - use options[:group] set colummn to group lists"
50
+ else
51
+ puts self.group_col.inspect
52
+ self.find(:all, :group => self.group_col).map {|x| x.group_name }
53
+ end
54
+ end
55
+
56
+ def group_list
57
+ self.groups.map {|group| self.find(:all, :conditions => {self.group_col => group})}
58
+ end
59
+
60
+ def is_smart_list?
61
+ self.included_modules.include?(InstanceMethods)
62
+ end
63
+
64
+ def reorder_group(group_name, options = {:order_by => :created_at})
65
+ if self.group_col.nil? || self.group_col.blank?
66
+ raise "Only grouped lists could be reordered"
67
+ else
68
+ transaction do
69
+ group = self.grouped_list(group_name)
70
+ order_mode = options[:order_by].to_s
71
+ ordered = group.sort_by {|item| item.send(order_mode)}
72
+ ordered.each_with_index do |item, i|
73
+ item[self.base_class.order_bit_name] = AddOrderBit::ORDER_BIT_DEFAULT+i
74
+ item.send(:update_without_callbacks)
75
+ end
76
+
77
+ new_group = self.grouped_list(group_name).map {|item| item.id}
78
+ if new_group == ordered.map {|item| item.id}
79
+ return true
80
+ else
81
+ raise ActiveRecord::Rollback
82
+ return false
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ module InstanceMethods
90
+ def move_up!
91
+ if self.base_class.fixed_list == false
92
+ unless self.order_position == 0
93
+ old_pos = self.order_bit_pos
94
+ pre_item = self.pre
95
+ if old_pos != pre_item.order_bit_pos
96
+ self.update_attributes(self.base_class.order_bit_name => pre_item.order_bit_pos)
97
+ pre_item.update_attributes(self.base_class.order_bit_name => old_pos)
98
+ else
99
+ self.update_attributes(self.base_class.order_bit_name => old_pos-1)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def move_down!
106
+ if self.base_class.fixed_list == false
107
+ if self.base_class.group_col.nil?
108
+ all = self.base_class.find(:all)
109
+ else
110
+ all = self.base_class.find(:all, :conditions => {self.base_class.group_col => self.send(self.base_class.group_col)})
111
+ end
112
+ unless self.order_position == all.size-1
113
+ old_pos = self.order_bit_pos
114
+ post_item = self.post
115
+ if old_pos != post_item.order_bit_pos
116
+ self.update_attributes(self.base_class.order_bit_name => post_item.order_bit_pos)
117
+ post_item.update_attributes(self.base_class.order_bit_name => old_pos)
118
+ else
119
+ self.update_attributes(self.base_class.order_bit_name => old_pos+1)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ def group_list_items(conditions = {})
126
+ if self.base_class.group_col.nil? || self.base_class.group_col.blank?
127
+ self.base_class.find(:all)
128
+ else
129
+ self.base_class.find_by_sql("SELECT * from #{self.base_class.table_name} where #{self.base_class.group_col} = '#{self[self.base_class.group_col].to_s}' order by #{self.base_class.order_bit_name} ASC")
130
+ end
131
+ end
132
+
133
+ # Previos Item
134
+ def pre
135
+ pos = (self.order_position == 0 ? 0 : (self.order_position - 1 rescue 0))
136
+ all = self.group_list_items[pos]
137
+ end
138
+
139
+ # Next Item
140
+ def post
141
+ all = self.group_list_items
142
+ pos = (self.order_position == all.size-1 ? self.order_position : self.order_position + 1)
143
+ all[pos]
144
+ end
145
+
146
+ def order_position
147
+ all = self.group_list_items.map {|x| x.id}
148
+ all.index(self.id)
149
+ end
150
+
151
+ def order_bit_pos
152
+ self.attributes[self.base_class.order_bit_name.to_s]
153
+ end
154
+
155
+ def group_name
156
+ if self.base_class.group_col.nil?
157
+ ""
158
+ else
159
+ self.send(self.base_class.group_col.to_s)
160
+ end
161
+ end
162
+
163
+ def set_order_bit
164
+ if self.base_class.fixed_list == false
165
+ self[self.base_class.order_bit_name] = self.base_class.last[self.base_class.order_bit_name] + 1 rescue 100
166
+ end
167
+ end
168
+
169
+ def followers(options = {})
170
+ if self.base_class.group_col.nil?
171
+ self.base_class.find_by_sql("SELECT * from #{self.base_class.table_name} where #{self.base_class.order_bit_name} #{options[:include_self] == true ? '>=' : '>'} #{self.order_bit}")
172
+ else
173
+ self.base_class.find_by_sql("SELECT * from #{self.base_class.table_name} where #{self.base_class.order_bit_name} #{options[:include_self] == true ? '>=' : '>'} #{self.order_bit} and #{self.base_class.group_col.to_s} = '#{self.group_name}'")
174
+ end
175
+ end
176
+
177
+ def previous_items(options = {})
178
+ if self.base_class.group_col.nil?
179
+ self.base_class.find_by_sql("SELECT * from #{self.base_class.table_name} where #{self.base_class.order_bit_name} #{options[:include_self] == true ? '<=' : '<'} #{self.order_bit}")
180
+ else
181
+ self.base_class.find_by_sql("SELECT * from #{self.base_class.table_name} where #{self.base_class.order_bit_name} #{options[:include_self] == true ? '<=' : '<'} #{self.order_bit} and #{self.base_class.group_col.to_s} = '#{self.group_name}'")
182
+ end
183
+ end
184
+
185
+ def class_name_sha
186
+ Digest::SHA1(self.class.name)
187
+ end
188
+
189
+ end
190
+
191
+ class Engine < Rails::Engine
192
+ end
193
+
194
+ SmartList::Engine.routes.draw do
195
+ get "/smart_list/move_up/:type/:id", :controller => "smart_list", :action => "move_up"
196
+ get "/smart_list/move_down/:type/:id", :controller => "smart_list", :action => "move_down"
197
+ end
198
+
199
+
200
+ end
201
+
202
+ ActiveRecord::Base.send(:include, SmartList)
203
+ ActionController::Base.helper SmartListHelper
204
+
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smart_list
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Florian Eck
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Easy to use list behavior for ActiveRecord models, includes grouping
15
+ of items by column content, order, reorder and helpers for ActionView
16
+ email: it-support@friends-systems.de
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/smart_list.rb
22
+ - lib/add_order_bit.rb
23
+ homepage: https://github.com/florianeck/smart_list
24
+ licenses: []
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 1.8.25
44
+ signing_key:
45
+ specification_version: 3
46
+ summary: List-style behavior for ActiveRecordt
47
+ test_files: []