acts_as_list_with_sti_support 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/.specification CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Coroutine
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-03-10 00:00:00 -06:00
18
+ date: 2010-03-25 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: activesupport
22
+ name: activerecord
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  requirements:
@@ -30,7 +30,19 @@ dependencies:
30
30
  version: "0"
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
- description: This acts_as extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a position column defined as an integer on the mapped database table.
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ version_requirements: *id002
45
+ description: This acts_as extension does everything acts_as_list does, but it also works in single table inheritance designs and accepts less brain-damaged scope syntax.
34
46
  email: jdugan@coroutine.com
35
47
  executables: []
36
48
 
@@ -39,14 +51,19 @@ extensions: []
39
51
  extra_rdoc_files:
40
52
  - README.rdoc
41
53
  files:
54
+ - .specification
42
55
  - MIT-LICENSE
43
56
  - README.rdoc
44
57
  - Rakefile
45
58
  - VERSION
59
+ - acts_as_list_with_sti_support.gemspec
46
60
  - init.rb
61
+ - lib/acts_as_list_with_sti_support.rb
62
+ - lib/acts_as_list_with_sti_support/base.rb
63
+ - test/acts_as_list_with_sti_support_test.rb
47
64
  - test/test_helper.rb
48
65
  has_rdoc: true
49
- homepage: http://github.com/coroutine/acts_as_label_with_sti_support
66
+ homepage: http://github.com/coroutine/acts_as_list_with_sti_support
50
67
  licenses: []
51
68
 
52
69
  post_install_message:
data/Rakefile CHANGED
@@ -28,13 +28,16 @@ end
28
28
 
29
29
  begin
30
30
  Jeweler::Tasks.new do |gemspec|
31
- gemspec.name = "acts_as_list_with_sti_support"
32
- gemspec.summary = "Gem version of acts_as_list_with_sti_support Rails plugin, a smarter version of acts_as_list."
33
- gemspec.description = "This acts_as extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a position column defined as an integer on the mapped database table."
31
+ gemspec.authors = ["Coroutine", "John Dugan"]
32
+ gemspec.description = "This acts_as extension does everything acts_as_list does, but it also works in single table inheritance designs and accepts less brain-damaged scope syntax."
34
33
  gemspec.email = "jdugan@coroutine.com"
35
34
  gemspec.homepage = "http://github.com/coroutine/acts_as_list_with_sti_support"
36
- gemspec.authors = ["Coroutine", "John Dugan"]
37
- gemspec.add_dependency "activesupport"
35
+ gemspec.name = "acts_as_list_with_sti_support"
36
+ gemspec.summary = "Gem version of acts_as_list_with_sti_support Rails plugin, a smarter version of acts_as_list."
37
+
38
+ gemspec.add_dependency("activerecord")
39
+ gemspec.add_dependency("activesupport")
40
+ gemspec.files.include("lib/**/*.rb")
38
41
  end
39
42
  Jeweler::GemcutterTasks.new
40
43
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.2
@@ -5,12 +5,12 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{acts_as_list_with_sti_support}
8
- s.version = "0.1.1"
8
+ s.version = "0.1.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Coroutine", "John Dugan"]
12
- s.date = %q{2010-03-10}
13
- s.description = %q{This acts_as extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a position column defined as an integer on the mapped database table.}
12
+ s.date = %q{2010-03-25}
13
+ s.description = %q{This acts_as extension does everything acts_as_list does, but it also works in single table inheritance designs and accepts less brain-damaged scope syntax.}
14
14
  s.email = %q{jdugan@coroutine.com}
15
15
  s.extra_rdoc_files = [
16
16
  "README.rdoc"
@@ -21,10 +21,10 @@ Gem::Specification.new do |s|
21
21
  "README.rdoc",
22
22
  "Rakefile",
23
23
  "VERSION",
24
- "acts_as_list_with_sti_support-0.1.0.gem",
25
24
  "acts_as_list_with_sti_support.gemspec",
26
25
  "init.rb",
27
26
  "lib/acts_as_list_with_sti_support.rb",
27
+ "lib/acts_as_list_with_sti_support/base.rb",
28
28
  "test/acts_as_list_with_sti_support_test.rb",
29
29
  "test/test_helper.rb"
30
30
  ]
@@ -43,11 +43,14 @@ Gem::Specification.new do |s|
43
43
  s.specification_version = 3
44
44
 
45
45
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
46
47
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
47
48
  else
49
+ s.add_dependency(%q<activerecord>, [">= 0"])
48
50
  s.add_dependency(%q<activesupport>, [">= 0"])
49
51
  end
50
52
  else
53
+ s.add_dependency(%q<activerecord>, [">= 0"])
51
54
  s.add_dependency(%q<activesupport>, [">= 0"])
52
55
  end
53
56
  end
data/init.rb CHANGED
@@ -1,5 +1 @@
1
- require 'acts_as_list_with_sti_support'
2
-
3
- ActiveRecord::Base.class_eval do
4
- include Coroutine::Acts::List
5
- end
1
+ require File.dirname(__FILE__) + "/rails/init.rb"
@@ -1,319 +1,10 @@
1
- module Coroutine #:nodoc:
2
- module Acts #:nodoc:
3
- module List #:nodoc:
4
-
5
- def self.included(base)
6
- base.extend(ClassMethods)
7
- end
1
+ # external gems
2
+ require "active_record"
8
3
 
9
-
10
- module ClassMethods
11
-
12
- # = Description
13
- #
14
- # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
15
- # The class that has this specified needs to have a +position+ column defined as an integer on
16
- # the mapped database table.
17
- #
18
- #
19
- # = Usage
20
- #
21
- # class TodoList < ActiveRecord::Base
22
- # has_many :todo_items, :order => "position"
23
- # end
24
- #
25
- # class TodoItem < ActiveRecord::Base
26
- # belongs_to :todo_list
27
- # acts_as_list :scope => :todo_list
28
- # end
29
- #
30
- # todo_list.first.move_to_bottom
31
- # todo_list.last.move_higher
32
- #
33
- #
34
- # = Configuration
35
- #
36
- # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
37
- # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
38
- # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
39
- # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
40
- # Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
41
- #
42
- def acts_as_list(options = {})
43
-
44
- #-------------------------------------------
45
- # scrub options
46
- #-------------------------------------------
47
- options = {} if !options.is_a?(Hash)
48
- column = options.key?(:column) ? options[:column] : :position
49
- scope = options.key?(:scope) ? options[:scope] : "1 = 1"
50
-
51
4
 
52
- #--------------------------------------------
53
- # mix methods into class definition
54
- #--------------------------------------------
55
- class_eval do
56
-
57
- # Add inheritable accessors
58
- write_inheritable_attribute :acts_as_list_column, column
59
- class_inheritable_reader :acts_as_list_column
60
- write_inheritable_attribute :acts_as_list_scope, scope
61
- class_inheritable_reader :acts_as_list_scope
62
- write_inheritable_attribute :acts_as_list_default_scope, "1 = 1"
63
- class_inheritable_reader :acts_as_list_default_scope
64
- write_inheritable_attribute :acts_as_list_scope_condition, nil
65
- class_inheritable_reader :acts_as_list_scope_condition
66
-
67
-
68
- # Add validations (column is allowed to be nil to support soft deletes)
69
- validates_numericality_of column, :only_integer => true, :greater_than => 0, :allow_nil => true
70
-
71
-
72
- # Add callbacks
73
- before_validation_on_create :add_to_list_bottom
74
- before_destroy :remove_from_list
75
-
76
-
77
- # if no default scoping, order by position
78
- if self.default_scoping.empty?
79
- default_scope :order => column
80
- end
81
-
82
-
83
- # Include instance methods
84
- include Coroutine::Acts::List::InstanceMethods
5
+ # acts_as_label extension
6
+ require File.dirname(__FILE__) + "/acts_as_list_with_sti_support/base"
85
7
 
86
- end
87
-
88
- end
89
- end
90
8
 
91
-
92
- # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works
93
- # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter
94
- # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return +true+ if that chapter is
95
- # the first in the list of all chapters.
96
- #
97
- module InstanceMethods
98
-
99
- # Return the instance's class object
100
- def acts_as_list_class
101
- self.class
102
- end
103
-
104
- # Returns the column name that holds the position value.
105
- def position_column
106
- acts_as_list_column
107
- end
108
-
109
- # Returns the scope condition appropriate for the specified definition. (This could probably
110
- # be refactored for brevity.)
111
- def scope_condition
112
- if acts_as_list_scope_condition.nil?
113
-
114
- # if symbol, do convenience conversions
115
- if acts_as_list_scope.is_a?(Symbol)
116
- scope_as_sym = acts_as_list_scope
117
- scope_as_str = acts_as_list_scope.to_s
118
- if scope_as_str.nil?
119
- acts_as_list_scope_condition = "#{scope_as_str} IS NULL"
120
- else
121
- scope_with_id = scope_as_str + "_id"
122
- if scope_as_str !~ /_id$/ && acts_as_list_class.column_names.include?("#{scope_with_id}")
123
- scope_as_sym = scope_with_id.to_sym
124
- scope_as_str = scope_as_sym.to_s
125
- end
126
- acts_as_list_scope_condition = "#{scope_as_str} = \'#{self[scope_as_sym]}\'"
127
- end
128
-
129
- # if lambda, execute in scope of instance
130
- elsif acts_as_list_scope.is_a?(Proc)
131
- acts_as_list_scope_condition = acts_as_list_scope.call(self)
132
-
133
- # else, return string as is
134
- else
135
- acts_as_list_scope_condition = !acts_as_list_scope.blank? ? acts_as_list_scope.to_s : acts_as_list_default_scope.to_s
136
- end
137
- end
138
-
139
- acts_as_list_scope_condition
140
- end
141
-
142
- # Insert the item at the given position (defaults to the top position of 1).
143
- def insert_at(position = 1)
144
- insert_at_position(position)
145
- end
146
-
147
- # Swap positions with the next lower item, if one exists.
148
- def move_lower
149
- return unless lower_item
150
-
151
- acts_as_list_class.transaction do
152
- lower_item.decrement_position
153
- increment_position
154
- end
155
- end
156
-
157
- # Swap positions with the next higher item, if one exists.
158
- def move_higher
159
- return unless higher_item
160
-
161
- acts_as_list_class.transaction do
162
- higher_item.increment_position
163
- decrement_position
164
- end
165
- end
166
-
167
- # Move to the bottom of the list. If the item is already in the list, the items below it have their
168
- # position adjusted accordingly.
169
- def move_to_bottom
170
- return unless in_list?
171
- acts_as_list_class.transaction do
172
- decrement_positions_on_lower_items
173
- assume_bottom_position
174
- end
175
- end
176
-
177
- # Move to the top of the list. If the item is already in the list, the items above it have their
178
- # position adjusted accordingly.
179
- def move_to_top
180
- return unless in_list?
181
- acts_as_list_class.transaction do
182
- increment_positions_on_higher_items
183
- assume_top_position
184
- end
185
- end
186
-
187
- # Removes the item from the list.
188
- def remove_from_list
189
- if in_list?
190
- decrement_positions_on_lower_items
191
- update_attribute position_column, nil
192
- end
193
- end
194
-
195
- # Increase the position of this item without adjusting the rest of the list.
196
- def increment_position
197
- return unless in_list?
198
- update_attribute position_column, self.send(position_column).to_i + 1
199
- end
200
-
201
- # Decrease the position of this item without adjusting the rest of the list.
202
- def decrement_position
203
- return unless in_list?
204
- update_attribute position_column, self.send(position_column).to_i - 1
205
- end
206
-
207
- # Return +true+ if this object is the first in the list.
208
- def first?
209
- return false unless in_list?
210
- self.send(position_column) == 1
211
- end
212
-
213
- # Return +true+ if this object is the last in the list.
214
- def last?
215
- return false unless in_list?
216
- self.send(position_column) == bottom_position_in_list
217
- end
218
-
219
- # Return the next higher item in the list.
220
- def higher_item
221
- return nil unless in_list?
222
- acts_as_list_class.find(:first, :conditions =>
223
- "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
224
- )
225
- end
226
-
227
- # Return the next lower item in the list.
228
- def lower_item
229
- return nil unless in_list?
230
- acts_as_list_class.find(:first, :conditions =>
231
- "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
232
- )
233
- end
234
-
235
- # Test if this record is in a list
236
- def in_list?
237
- !send(position_column).nil?
238
- end
239
-
240
- private
241
- def add_to_list_top
242
- increment_positions_on_all_items
243
- end
244
-
245
- def add_to_list_bottom
246
- self[position_column] = bottom_position_in_list.to_i + 1
247
- end
248
-
249
- # Returns the bottom position number in the list.
250
- # bottom_position_in_list # => 2
251
- def bottom_position_in_list(except = nil)
252
- item = bottom_item(except)
253
- item ? item.send(position_column) : 0
254
- end
255
-
256
- # Returns the bottom item
257
- def bottom_item(except = nil)
258
- conditions = scope_condition
259
- conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
260
- acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
261
- end
262
-
263
- # Forces item to assume the bottom position in the list.
264
- def assume_bottom_position
265
- update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
266
- end
267
-
268
- # Forces item to assume the top position in the list.
269
- def assume_top_position
270
- update_attribute(position_column, 1)
271
- end
272
-
273
- # This has the effect of moving all the higher items up one.
274
- def decrement_positions_on_higher_items(position)
275
- acts_as_list_class.update_all(
276
- "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
277
- )
278
- end
279
-
280
- # This has the effect of moving all the lower items up one.
281
- def decrement_positions_on_lower_items
282
- return unless in_list?
283
- acts_as_list_class.update_all(
284
- "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
285
- )
286
- end
287
-
288
- # This has the effect of moving all the higher items down one.
289
- def increment_positions_on_higher_items
290
- return unless in_list?
291
- acts_as_list_class.update_all(
292
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
293
- )
294
- end
295
-
296
- # This has the effect of moving all the lower items down one.
297
- def increment_positions_on_lower_items(position)
298
- acts_as_list_class.update_all(
299
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
300
- )
301
- end
302
-
303
- # Increments position (<tt>position_column</tt>) of all items in the list.
304
- def increment_positions_on_all_items
305
- acts_as_list_class.update_all(
306
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
307
- )
308
- end
309
-
310
- def insert_at_position(position)
311
- remove_from_list
312
- increment_positions_on_lower_items(position)
313
- self.update_attribute(position_column, position)
314
- end
315
-
316
- end
317
- end
318
- end
319
- end
9
+ # add extensions to active record
10
+ ::ActiveRecord::Base.send(:include, Coroutine::ActsAsList::Base)
@@ -0,0 +1,319 @@
1
+ module Coroutine #:nodoc:
2
+ module ActsAsList #:nodoc:
3
+ module Base #:nodoc:
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+
10
+ module ClassMethods
11
+
12
+ # = Description
13
+ #
14
+ # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
15
+ # The class that has this specified needs to have a +position+ column defined as an integer on
16
+ # the mapped database table.
17
+ #
18
+ #
19
+ # = Usage
20
+ #
21
+ # class TodoList < ActiveRecord::Base
22
+ # has_many :todo_items, :order => "position"
23
+ # end
24
+ #
25
+ # class TodoItem < ActiveRecord::Base
26
+ # belongs_to :todo_list
27
+ # acts_as_list :scope => :todo_list
28
+ # end
29
+ #
30
+ # todo_list.first.move_to_bottom
31
+ # todo_list.last.move_higher
32
+ #
33
+ #
34
+ # = Configuration
35
+ #
36
+ # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
37
+ # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
38
+ # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
39
+ # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
40
+ # Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
41
+ #
42
+ def acts_as_list(options = {})
43
+
44
+ #-------------------------------------------
45
+ # scrub options
46
+ #-------------------------------------------
47
+ options = {} if !options.is_a?(Hash)
48
+ column = options.key?(:column) ? options[:column] : :position
49
+ scope = options.key?(:scope) ? options[:scope] : "1 = 1"
50
+
51
+
52
+ #--------------------------------------------
53
+ # mix methods into class definition
54
+ #--------------------------------------------
55
+ class_eval do
56
+
57
+ # Add inheritable accessors
58
+ write_inheritable_attribute :acts_as_list_column, column
59
+ class_inheritable_reader :acts_as_list_column
60
+ write_inheritable_attribute :acts_as_list_scope, scope
61
+ class_inheritable_reader :acts_as_list_scope
62
+ write_inheritable_attribute :acts_as_list_default_scope, "1 = 1"
63
+ class_inheritable_reader :acts_as_list_default_scope
64
+ write_inheritable_attribute :acts_as_list_scope_condition, nil
65
+ class_inheritable_reader :acts_as_list_scope_condition
66
+
67
+
68
+ # Add validations (column is allowed to be nil to support soft deletes)
69
+ validates_numericality_of column, :only_integer => true, :greater_than => 0, :allow_nil => true
70
+
71
+
72
+ # Add callbacks
73
+ before_validation_on_create :add_to_list_bottom
74
+ before_destroy :remove_from_list
75
+
76
+
77
+ # if no default scoping, order by position
78
+ if self.default_scoping.empty?
79
+ default_scope :order => column
80
+ end
81
+
82
+
83
+ # Include instance methods
84
+ include Coroutine::ActsAsList::Base::InstanceMethods
85
+
86
+ end
87
+
88
+ end
89
+ end
90
+
91
+
92
+ # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works
93
+ # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter
94
+ # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return +true+ if that chapter is
95
+ # the first in the list of all chapters.
96
+ #
97
+ module InstanceMethods
98
+
99
+ # Return the instance's class object
100
+ def acts_as_list_class
101
+ self.class
102
+ end
103
+
104
+ # Returns the column name that holds the position value.
105
+ def position_column
106
+ acts_as_list_column
107
+ end
108
+
109
+ # Returns the scope condition appropriate for the specified definition. (This could probably
110
+ # be refactored for brevity.)
111
+ def scope_condition
112
+ if acts_as_list_scope_condition.nil?
113
+
114
+ # if symbol, do convenience conversions
115
+ if acts_as_list_scope.is_a?(Symbol)
116
+ scope_as_sym = acts_as_list_scope
117
+ scope_as_str = acts_as_list_scope.to_s
118
+ if scope_as_str.nil?
119
+ acts_as_list_scope_condition = "#{scope_as_str} IS NULL"
120
+ else
121
+ scope_with_id = scope_as_str + "_id"
122
+ if scope_as_str !~ /_id$/ && acts_as_list_class.column_names.include?("#{scope_with_id}")
123
+ scope_as_sym = scope_with_id.to_sym
124
+ scope_as_str = scope_as_sym.to_s
125
+ end
126
+ acts_as_list_scope_condition = "#{scope_as_str} = \'#{self[scope_as_sym]}\'"
127
+ end
128
+
129
+ # if lambda, execute in scope of instance
130
+ elsif acts_as_list_scope.is_a?(Proc)
131
+ acts_as_list_scope_condition = acts_as_list_scope.call(self)
132
+
133
+ # else, return string as is
134
+ else
135
+ acts_as_list_scope_condition = !acts_as_list_scope.blank? ? acts_as_list_scope.to_s : acts_as_list_default_scope.to_s
136
+ end
137
+ end
138
+
139
+ acts_as_list_scope_condition
140
+ end
141
+
142
+ # Insert the item at the given position (defaults to the top position of 1).
143
+ def insert_at(position = 1)
144
+ insert_at_position(position)
145
+ end
146
+
147
+ # Swap positions with the next lower item, if one exists.
148
+ def move_lower
149
+ return unless lower_item
150
+
151
+ acts_as_list_class.transaction do
152
+ lower_item.decrement_position
153
+ increment_position
154
+ end
155
+ end
156
+
157
+ # Swap positions with the next higher item, if one exists.
158
+ def move_higher
159
+ return unless higher_item
160
+
161
+ acts_as_list_class.transaction do
162
+ higher_item.increment_position
163
+ decrement_position
164
+ end
165
+ end
166
+
167
+ # Move to the bottom of the list. If the item is already in the list, the items below it have their
168
+ # position adjusted accordingly.
169
+ def move_to_bottom
170
+ return unless in_list?
171
+ acts_as_list_class.transaction do
172
+ decrement_positions_on_lower_items
173
+ assume_bottom_position
174
+ end
175
+ end
176
+
177
+ # Move to the top of the list. If the item is already in the list, the items above it have their
178
+ # position adjusted accordingly.
179
+ def move_to_top
180
+ return unless in_list?
181
+ acts_as_list_class.transaction do
182
+ increment_positions_on_higher_items
183
+ assume_top_position
184
+ end
185
+ end
186
+
187
+ # Removes the item from the list.
188
+ def remove_from_list
189
+ if in_list?
190
+ decrement_positions_on_lower_items
191
+ update_attribute position_column, nil
192
+ end
193
+ end
194
+
195
+ # Increase the position of this item without adjusting the rest of the list.
196
+ def increment_position
197
+ return unless in_list?
198
+ update_attribute position_column, self.send(position_column).to_i + 1
199
+ end
200
+
201
+ # Decrease the position of this item without adjusting the rest of the list.
202
+ def decrement_position
203
+ return unless in_list?
204
+ update_attribute position_column, self.send(position_column).to_i - 1
205
+ end
206
+
207
+ # Return +true+ if this object is the first in the list.
208
+ def first?
209
+ return false unless in_list?
210
+ self.send(position_column) == 1
211
+ end
212
+
213
+ # Return +true+ if this object is the last in the list.
214
+ def last?
215
+ return false unless in_list?
216
+ self.send(position_column) == bottom_position_in_list
217
+ end
218
+
219
+ # Return the next higher item in the list.
220
+ def higher_item
221
+ return nil unless in_list?
222
+ acts_as_list_class.find(:first, :conditions =>
223
+ "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
224
+ )
225
+ end
226
+
227
+ # Return the next lower item in the list.
228
+ def lower_item
229
+ return nil unless in_list?
230
+ acts_as_list_class.find(:first, :conditions =>
231
+ "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
232
+ )
233
+ end
234
+
235
+ # Test if this record is in a list
236
+ def in_list?
237
+ !send(position_column).nil?
238
+ end
239
+
240
+ private
241
+ def add_to_list_top
242
+ increment_positions_on_all_items
243
+ end
244
+
245
+ def add_to_list_bottom
246
+ self[position_column] = bottom_position_in_list.to_i + 1
247
+ end
248
+
249
+ # Returns the bottom position number in the list.
250
+ # bottom_position_in_list # => 2
251
+ def bottom_position_in_list(except = nil)
252
+ item = bottom_item(except)
253
+ item ? item.send(position_column) : 0
254
+ end
255
+
256
+ # Returns the bottom item
257
+ def bottom_item(except = nil)
258
+ conditions = scope_condition
259
+ conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
260
+ acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC")
261
+ end
262
+
263
+ # Forces item to assume the bottom position in the list.
264
+ def assume_bottom_position
265
+ update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
266
+ end
267
+
268
+ # Forces item to assume the top position in the list.
269
+ def assume_top_position
270
+ update_attribute(position_column, 1)
271
+ end
272
+
273
+ # This has the effect of moving all the higher items up one.
274
+ def decrement_positions_on_higher_items(position)
275
+ acts_as_list_class.update_all(
276
+ "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
277
+ )
278
+ end
279
+
280
+ # This has the effect of moving all the lower items up one.
281
+ def decrement_positions_on_lower_items
282
+ return unless in_list?
283
+ acts_as_list_class.update_all(
284
+ "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
285
+ )
286
+ end
287
+
288
+ # This has the effect of moving all the higher items down one.
289
+ def increment_positions_on_higher_items
290
+ return unless in_list?
291
+ acts_as_list_class.update_all(
292
+ "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
293
+ )
294
+ end
295
+
296
+ # This has the effect of moving all the lower items down one.
297
+ def increment_positions_on_lower_items(position)
298
+ acts_as_list_class.update_all(
299
+ "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
300
+ )
301
+ end
302
+
303
+ # Increments position (<tt>position_column</tt>) of all items in the list.
304
+ def increment_positions_on_all_items
305
+ acts_as_list_class.update_all(
306
+ "#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
307
+ )
308
+ end
309
+
310
+ def insert_at_position(position)
311
+ remove_from_list
312
+ increment_positions_on_lower_items(position)
313
+ self.update_attribute(position_column, position)
314
+ end
315
+
316
+ end
317
+ end
318
+ end
319
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Coroutine
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-03-10 00:00:00 -06:00
18
+ date: 2010-03-25 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: activesupport
22
+ name: activerecord
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  requirements:
@@ -30,7 +30,19 @@ dependencies:
30
30
  version: "0"
31
31
  type: :runtime
32
32
  version_requirements: *id001
33
- description: This acts_as extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a position column defined as an integer on the mapped database table.
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ version_requirements: *id002
45
+ description: This acts_as extension does everything acts_as_list does, but it also works in single table inheritance designs and accepts less brain-damaged scope syntax.
34
46
  email: jdugan@coroutine.com
35
47
  executables: []
36
48
 
@@ -44,10 +56,10 @@ files:
44
56
  - README.rdoc
45
57
  - Rakefile
46
58
  - VERSION
47
- - acts_as_list_with_sti_support-0.1.0.gem
48
59
  - acts_as_list_with_sti_support.gemspec
49
60
  - init.rb
50
61
  - lib/acts_as_list_with_sti_support.rb
62
+ - lib/acts_as_list_with_sti_support/base.rb
51
63
  - test/acts_as_list_with_sti_support_test.rb
52
64
  - test/test_helper.rb
53
65
  has_rdoc: true