acts_as_positioned 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.
- checksums.yaml +7 -0
- data/README.md +144 -0
- data/Rakefile +7 -0
- data/lib/acts_as_positioned.rb +89 -0
- data/test/lib/acts_as_positioned_test.rb +179 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 83b94938abcb3a029732e108e86d077e46d60674
|
4
|
+
data.tar.gz: 445a9a8fd77994dca9df179e796f3208397bd1b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 949f19c613d45803c816678b6b6f3dcc00ddf1f67f47b533c4d9e0443285970c41f5f90330e9fbb1f61c3cd7a546354d3bda2859e58bb8b43858ea5a45d3eaa7
|
7
|
+
data.tar.gz: 847050cd223261db55862b04d71113975ddc7057f70a8bc0b0e94e5ec4a3482ba9e62995267189a430dcc5f8dd370544c62d1e9926cd94c5bbeaa1535499d560
|
data/README.md
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# ActsAsPositioned (for ActiveRecord 3 or higher)
|
2
|
+
|
3
|
+
This gem allows you to have ordered models. It is like the old *acts_as_list*
|
4
|
+
gem, but very lightweight and with an optimized SQL syntax.
|
5
|
+
|
6
|
+
Suppose you want to order a Post model by position. You need to add a
|
7
|
+
`position` column to the table *posts* first.
|
8
|
+
|
9
|
+
class CreatePost < ActiveRecord::Migration
|
10
|
+
def change
|
11
|
+
create_table(:posts) do |t|
|
12
|
+
...
|
13
|
+
t.integer(:position, null: false)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
You can make the `position` column optional: only records with entered
|
19
|
+
positions will be ordered. In rare cases, you can also add extra order columns.
|
20
|
+
|
21
|
+
To add ordering to a model, do the following:
|
22
|
+
|
23
|
+
class Post < ActiveRecord::Base
|
24
|
+
acts_as_positioned
|
25
|
+
end
|
26
|
+
|
27
|
+
You can also order within the scope of other columns, which is useful for
|
28
|
+
things like associations:
|
29
|
+
|
30
|
+
class Detail < ActiveRecord::Base
|
31
|
+
belongs_to(:post)
|
32
|
+
acts_as_positioned(scope: :post_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
This means the order positions are unique within the scope of `post_id`.
|
36
|
+
|
37
|
+
# Examples
|
38
|
+
|
39
|
+
Check out the tests (in `test/lib/acts_as_positioned.rb`) to see more
|
40
|
+
examples.
|
41
|
+
|
42
|
+
Suppose you have these records (for all examples this is the starting point):
|
43
|
+
|
44
|
+
id | position
|
45
|
+
---+---------
|
46
|
+
1 | 0
|
47
|
+
2 | 1
|
48
|
+
3 | 2
|
49
|
+
|
50
|
+
## Insert a new record at position 1
|
51
|
+
|
52
|
+
The existing records with position greater than or equal to 1 will have their
|
53
|
+
position increased by 1 and the new record (with id 4) is inserted:
|
54
|
+
|
55
|
+
Post.create(position: 2)
|
56
|
+
|
57
|
+
id | position
|
58
|
+
---+---------
|
59
|
+
1 | 0
|
60
|
+
2 | 2 # moved down
|
61
|
+
3 | 3 # moved down
|
62
|
+
4 | 1 # inserted
|
63
|
+
|
64
|
+
## Delete a record at position 1
|
65
|
+
|
66
|
+
The existing records with position greater than or equal to 1 will have their
|
67
|
+
position decreased by 1 and the record (with id 2) is deleted:
|
68
|
+
|
69
|
+
Post.find(2).destroy
|
70
|
+
|
71
|
+
id | position
|
72
|
+
---+---------
|
73
|
+
1 | 0
|
74
|
+
# deleted
|
75
|
+
3 | 1 # moved up
|
76
|
+
|
77
|
+
## Move a record down from position 0 to position 1
|
78
|
+
|
79
|
+
The existing record with position equal to 1 will have its position decreased
|
80
|
+
by 1 and the record (with id 1) is moved down:
|
81
|
+
|
82
|
+
Post.find(1).update(position: 1)
|
83
|
+
|
84
|
+
id | position
|
85
|
+
---+---------
|
86
|
+
1 | 1 # moved down
|
87
|
+
2 | 0 # moved up
|
88
|
+
3 | 2
|
89
|
+
|
90
|
+
## Move a record up from position 2 to position 0
|
91
|
+
|
92
|
+
The existing records with position greater than or equal to 0 and less than or
|
93
|
+
equal to 1 will have their position increased by 1 and the record (with id 3)
|
94
|
+
is moved up:
|
95
|
+
|
96
|
+
Post.find(3).update(position: 0)
|
97
|
+
|
98
|
+
id | position
|
99
|
+
---+---------
|
100
|
+
1 | 1 # moved down
|
101
|
+
2 | 2 # moved down
|
102
|
+
3 | 0 # moved up
|
103
|
+
|
104
|
+
## Insert a new record at position 4
|
105
|
+
|
106
|
+
This would create a gap in the positions and is not allowed.
|
107
|
+
|
108
|
+
Post.create(position: 4)
|
109
|
+
|
110
|
+
id | position
|
111
|
+
---+---------
|
112
|
+
1 | 0
|
113
|
+
2 | 1
|
114
|
+
3 | 2
|
115
|
+
4 | 4 # invalid (thus not saved)
|
116
|
+
|
117
|
+
## Insert a new record with an empty position
|
118
|
+
|
119
|
+
This will not affect the other records.
|
120
|
+
|
121
|
+
Post.create(position: nil)
|
122
|
+
|
123
|
+
id | position
|
124
|
+
---+---------
|
125
|
+
1 | 0
|
126
|
+
2 | 1
|
127
|
+
3 | 2
|
128
|
+
4 | nil # inserted, but without position
|
129
|
+
|
130
|
+
## Clear a record's position
|
131
|
+
|
132
|
+
Clearing a record's position, is like deleting its position.
|
133
|
+
|
134
|
+
Post.find(1).update(position: nil)
|
135
|
+
|
136
|
+
id | position
|
137
|
+
---+---------
|
138
|
+
1 | nil
|
139
|
+
2 | 0 # moved up
|
140
|
+
3 | 1 # moved up
|
141
|
+
|
142
|
+
# Copyright
|
143
|
+
|
144
|
+
© 2017 Walter Horstman, [IT on Rails](http://itonrails.com)
|
data/Rakefile
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# This module allow models to be positioned (order on a specific column). See the README file for more information.
|
2
|
+
module ActsAsPositioned
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
# Class methods that will be added to the base class (the class mixing in this module).
|
8
|
+
module ClassMethods
|
9
|
+
def acts_as_positioned(options = {})
|
10
|
+
column = options[:column] || :position
|
11
|
+
scope_columns = Array.wrap(options[:scope])
|
12
|
+
|
13
|
+
after_validation do
|
14
|
+
acts_as_positioned_validation(column, scope_columns)
|
15
|
+
end
|
16
|
+
|
17
|
+
before_create do
|
18
|
+
acts_as_positioned_create(column, scope_columns)
|
19
|
+
end
|
20
|
+
|
21
|
+
before_destroy do
|
22
|
+
acts_as_positioned_destroy(column, scope_columns)
|
23
|
+
end
|
24
|
+
|
25
|
+
before_update do
|
26
|
+
acts_as_positioned_update(column, scope_columns)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def acts_as_positioned_create(column, scope_columns)
|
34
|
+
scope = acts_as_positioned_scope(column, scope_columns)
|
35
|
+
scope.where(scope.arel_table[column].gteq(send(column))).update_all("#{column} = #{column} + 1")
|
36
|
+
end
|
37
|
+
|
38
|
+
def acts_as_positioned_destroy(column, scope_columns)
|
39
|
+
scope = acts_as_positioned_scope(column, scope_columns, true)
|
40
|
+
scope.where(scope.arel_table[column].gt(send("#{column}_was"))).update_all("#{column} = #{column} - 1")
|
41
|
+
end
|
42
|
+
|
43
|
+
def acts_as_positioned_scope(column, scope_columns, use_old_values = false)
|
44
|
+
scope_columns.reduce(self.class.base_class.where.not(column => nil)) do |scope, scope_column|
|
45
|
+
scope.where(scope_column => use_old_values ? send("#{scope_column}_was") : send(scope_column))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def acts_as_positioned_update(column, scope_columns)
|
50
|
+
if scope_columns.any? { |scope_column| send("#{scope_column}_changed?") }
|
51
|
+
acts_as_positioned_create(column, scope_columns)
|
52
|
+
acts_as_positioned_destroy(column, scope_columns)
|
53
|
+
|
54
|
+
elsif send(:"#{column}_changed?")
|
55
|
+
old_value, new_value = send("#{column}_change")
|
56
|
+
|
57
|
+
# If the new position becomes nil (and thus the old position wasn't), it should destroy a position.
|
58
|
+
if new_value.nil?
|
59
|
+
acts_as_positioned_destroy(column, scope_columns)
|
60
|
+
|
61
|
+
# If the old position was nil (and thus the new position isn't), it should insert a position.
|
62
|
+
elsif old_value.nil?
|
63
|
+
acts_as_positioned_create(column, scope_columns)
|
64
|
+
|
65
|
+
else
|
66
|
+
from, to, sign = old_value < new_value ? [old_value + 1, new_value, '-'] : [new_value, old_value - 1, '+']
|
67
|
+
|
68
|
+
acts_as_positioned_scope(column, scope_columns)
|
69
|
+
.where(column => from.eql?(to) ? from : from..to)
|
70
|
+
.update_all("#{column} = #{column} #{sign} 1")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def acts_as_positioned_validation(column, scope_columns)
|
76
|
+
return if errors[column].any?
|
77
|
+
|
78
|
+
scope = acts_as_positioned_scope(column, scope_columns)
|
79
|
+
scope = scope.where(scope.arel_table[scope.primary_key].not_eq(id)) unless new_record?
|
80
|
+
options = { attributes: column, allow_nil: true, only_integer: true, greater_than_or_equal_to: 0,
|
81
|
+
less_than_or_equal_to: (scope.maximum(column) || -1) + 1 }
|
82
|
+
|
83
|
+
ActiveModel::Validations::NumericalityValidator.new(options).validate(self)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
ActiveSupport.on_load(:active_record) do
|
88
|
+
include(ActsAsPositioned)
|
89
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require('active_record')
|
2
|
+
require('minitest')
|
3
|
+
require('minitest/autorun')
|
4
|
+
require('acts_as_positioned')
|
5
|
+
|
6
|
+
# Test by running: ruby -Ilib test/lib/acts_as_positioned_test.rb
|
7
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: File.dirname(__FILE__) + '/../test.sqlite3')
|
8
|
+
|
9
|
+
# Create "posts" table.
|
10
|
+
ActiveRecord::Schema.define do
|
11
|
+
create_table(:posts, force: true) do |t|
|
12
|
+
t.string(:text, null: false)
|
13
|
+
t.integer(:position)
|
14
|
+
t.integer(:author_id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create "animals" table.
|
19
|
+
ActiveRecord::Schema.define do
|
20
|
+
create_table(:animals, force: true) do |t|
|
21
|
+
t.string(:type, null: false)
|
22
|
+
t.string(:sound, null: false)
|
23
|
+
t.integer(:ordering)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Post < ActiveRecord::Base
|
28
|
+
acts_as_positioned
|
29
|
+
end
|
30
|
+
|
31
|
+
class PostWithScope < ActiveRecord::Base
|
32
|
+
self.table_name = 'posts'
|
33
|
+
acts_as_positioned(scope: :author_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
class Animal < ActiveRecord::Base
|
37
|
+
acts_as_positioned(column: :ordering)
|
38
|
+
end
|
39
|
+
|
40
|
+
class Cat < Animal
|
41
|
+
end
|
42
|
+
|
43
|
+
class Dog < Animal
|
44
|
+
end
|
45
|
+
|
46
|
+
class ActsAsPositionedTest < Minitest::Test
|
47
|
+
def setup
|
48
|
+
Post.delete_all
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_insert_record
|
52
|
+
post1 = Post.create(text: '1st post', position: 0)
|
53
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
54
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
55
|
+
post4 = Post.create(text: '4th post', position: 1)
|
56
|
+
assert_equal(post4.position, 1)
|
57
|
+
assert_equal(post1.reload.position, 0)
|
58
|
+
assert_equal(post2.reload.position, 2)
|
59
|
+
assert_equal(post3.reload.position, 3)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_delete_record
|
63
|
+
post1 = Post.create(text: '1st post', position: 0)
|
64
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
65
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
66
|
+
post2.destroy
|
67
|
+
assert_equal(post1.reload.position, 0)
|
68
|
+
assert_equal(post3.reload.position, 1)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_move_record_downwards
|
72
|
+
post1 = Post.create(text: '1st post', position: 0)
|
73
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
74
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
75
|
+
post1.update(position: 1)
|
76
|
+
assert_equal(post1.reload.position, 1)
|
77
|
+
assert_equal(post2.reload.position, 0)
|
78
|
+
assert_equal(post3.reload.position, 2)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_move_record_upwards
|
82
|
+
post1 = Post.create(text: '1st post', position: 0)
|
83
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
84
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
85
|
+
post3.update(position: 0)
|
86
|
+
assert_equal(post1.reload.position, 1)
|
87
|
+
assert_equal(post2.reload.position, 2)
|
88
|
+
assert_equal(post3.reload.position, 0)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_move_record_downwards_and_upwards
|
92
|
+
post1 = Post.create(text: '1st post', position: 0)
|
93
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
94
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
95
|
+
post1.update(position: 1)
|
96
|
+
post1.update(position: 0)
|
97
|
+
assert_equal(post1.reload.position, 0)
|
98
|
+
assert_equal(post2.reload.position, 1)
|
99
|
+
assert_equal(post3.reload.position, 2)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_insert_record_without_position_should_do_nothing
|
103
|
+
post1 = Post.create(text: '1st post', position: 0)
|
104
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
105
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
106
|
+
post4 = Post.create(text: '4th post')
|
107
|
+
assert_nil(post4.position)
|
108
|
+
assert_equal(post1.reload.position, 0)
|
109
|
+
assert_equal(post2.reload.position, 1)
|
110
|
+
assert_equal(post3.reload.position, 2)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_clear_position
|
114
|
+
post1 = Post.create(text: '1st post', position: 0)
|
115
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
116
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
117
|
+
post1.update(position: nil)
|
118
|
+
assert_equal(post2.reload.position, 0)
|
119
|
+
assert_equal(post3.reload.position, 1)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_fill_position
|
123
|
+
post1 = Post.create(text: '1st post', position: 0)
|
124
|
+
post2 = Post.create(text: '2nd post', position: 1)
|
125
|
+
post3 = Post.create(text: '3rd post', position: 2)
|
126
|
+
post4 = Post.create(text: '4th post')
|
127
|
+
assert_nil(post4.position)
|
128
|
+
assert_equal(post1.reload.position, 0)
|
129
|
+
assert_equal(post2.reload.position, 1)
|
130
|
+
assert_equal(post3.reload.position, 2)
|
131
|
+
|
132
|
+
post4.update(position: 1)
|
133
|
+
assert_equal(post4.position, 1)
|
134
|
+
assert_equal(post1.reload.position, 0)
|
135
|
+
assert_equal(post2.reload.position, 2)
|
136
|
+
assert_equal(post3.reload.position, 3)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_update_record_without_position_should_do_nothing
|
140
|
+
post = Post.create(text: 'Initial text', position: 0)
|
141
|
+
assert_equal(post.reload.position, 0)
|
142
|
+
post.update(text: 'Changed text')
|
143
|
+
assert_equal(post.reload.position, 0)
|
144
|
+
end
|
145
|
+
|
146
|
+
# First record that gets created, must have position 0.
|
147
|
+
def test_validation
|
148
|
+
post = Post.new(text: 'Post', position: 4)
|
149
|
+
assert_equal(post.valid?, false)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_insert_record_with_scope_column
|
153
|
+
post1 = PostWithScope.create(text: '1st post', position: 0)
|
154
|
+
post2 = PostWithScope.create(text: '1nd post for author 1', position: 0, author_id: 1)
|
155
|
+
post3 = PostWithScope.create(text: '2nd post for author 1', position: 1, author_id: 1)
|
156
|
+
post4 = PostWithScope.create(text: '3th post for author 1', position: 1, author_id: 1)
|
157
|
+
assert_equal(post4.position, 1)
|
158
|
+
assert_equal(post1.reload.position, 0)
|
159
|
+
assert_equal(post2.reload.position, 0)
|
160
|
+
assert_equal(post3.reload.position, 2)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_reposition_when_author_changes
|
164
|
+
post1 = PostWithScope.create(text: '1st post', position: 0)
|
165
|
+
post2 = PostWithScope.create(text: '1nd post for author 1', position: 0, author_id: 1)
|
166
|
+
post3 = PostWithScope.create(text: '2nd post for author 1', position: 1, author_id: 1)
|
167
|
+
post2.update(author_id: nil)
|
168
|
+
assert_equal(post2.position, 0)
|
169
|
+
assert_equal(post1.reload.position, 1)
|
170
|
+
assert_equal(post3.reload.position, 0)
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_single_table_inheritance
|
174
|
+
cat = Cat.create(sound: 'Miaow', ordering: 0)
|
175
|
+
dog = Dog.create(sound: 'Bark', ordering: 0)
|
176
|
+
assert_equal(dog.ordering, 0)
|
177
|
+
assert_equal(cat.reload.ordering, 1)
|
178
|
+
end
|
179
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_positioned
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Walter Horstman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: This gem allows you to have ordered models. It is like the old acts_as_list,
|
84
|
+
but very lightweight and with an optimized SQL syntax.
|
85
|
+
email:
|
86
|
+
- walter.horstman@itonrails.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- lib/acts_as_positioned.rb
|
94
|
+
- test/lib/acts_as_positioned_test.rb
|
95
|
+
homepage: http://github.com/walterhorstman/acts_as_positioned
|
96
|
+
licenses: []
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.5.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Lightweight ordering of models in ActiveRecord 3 or higher
|
118
|
+
test_files:
|
119
|
+
- test/lib/acts_as_positioned_test.rb
|