mongo_mapper_acts_as_list 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.
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
+