Skip to content
This repository
Browse code

Added higher_item and lower_item as public methods for acts_as_list #342

[Tobias Luetke]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@221 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 356f16006b44ee500db0fda0da055436ff41e37e 1 parent eeae1ee
David Heinemeier Hansson authored
2  activerecord/CHANGELOG
... ...
@@ -1,5 +1,7 @@
1 1
 *SVN*
2 2
 
  3
+* Added higher_item and lower_item as public methods for acts_as_list #342 [Tobias Luetke]
  4
+
3 5
 * Added respondence to *_before_type_cast for all attributes to return their string-state before they were type casted by the column type.
4 6
   This is helpful for getting "100,000" back on a integer-based validation where the value would normally be "100".
5 7
 
26  activerecord/lib/active_record/acts/list.rb
@@ -109,6 +109,18 @@ def first?
109 109
         def last?
110 110
           self.send(position_column) == bottom_position_in_list
111 111
         end
  112
+        
  113
+        def higher_item
  114
+          self.class.find_first(
  115
+            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
  116
+          )
  117
+        end
  118
+
  119
+        def lower_item
  120
+          self.class.find_first(
  121
+            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
  122
+          )
  123
+        end
112 124
 
113 125
         private
114 126
         
@@ -123,18 +135,6 @@ def add_to_list_bottom
123 135
         # Overwrite this method to define the scope of the list changes
124 136
         def scope_condition() "1" end
125 137
 
126  
-        def higher_item
127  
-          self.class.find_first(
128  
-            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
129  
-          )
130  
-        end
131  
-
132  
-        def lower_item
133  
-          self.class.find_first(
134  
-            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
135  
-          )
136  
-        end
137  
-
138 138
         def bottom_position_in_list
139 139
           item = bottom_item
140 140
           item ? item.send(position_column) : 0
@@ -163,7 +163,7 @@ def decrement_positions_on_lower_items
163 163
   
164 164
         def increment_positions_on_higher_items
165 165
           self.class.update_all(
166  
-            "#{position_column} = (#{position_column} + 1)",  "#{scope_condition} AND #{position_column} < #{send(position_column)}"
  166
+            "#{position_column} = (#{position_column} + 1)",  "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
167 167
           )
168 168
         end
169 169
 
7  activerecord/test/fixtures/db_definitions/mysql.sql
@@ -102,10 +102,11 @@ CREATE TABLE `mixins` (
102 102
   `id` int(11) NOT NULL auto_increment,
103 103
   `parent_id` int(11) default NULL,
104 104
   `pos` int(11) default NULL,
105  
-  `lft` int(11) default NULL,
106  
-  `rgt` int(11) default NULL,
107  
-  `root_id` int(11) default NULL,  
108 105
   `created_at` datetime default NULL,
109 106
   `updated_at` datetime default NULL,
  107
+  `lft` int(11) default NULL,
  108
+  `rgt` int(11) default NULL,
  109
+  `root_id` int(11) default NULL,
  110
+  `type` varchar(40) default NULL,
110 111
   PRIMARY KEY  (`id`)
111 112
 );
1  activerecord/test/fixtures/db_definitions/postgresql.sql
@@ -118,6 +118,7 @@ CREATE TABLE colnametests (
118 118
 CREATE TABLE mixins (
119 119
   id serial,
120 120
   parent_id integer,
  121
+  type character varying,  
121 122
   pos integer,
122 123
   lft integer,
123 124
   rgt integer,
1  activerecord/test/fixtures/db_definitions/sqlite.sql
@@ -90,6 +90,7 @@ CREATE TABLE 'colnametests' (
90 90
 CREATE TABLE 'mixins' (
91 91
   'id' INTEGER NOT NULL PRIMARY KEY,
92 92
   'parent_id' INTEGER DEFAULT NULL,
  93
+  'type' VARCHAR(40) DEFAULT NULL,  
93 94
   'pos' INTEGER DEFAULT NULL,
94 95
   'lft' INTEGER DEFAULT NULL,
95 96
   'rgt' INTEGER DEFAULT NULL,
1  activerecord/test/fixtures/db_definitions/sqlserver.sql
@@ -99,6 +99,7 @@ CREATE TABLE colnametests (
99 99
 CREATE TABLE mixins (
100 100
   id int NOT NULL IDENTITY(1, 1),
101 101
   parent_id int default NULL,
  102
+  type varchar(40) default NULL,  
102 103
   pos int default NULL,
103 104
   lft int default NULL,
104 105
   rgt int default NULL,
7  activerecord/test/fixtures/mixin.rb
... ...
@@ -1,9 +1,12 @@
1 1
 class Mixin < ActiveRecord::Base
2  
-  acts_as_tree :foreign_key => "parent_id", :order => "id"
3 2
 
4 3
 end
5 4
 
6  
-class ListMixin < ActiveRecord::Base
  5
+class TreeMixin < Mixin 
  6
+    acts_as_tree :foreign_key => "parent_id", :order => "id"
  7
+end
  8
+
  9
+class ListMixin < Mixin
7 10
   acts_as_list :column => "pos", :scope => :parent
8 11
 
9 12
   def self.table_name() "mixins" end
30  activerecord/test/fixtures/mixins.yml
... ...
@@ -1,14 +1,30 @@
1  
-first:
  1
+# tree mixins
  2
+tree_1:
2 3
   id: 1
3  
-  pos: 1
  4
+  type: TreeMixin
4 5
   parent_id: 0 
5 6
   
6  
-second:
  7
+tree_2:
7 8
   id: 2
8  
-  pos: 1
  9
+  type: TreeMixin
9 10
   parent_id: 1
10 11
 
11  
-third:
  12
+tree_3:
12 13
   id: 3
13  
-  pos: 2
14  
-  parent_id: 1
  14
+  type: TreeMixin  
  15
+  parent_id: 2
  16
+
  17
+tree_4:
  18
+  id: 4
  19
+  type: TreeMixin  
  20
+  parent_id: 1
  21
+  
  22
+# List mixins
  23
+
  24
+<% (1..4).each do |counter| %>  
  25
+list_<%= counter %>:
  26
+  id: <%= counter+6 %>
  27
+  pos: <%= counter  %>
  28
+  type: ListMixin
  29
+  parent_id: 5
  30
+<% end %>
206  activerecord/test/mixin_test.rb
@@ -3,72 +3,136 @@
3 3
 require 'active_record/acts/list'
4 4
 require 'fixtures/mixin'
5 5
 
6  
-
7 6
 class ListTest < Test::Unit::TestCase
8 7
   fixtures :mixins
9 8
   
10  
-  def test_injection
11  
-    l = ListMixin.new("parent_id"=>1)
12  
-    assert_equal "parent_id = 1", l.scope_condition
13  
-    assert_equal "pos", l.position_column
14  
-
15  
-  end
16  
-  
17 9
   def test_reordering
18 10
     
19  
-    assert_equal [ListMixin.find(2), ListMixin.find(3)], ListMixin.find_all("parent_id=1", "pos")
20  
-    
21  
-    ListMixin.find(2).move_lower
22  
-    
23  
-    assert_equal [ListMixin.find(3), ListMixin.find(2)], ListMixin.find_all("parent_id=1", "pos")
24  
-    
25  
-    ListMixin.find(2).move_higher
  11
+    assert_equal [@mixins['list_1'].find, 
  12
+                  @mixins['list_2'].find, 
  13
+                  @mixins['list_3'].find, 
  14
+                  @mixins['list_4'].find], 
  15
+                  ListMixin.find_all("parent_id=5", "pos")
  16
+                  
  17
+    @mixins['list_2'].find.move_lower
  18
+                  
  19
+    assert_equal [@mixins['list_1'].find, 
  20
+                  @mixins['list_3'].find, 
  21
+                  @mixins['list_2'].find, 
  22
+                  @mixins['list_4'].find], 
  23
+                  ListMixin.find_all("parent_id=5", "pos")                      
  24
+                  
  25
+    @mixins['list_2'].find.move_higher
26 26
 
27  
-    assert_equal [ListMixin.find(2), ListMixin.find(3)], ListMixin.find_all("parent_id=1", "pos")
  27
+    assert_equal [@mixins['list_1'].find, 
  28
+                  @mixins['list_2'].find, 
  29
+                  @mixins['list_3'].find, 
  30
+                  @mixins['list_4'].find], 
  31
+                  ListMixin.find_all("parent_id=5", "pos")
28 32
     
29  
-  end
  33
+    @mixins['list_1'].find.move_to_bottom
  34
+
  35
+    assert_equal [@mixins['list_2'].find, 
  36
+                  @mixins['list_3'].find, 
  37
+                  @mixins['list_4'].find, 
  38
+                  @mixins['list_1'].find], 
  39
+                  ListMixin.find_all("parent_id=5", "pos")
  40
+
  41
+    @mixins['list_1'].find.move_to_top
30 42
 
  43
+    assert_equal [@mixins['list_1'].find, 
  44
+                  @mixins['list_2'].find, 
  45
+                  @mixins['list_3'].find, 
  46
+                  @mixins['list_4'].find],
  47
+                  ListMixin.find_all("parent_id=5", "pos")
  48
+                  
  49
+                  
  50
+    @mixins['list_2'].find.move_to_bottom
  51
+  
  52
+    assert_equal [@mixins['list_1'].find, 
  53
+                  @mixins['list_3'].find, 
  54
+                  @mixins['list_4'].find, 
  55
+                  @mixins['list_2'].find],
  56
+                  ListMixin.find_all("parent_id=5", "pos")                  
  57
+
  58
+    @mixins['list_4'].find.move_to_top
  59
+
  60
+    assert_equal [@mixins['list_4'].find, 
  61
+                  @mixins['list_1'].find, 
  62
+                  @mixins['list_3'].find, 
  63
+                  @mixins['list_2'].find],
  64
+                  ListMixin.find_all("parent_id=5", "pos")                  
  65
+        
  66
+  end
  67
+  
  68
+  def test_next_prev
  69
+    assert_equal @list_2, @list_1.lower_item
  70
+    assert_nil @list_1.higher_item
  71
+    assert_equal @list_3, @list_4.higher_item
  72
+    assert_nil @list_4.lower_item
  73
+  end
  74
+  
  75
+  
  76
+  def test_injection
  77
+    item = ListMixin.new("parent_id"=>1)
  78
+    assert_equal "parent_id = 1", item.scope_condition
  79
+    assert_equal "pos", item.position_column
  80
+  end  
  81
+  
31 82
   def test_insert
32  
-    new = ListMixin.create("parent_id"=>5)
  83
+    new = ListMixin.create("parent_id"=>20)
33 84
     assert_equal 1, new.pos
34 85
     assert new.first?
35 86
     assert new.last?
36 87
 
37  
-    new = ListMixin.create("parent_id"=>5)
  88
+    new = ListMixin.create("parent_id"=>20)
38 89
     assert_equal 2, new.pos
39 90
     assert !new.first?
40 91
     assert new.last?
41 92
     
42  
-    new = ListMixin.create("parent_id"=>5)
  93
+    new = ListMixin.create("parent_id"=>20)
43 94
     assert_equal 3, new.pos    
44 95
     assert !new.first?
45 96
     assert new.last?
46 97
     
47  
-    new = ListMixin.create("parent_id"=>10)
  98
+    new = ListMixin.create("parent_id"=>0)
48 99
     assert_equal 1, new.pos
49 100
     assert new.first?
50 101
     assert new.last?
51 102
   end    
52 103
   
53 104
   def test_delete_middle
54  
-    first = ListMixin.create("parent_id"=>5)
55  
-    assert_equal 1, first.pos
56  
-
57  
-    second = ListMixin.create("parent_id"=>5)
58  
-    assert_equal 2, second.pos
59  
-    
60  
-    third = ListMixin.create("parent_id"=>5)
61  
-    assert_equal 3, third.pos    
62 105
     
63  
-    second.destroy
  106
+    assert_equal [@mixins['list_1'].find, 
  107
+                  @mixins['list_2'].find, 
  108
+                  @mixins['list_3'].find, 
  109
+                  @mixins['list_4'].find], 
  110
+                  ListMixin.find_all("parent_id=5", "pos")
  111
+              
  112
+    @mixins['list_2'].find.destroy
64 113
     
65  
-    assert_equal 1, @mixins["first"].find.pos
66  
-    assert_equal 2, @mixins["third"].find.pos
  114
+    assert_equal [@mixins['list_1'].find, 
  115
+                  @mixins['list_3'].find, 
  116
+                  @mixins['list_4'].find], 
  117
+                  ListMixin.find_all("parent_id=5", "pos")
  118
+                  
  119
+    assert_equal 1, @mixins['list_1'].find.pos
  120
+    assert_equal 2, @mixins['list_3'].find.pos
  121
+    assert_equal 3, @mixins['list_4'].find.pos
  122
+
  123
+    @mixins['list_1'].find.destroy
  124
+
  125
+    assert_equal [@mixins['list_3'].find, 
  126
+                  @mixins['list_4'].find], 
  127
+                  ListMixin.find_all("parent_id=5", "pos")
  128
+                  
  129
+    assert_equal 1, @mixins['list_3'].find.pos
  130
+    assert_equal 2, @mixins['list_4'].find.pos
67 131
     
68 132
   end  
69 133
 
70 134
   def test_with_string_based_scope
71  
-    new = ListWithStringScopeMixin.create("parent_id"=>5)
  135
+    new = ListWithStringScopeMixin.create("parent_id"=>500)
72 136
     assert_equal 1, new.pos
73 137
     assert new.first?
74 138
     assert new.last?
@@ -79,59 +143,89 @@ class TreeTest < Test::Unit::TestCase
79 143
   fixtures :mixins
80 144
   
81 145
   def test_has_child
82  
-    assert_equal true, @first.has_children?
83  
-    assert_equal false, @second.has_children?
84  
-    assert_equal false, @third.has_children?
  146
+    assert_equal true, @tree_1.has_children?
  147
+    assert_equal true, @tree_2.has_children?
  148
+    assert_equal false, @tree_3.has_children?
  149
+    assert_equal false, @tree_4.has_children?
85 150
   end
86 151
 
87 152
   def test_children
88  
-    assert_equal @first.children, [@second, @third]
89  
-    assert_equal @second.children, []
  153
+    assert_equal @tree_1.children, [@tree_2, @tree_4]
  154
+    assert_equal @tree_2.children, [@tree_3]
  155
+    assert_equal @tree_3.children, []
  156
+    assert_equal @tree_4.children, []
90 157
   end
91 158
 
92 159
   def test_parent
93  
-    assert_equal @second.parent, @first
94  
-    assert_equal @second.parent, @third.parent
95  
-    assert_nil @first.parent
  160
+    assert_equal @tree_2.parent, @tree_1
  161
+    assert_equal @tree_2.parent, @tree_4.parent
  162
+    assert_nil @tree_1.parent
  163
+  end
  164
+  
  165
+  def test_delete
  166
+    assert_equal 4, TreeMixin.count
  167
+    @tree_1.destroy
  168
+    assert_equal 0, TreeMixin.count
96 169
   end
97 170
   
98 171
   def test_insert
99  
-    @extra = @first.children.create
  172
+    @extra = @tree_1.children.create
100 173
     
101 174
     assert @extra
102 175
     
103  
-    assert_equal @extra.parent, @first
104  
-    assert_equal [@second, @third, @extra], @first.children
  176
+    assert_equal @extra.parent, @tree_1
  177
+    assert_equal [@tree_2, @tree_4, @extra], @tree_1.children
105 178
   end
106 179
   
107  
-  def test_delete
108  
-    assert_equal 3, Mixin.count
109  
-    @first.destroy
110  
-    assert_equal 0, Mixin.count
111  
-  end
  180
+
112 181
 end
113 182
 
114 183
 class TouchTest < Test::Unit::TestCase
115 184
   fixtures :mixins
116 185
   
117 186
   def test_update
118  
-    assert_nil @first.updated_at
119  
-    @first.save
120  
-    assert_not_nil @first.updated_at
  187
+    
  188
+    stamped = Mixin.new 
  189
+      
  190
+    assert_nil stamped.updated_at
  191
+    assert_nil stamped.created_at
  192
+    stamped.save
  193
+    assert_not_nil stamped.updated_at
  194
+    assert_not_nil stamped.created_at
121 195
   end  
122 196
 
123 197
   def test_create
124  
-    @obj = Mixin.create({"parent" => @third})
  198
+    @obj = Mixin.create
125 199
     assert_not_nil @obj.updated_at
126 200
     assert_not_nil @obj.created_at
127 201
   end  
  202
+
  203
+  def test_many_updates
  204
+
  205
+    stamped = Mixin.new 
  206
+
  207
+    assert_nil stamped.updated_at
  208
+    assert_nil stamped.created_at
  209
+    stamped.save
  210
+    assert_not_nil stamped.created_at
  211
+    assert_not_nil stamped.updated_at
  212
+    
  213
+    old_updated_at = stamped.updated_at
  214
+
  215
+    sleep 1
  216
+    stamped.save    
  217
+    assert_not_equal stamped.created_at, stamped.updated_at
  218
+    assert_not_equal old_updated_at, stamped.updated_at
  219
+
  220
+  end
  221
+
128 222
   
129 223
   def test_create_turned_off
130 224
     Mixin.record_timestamps = false
131 225
 
132  
-    assert_nil @first.updated_at
133  
-    @first.save
134  
-    assert_nil @first.updated_at
  226
+    assert_nil @tree_1.updated_at
  227
+    @tree_1.save
  228
+    assert_nil @tree_1.updated_at
135 229
 
136 230
     Mixin.record_timestamps = true
137 231
   end

0 notes on commit 356f160

Please sign in to comment.
Something went wrong with that request. Please try again.