mongo_mapper_acts_as_list 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,44 @@
1
+ = mongo_mapper_acts_as_list
2
+
3
+ This is a port of classic Rails' {acts_as_list}[http://github.com/rails/acts_as_list] to Mongo Mapper. This MongoMapper plugin provides the capabilities for sorting and reordering a number of objects in a list. If you do not specify custom position column in the options, a key named position will be used by default.
4
+
5
+ It has (almost) the same functionality and passes the original test-suite. Scope needs to be defined as symbol or array of symbols. It does not work for Embedded Documents.
6
+
7
+ == Installation
8
+
9
+ mongo_mapper_acts_as_list is available as RubyGem:
10
+
11
+ gem install mongo_mapper_acts_as_list
12
+
13
+ == Example
14
+
15
+ class TodoList
16
+ include MongoMapper::Document
17
+
18
+ many :todo_items, :order => "position"
19
+ end
20
+
21
+ class TodoItem
22
+ include MongoMapper::Document
23
+ plugin MongoMapper::Plugins::ActsAsList
24
+
25
+ key :todo_list_id, ObjectId
26
+ belongs_to :todo_list
27
+
28
+ acts_as_list :scope => :todo_list_id
29
+ end
30
+
31
+ todo_list.first.move_to_bottom
32
+ todo_list.last.move_higher
33
+
34
+ == Note on Patches/Pull Requests
35
+
36
+ * Fork the project.
37
+ * Make your feature addition or bug fix.
38
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
39
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
40
+ * Send me a pull request. Bonus points for topic branches.
41
+
42
+ == Copyright
43
+
44
+ Original Rails' acts_as_list Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
@@ -0,0 +1,234 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module ActsAsList
4
+
5
+ require 'mongo_mapper'
6
+
7
+ module ClassMethods
8
+ def acts_as_list(options = {})
9
+ configuration = { :column => "position", :scope => {} }
10
+ configuration.update(options) if options.is_a?(Hash)
11
+
12
+ configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
13
+
14
+ if configuration[:scope].is_a?(Symbol)
15
+ scope_condition_method = %(
16
+ def scope_condition
17
+ { "#{configuration[:scope].to_s}" => send(:#{configuration[:scope].to_s}) }.symbolize_keys!
18
+ end
19
+ )
20
+ elsif configuration[:scope].is_a?(Array)
21
+ scope_condition_method = %(
22
+ def scope_condition
23
+ attrs = %w(#{configuration[:scope].join(" ")}).inject({}) do |memo, column|
24
+ memo[column.intern] = send(column.intern)
25
+ memo
26
+ end
27
+ attrs.symbolize_keys!
28
+ end
29
+ )
30
+ else
31
+ scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
32
+ end
33
+
34
+ class_eval <<-EOV
35
+ include MongoMapper::Plugins::ActsAsList::InstanceMethods
36
+
37
+ def acts_as_list_class
38
+ ::#{self.name}
39
+ end
40
+
41
+ def position_column
42
+ '#{configuration[:column]}'
43
+ end
44
+
45
+ #{scope_condition_method}
46
+
47
+ before_destroy :decrement_positions_on_lower_items
48
+ before_create :add_to_list_bottom
49
+ EOV
50
+ end
51
+
52
+ end
53
+
54
+
55
+
56
+ module InstanceMethods
57
+ # Insert the item at the given position (defaults to the top position of 1).
58
+ def insert_at(position = 1)
59
+ insert_at_position(position)
60
+ end
61
+
62
+ # Swap positions with the next lower item, if one exists.
63
+ def move_lower
64
+ return unless lower_item
65
+ lower_item.decrement_position
66
+ increment_position
67
+ end
68
+
69
+ # Swap positions with the next higher item, if one exists.
70
+ def move_higher
71
+ return unless higher_item
72
+ higher_item.increment_position
73
+ decrement_position
74
+ end
75
+
76
+ # Move to the bottom of the list. If the item is already in the list, the items below it have their
77
+ # position adjusted accordingly.
78
+ def move_to_bottom
79
+ return unless in_list?
80
+ decrement_positions_on_lower_items
81
+ assume_bottom_position
82
+ end
83
+
84
+ # Move to the top of the list. If the item is already in the list, the items above it have their
85
+ # position adjusted accordingly.
86
+ def move_to_top
87
+ return unless in_list?
88
+ increment_positions_on_higher_items
89
+ assume_top_position
90
+ end
91
+
92
+ def update_position(value=nil)
93
+ # update_attribute position_column, value
94
+ self.set( { position_column.to_sym => value } )
95
+ self[position_column] = value
96
+ end
97
+
98
+ # Removes the item from the list.
99
+ def remove_from_list
100
+ if in_list?
101
+ decrement_positions_on_lower_items
102
+ update_position( nil )
103
+ end
104
+ end
105
+
106
+ # Increase the position of this item without adjusting the rest of the list.
107
+ def increment_position
108
+ return unless in_list?
109
+ update_position( self.send(position_column).to_i+1 )
110
+ end
111
+
112
+ # Decrease the position of this item without adjusting the rest of the list.
113
+ def decrement_position
114
+ return unless in_list?
115
+ update_position( self.send(position_column).to_i-1 )
116
+ end
117
+
118
+ # Return +true+ if this object is the first in the list.
119
+ def first?
120
+ return false unless in_list?
121
+ self.send(position_column) == 1
122
+ end
123
+
124
+ # Return +true+ if this object is the last in the list.
125
+ def last?
126
+ return false unless in_list?
127
+ self.send(position_column) == bottom_position_in_list
128
+ end
129
+
130
+ # Return the next higher item in the list.
131
+ def higher_item
132
+ return nil unless in_list?
133
+ conditions = scope_condition
134
+ conditions.merge!( { position_column.to_sym => send(position_column).to_i-1 } )
135
+ acts_as_list_class.where(conditions).first
136
+ end
137
+
138
+ # Return the next lower item in the list.
139
+ def lower_item
140
+ return nil unless in_list?
141
+ conditions = scope_condition
142
+ conditions.merge!( { position_column.to_sym => send(position_column).to_i+1 } )
143
+ acts_as_list_class.where(conditions).first
144
+ end
145
+
146
+ # Test if this record is in a list
147
+ def in_list?
148
+ !send(position_column).nil?
149
+ end
150
+
151
+ private
152
+
153
+ def add_to_list_top
154
+ increment_positions_on_all_items
155
+ end
156
+
157
+ def add_to_list_bottom
158
+ self[position_column] = bottom_position_in_list.to_i+1
159
+ end
160
+
161
+ def scope_condition() "1" end
162
+
163
+ # Returns the bottom position number in the list.
164
+ # bottom_position_in_list # => 2
165
+ def bottom_position_in_list(except = nil)
166
+ item = bottom_item(except)
167
+ item ? item.send(position_column) : 0
168
+ end
169
+
170
+ # Returns the bottom item
171
+ def bottom_item(except = nil)
172
+ conditions = scope_condition
173
+ conditions.merge!( { :id.ne => except.id } ) if except
174
+ acts_as_list_class.where(conditions).sort(position_column.to_sym.desc).first
175
+ end
176
+
177
+ # Forces item to assume the bottom position in the list.
178
+ def assume_bottom_position
179
+ update_position( bottom_position_in_list(self).to_i+1 )
180
+ end
181
+
182
+ # Forces item to assume the top position in the list.
183
+ def assume_top_position
184
+ update_position 1
185
+ end
186
+
187
+ # This has the effect of moving all the higher items up one.
188
+ def decrement_positions_on_higher_items(position)
189
+ conditions = scope_condition
190
+ conditions.merge!( { position_column.to_sym.lt => position } )
191
+ acts_as_list_class.decrement( conditions, { position_column.to_sym => 1 } )
192
+ end
193
+
194
+ # This has the effect of moving all the lower items up one.
195
+ def decrement_positions_on_lower_items
196
+ return unless in_list?
197
+ conditions = scope_condition
198
+ conditions.merge!( { position_column.to_sym.gt => send(position_column).to_i } )
199
+ acts_as_list_class.decrement( conditions, { position_column => 1 } )
200
+ end
201
+
202
+ # This has the effect of moving all the higher items down one.
203
+ def increment_positions_on_higher_items
204
+ return unless in_list?
205
+ conditions = scope_condition
206
+ conditions.merge!( { position_column.to_sym.lt => send(position_column).to_i } )
207
+ acts_as_list_class.increment( conditions, { position_column.to_sym => 1 } )
208
+ end
209
+
210
+ # This has the effect of moving all the lower items down one.
211
+ def increment_positions_on_lower_items(position)
212
+ conditions = scope_condition
213
+ conditions.merge!( { position_column.to_sym.gte => position } )
214
+ acts_as_list_class.increment( conditions, { position_column.to_sym => 1 } )
215
+ end
216
+
217
+ # Increments position (<tt>position_column</tt>) of all items in the list.
218
+ def increment_positions_on_all_items
219
+ conditions = scope_condition
220
+ acts_as_list_class.increment( conditions, { position_column.to_sym => 1 } )
221
+ end
222
+
223
+ def insert_at_position(position)
224
+ remove_from_list
225
+ increment_positions_on_lower_items( position )
226
+ update_position( position )
227
+ end
228
+
229
+
230
+ end
231
+
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module ActsAsList
5
+ Version = '0.1'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,335 @@
1
+ require 'test_helper'
2
+
3
+
4
+
5
+ # CLASS SETUP
6
+
7
+ class ListMixin
8
+ include MongoMapper::Document
9
+
10
+ plugin MongoMapper::Plugins::ActsAsList
11
+
12
+ key :pos, Integer
13
+ key :parent_id, Integer
14
+ key :original_id, Integer
15
+
16
+ acts_as_list :column => :pos, :scope => :parent_id
17
+ end
18
+
19
+ class ListMixinSub1 < ListMixin
20
+ end
21
+
22
+ class ListMixinSub2 < ListMixin
23
+ end
24
+
25
+ class ListMixinWithArrayScope
26
+ include MongoMapper::Document
27
+
28
+ plugin MongoMapper::Plugins::ActsAsList
29
+
30
+ key :pos, Integer
31
+ key :parent_id, Integer
32
+
33
+ acts_as_list :column => :pos, :scope => [:parent_id, :original_id]
34
+ end
35
+
36
+
37
+
38
+ # TESTS
39
+
40
+ class ScopeTest < ActiveSupport::TestCase
41
+
42
+ def setup
43
+ @lm1 = ListMixin.create! :pos => 1, :parent_id => 5, :original_id => 1
44
+ @lm2 = ListMixinWithArrayScope.create! :pos => 1, :parent_id => 5, :original_id => 1
45
+ end
46
+
47
+ def test_symbol_scope
48
+ assert_equal @lm1.scope_condition, { :parent_id => 5 }
49
+ assert_equal @lm2.scope_condition, { :parent_id => 5, :original_id => 1 }
50
+ end
51
+
52
+ end
53
+
54
+
55
+
56
+ class ActiveSupport::TestCase
57
+
58
+ private
59
+
60
+ def mixins_with_parent_id(parent_id)
61
+ ListMixin.where(:parent_id => parent_id).sort(:pos).all.map(&:original_id)
62
+ end
63
+
64
+ def mixin_with_original_id(original_id)
65
+ ListMixin.where(:original_id => original_id).first
66
+ end
67
+ end
68
+
69
+
70
+
71
+ class ListTest < ActiveSupport::TestCase
72
+
73
+ def setup
74
+ (1..4).each{ |counter| ListMixin.create! :pos => counter, :parent_id => 5, :original_id => counter }
75
+ end
76
+
77
+ def test_reordering
78
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
79
+
80
+ mixin_with_original_id(2).move_lower
81
+ assert_equal [1, 3, 2, 4], mixins_with_parent_id(5)
82
+
83
+ mixin_with_original_id(2).move_higher
84
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
85
+
86
+ mixin_with_original_id(1).move_to_bottom
87
+ assert_equal [2, 3, 4, 1], mixins_with_parent_id(5)
88
+
89
+ mixin_with_original_id(1).move_to_top
90
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
91
+
92
+ mixin_with_original_id(2).move_to_bottom
93
+ assert_equal [1, 3, 4, 2], mixins_with_parent_id(5)
94
+
95
+ mixin_with_original_id(4).move_to_top
96
+ assert_equal [4, 1, 3, 2], mixins_with_parent_id(5)
97
+ end
98
+
99
+ def test_move_to_bottom_with_next_to_last_item
100
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
101
+ mixin_with_original_id(3).move_to_bottom
102
+ assert_equal [1, 2, 4, 3], mixins_with_parent_id(5)
103
+ end
104
+
105
+ def test_next_prev
106
+ assert_equal mixin_with_original_id(2), mixin_with_original_id(1).lower_item
107
+ assert_nil mixin_with_original_id(1).higher_item
108
+ assert_equal mixin_with_original_id(3), mixin_with_original_id(4).higher_item
109
+ assert_nil mixin_with_original_id(4).lower_item
110
+ end
111
+
112
+ def test_injection
113
+ item = ListMixin.new(:parent_id => 1)
114
+ assert_equal item.scope_condition, {:parent_id => 1}
115
+ assert_equal "pos", item.position_column
116
+ end
117
+
118
+ def test_insert
119
+ new = ListMixin.create(:parent_id => 20)
120
+ assert_equal 1, new.pos
121
+ assert new.first?
122
+ assert new.last?
123
+
124
+ new = ListMixin.create(:parent_id => 20)
125
+ assert_equal 2, new.pos
126
+ assert !new.first?
127
+ assert new.last?
128
+
129
+ new = ListMixin.create(:parent_id => 20)
130
+ assert_equal 3, new.pos
131
+ assert !new.first?
132
+ assert new.last?
133
+
134
+ new = ListMixin.create(:parent_id => 0)
135
+ assert_equal 1, new.pos
136
+ assert new.first?
137
+ assert new.last?
138
+ end
139
+
140
+ def test_insert_at
141
+ new = ListMixin.create(:parent_id => 20)
142
+ assert_equal 1, new.pos
143
+
144
+ new = ListMixin.create(:parent_id => 20)
145
+ assert_equal 2, new.pos
146
+
147
+ new = ListMixin.create(:parent_id => 20)
148
+ assert_equal 3, new.pos
149
+
150
+ new4 = ListMixin.create(:parent_id => 20)
151
+ assert_equal 4, new4.pos
152
+
153
+ new4.insert_at(3)
154
+ assert_equal 3, new4.pos
155
+
156
+ new.reload
157
+ assert_equal 4, new.pos
158
+
159
+ new.insert_at(2)
160
+ assert_equal 2, new.pos
161
+
162
+ new4.reload
163
+ assert_equal 4, new4.pos
164
+
165
+ new5 = ListMixin.create(:parent_id => 20)
166
+ assert_equal 5, new5.pos
167
+
168
+ new5.insert_at(1)
169
+ assert_equal 1, new5.pos
170
+
171
+ new4.reload
172
+ assert_equal 5, new4.pos
173
+ end
174
+
175
+ def test_delete_middle
176
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
177
+
178
+ mixin_with_original_id(2).destroy
179
+
180
+ assert_equal [1, 3, 4], mixins_with_parent_id(5)
181
+
182
+ assert_equal 1, mixin_with_original_id(1).pos
183
+ assert_equal 2, mixin_with_original_id(3).pos
184
+ assert_equal 3, mixin_with_original_id(4).pos
185
+
186
+ mixin_with_original_id(1).destroy
187
+
188
+ assert_equal [3, 4], mixins_with_parent_id(5)
189
+
190
+ assert_equal 1, mixin_with_original_id(3).pos
191
+ assert_equal 2, mixin_with_original_id(4).pos
192
+ end
193
+
194
+ def test_nil_scope
195
+ new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
196
+ new2.move_higher
197
+ assert_equal [new2, new1, new3], ListMixin.where(:parent_id => nil).sort(:pos).all
198
+ end
199
+
200
+ def test_remove_from_list_should_then_fail_in_list?
201
+ assert_equal true, mixin_with_original_id(1).in_list?
202
+ mixin_with_original_id(1).remove_from_list
203
+ assert_equal false, mixin_with_original_id(1).in_list?
204
+ end
205
+
206
+ def test_remove_from_list_should_set_position_to_nil
207
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
208
+
209
+ mixin_with_original_id(2).remove_from_list
210
+
211
+ assert_equal [2, 1, 3, 4], mixins_with_parent_id(5)
212
+
213
+ assert_equal 1, mixin_with_original_id(1).pos
214
+ assert_equal nil, mixin_with_original_id(2).pos
215
+ assert_equal 2, mixin_with_original_id(3).pos
216
+ assert_equal 3, mixin_with_original_id(4).pos
217
+ end
218
+
219
+ def test_remove_before_destroy_does_not_shift_lower_items_twice
220
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5)
221
+
222
+ mixin_with_original_id(2).remove_from_list
223
+ mixin_with_original_id(2).destroy
224
+
225
+ assert_equal [1, 3, 4], mixins_with_parent_id(5)
226
+
227
+ assert_equal 1, mixin_with_original_id(1).pos
228
+ assert_equal 2, mixin_with_original_id(3).pos
229
+ assert_equal 3, mixin_with_original_id(4).pos
230
+ end
231
+
232
+ end
233
+
234
+ class ListSubTest < ActiveSupport::TestCase
235
+
236
+ def setup
237
+ (1..4).each{ |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000, :original_id => i }
238
+ end
239
+
240
+ def test_reordering
241
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5000)
242
+
243
+ mixin_with_original_id(2).move_lower
244
+ assert_equal [1, 3, 2, 4], mixins_with_parent_id(5000)
245
+
246
+ mixin_with_original_id(2).move_higher
247
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5000)
248
+
249
+ mixin_with_original_id(1).move_to_bottom
250
+ assert_equal [2, 3, 4, 1], mixins_with_parent_id(5000)
251
+
252
+ mixin_with_original_id(1).move_to_top
253
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5000)
254
+
255
+ mixin_with_original_id(2).move_to_bottom
256
+ assert_equal [1, 3, 4, 2], mixins_with_parent_id(5000)
257
+
258
+ mixin_with_original_id(4).move_to_top
259
+ assert_equal [4, 1, 3, 2], mixins_with_parent_id(5000)
260
+ end
261
+
262
+ def test_move_to_bottom_with_next_to_last_item
263
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5000)
264
+ mixin_with_original_id(3).move_to_bottom
265
+ assert_equal [1, 2, 4, 3], mixins_with_parent_id(5000)
266
+ end
267
+
268
+ def test_next_prev
269
+ assert_equal mixin_with_original_id(2), mixin_with_original_id(1).lower_item
270
+ assert_nil mixin_with_original_id(1).higher_item
271
+ assert_equal mixin_with_original_id(3), mixin_with_original_id(4).higher_item
272
+ assert_nil mixin_with_original_id(4).lower_item
273
+ end
274
+
275
+ def test_injection
276
+ item = ListMixin.new(:parent_id => 1)
277
+ assert_equal item.scope_condition, { :parent_id => 1 }
278
+ assert_equal "pos", item.position_column
279
+ end
280
+
281
+ def test_insert_at
282
+ new = ListMixin.create(:parent_id => 20)
283
+ assert_equal 1, new.pos
284
+
285
+ new = ListMixinSub1.create(:parent_id => 20)
286
+ assert_equal 2, new.pos
287
+
288
+ new = ListMixinSub2.create(:parent_id => 20)
289
+ assert_equal 3, new.pos
290
+
291
+ new4 = ListMixin.create(:parent_id => 20)
292
+ assert_equal 4, new4.pos
293
+
294
+ new4.insert_at(3)
295
+ assert_equal 3, new4.pos
296
+
297
+ new.reload
298
+ assert_equal 4, new.pos
299
+
300
+ new.insert_at(2)
301
+ assert_equal 2, new.pos
302
+
303
+ new4.reload
304
+ assert_equal 4, new4.pos
305
+
306
+ new5 = ListMixinSub1.create(:parent_id => 20)
307
+ assert_equal 5, new5.pos
308
+
309
+ new5.insert_at(1)
310
+ assert_equal 1, new5.pos
311
+
312
+ new4.reload
313
+ assert_equal 5, new4.pos
314
+ end
315
+
316
+ def test_delete_middle
317
+ assert_equal [1, 2, 3, 4], mixins_with_parent_id(5000)
318
+
319
+ mixin_with_original_id(2).destroy
320
+
321
+ assert_equal [1, 3, 4], mixins_with_parent_id(5000)
322
+
323
+ assert_equal 1, mixin_with_original_id(1).pos
324
+ assert_equal 2, mixin_with_original_id(3).pos
325
+ assert_equal 3, mixin_with_original_id(4).pos
326
+
327
+ mixin_with_original_id(1).destroy
328
+
329
+ assert_equal [3, 4], mixins_with_parent_id(5000)
330
+
331
+ assert_equal 1, mixin_with_original_id(3).pos
332
+ assert_equal 2, mixin_with_original_id(4).pos
333
+ end
334
+
335
+ end
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'mongo_mapper'
5
+ require 'mongo_mapper/plugins/acts_as_list'
6
+ require 'test/unit'
7
+
8
+
9
+
10
+ class ActiveSupport::TestCase
11
+
12
+ # Drop all collections after each test case.
13
+ def teardown
14
+ MongoMapper.database.collections.each { |coll| coll.remove }
15
+ end
16
+
17
+ # Make sure that each test case has a teardown
18
+ # method to clear the db after each test.
19
+ def inherited(base)
20
+ base.define_method teardown do
21
+ super
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+
28
+
29
+ MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017)
30
+ MongoMapper.database = "mongo_mapper_acts_as_list_test"
31
+ MongoMapper.database.collections.each { |c| c.drop_indexes }
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongo_mapper_acts_as_list
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Tomas Celizna
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-31 01:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: mongo_mapper
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ description:
49
+ email:
50
+ - tomas.celizna@gmail.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - lib/mongo_mapper/plugins/acts_as_list.rb
59
+ - lib/mongo_mapper/plugins/version.rb
60
+ - test/mongo_mapper_acts_as_list_test.rb
61
+ - test/test_helper.rb
62
+ - README.rdoc
63
+ has_rdoc: true
64
+ homepage: http://github.com/tomasc/mongo_mapper_acts_as_list
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.7
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Port of classic Rails ActsAsList for MongoMapper
97
+ test_files: []
98
+