mongoid_orderable 5.0.0 → 6.0.2
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 +5 -5
- data/CHANGELOG.md +83 -22
- data/LICENSE.txt +20 -0
- data/README.md +256 -149
- data/Rakefile +24 -6
- data/lib/config/locales/en.yml +12 -9
- data/lib/mongoid/orderable.rb +29 -22
- data/lib/mongoid/orderable/configs/field_config.rb +79 -0
- data/lib/mongoid/orderable/configs/global_config.rb +26 -0
- data/lib/mongoid/orderable/errors/invalid_target_position.rb +19 -18
- data/lib/mongoid/orderable/errors/transaction_failed.rb +20 -0
- data/lib/mongoid/orderable/generators/base.rb +21 -0
- data/lib/mongoid/orderable/generators/helpers.rb +29 -0
- data/lib/mongoid/orderable/generators/listable.rb +41 -0
- data/lib/mongoid/orderable/generators/lock_collection.rb +37 -0
- data/lib/mongoid/orderable/generators/movable.rb +62 -0
- data/lib/mongoid/orderable/generators/position.rb +26 -0
- data/lib/mongoid/orderable/generators/scope.rb +26 -0
- data/lib/mongoid/orderable/handlers/base.rb +167 -0
- data/lib/mongoid/orderable/handlers/document.rb +24 -0
- data/lib/mongoid/orderable/handlers/document_embedded.rb +14 -0
- data/lib/mongoid/orderable/handlers/document_transactional.rb +35 -0
- data/lib/mongoid/orderable/handlers/transaction.rb +71 -0
- data/lib/mongoid/orderable/installer.rb +63 -0
- data/lib/mongoid/orderable/mixins/callbacks.rb +43 -0
- data/lib/mongoid/orderable/mixins/helpers.rb +39 -0
- data/lib/mongoid/orderable/mixins/listable.rb +49 -0
- data/lib/mongoid/orderable/mixins/movable.rb +60 -0
- data/lib/mongoid/orderable/version.rb +7 -0
- data/lib/mongoid_orderable.rb +33 -54
- data/spec/integration/concurrency_spec.rb +232 -0
- data/spec/integration/customized_spec.rb +31 -0
- data/spec/integration/embedded_spec.rb +41 -0
- data/spec/integration/foreign_key_spec.rb +33 -0
- data/spec/integration/inherited_spec.rb +54 -0
- data/spec/integration/multiple_fields_spec.rb +554 -0
- data/spec/integration/multiple_scoped_spec.rb +63 -0
- data/spec/integration/no_indexed_spec.rb +23 -0
- data/spec/integration/scoped_spec.rb +151 -0
- data/spec/integration/simple_spec.rb +184 -0
- data/spec/integration/string_scoped_spec.rb +28 -0
- data/spec/integration/zero_based_spec.rb +161 -0
- data/spec/spec_helper.rb +42 -30
- data/spec/support/models.rb +122 -0
- metadata +75 -41
- data/.gitignore +0 -4
- data/.rspec +0 -2
- data/.rvmrc +0 -1
- data/.travis.yml +0 -14
- data/Gemfile +0 -18
- data/lib/mongoid/orderable/callbacks.rb +0 -75
- data/lib/mongoid/orderable/configuration.rb +0 -60
- data/lib/mongoid/orderable/errors.rb +0 -2
- data/lib/mongoid/orderable/errors/mongoid_orderable_error.rb +0 -14
- data/lib/mongoid/orderable/generator.rb +0 -34
- data/lib/mongoid/orderable/generator/helpers.rb +0 -29
- data/lib/mongoid/orderable/generator/listable.rb +0 -41
- data/lib/mongoid/orderable/generator/movable.rb +0 -62
- data/lib/mongoid/orderable/generator/position.rb +0 -26
- data/lib/mongoid/orderable/generator/scope.rb +0 -17
- data/lib/mongoid/orderable/helpers.rb +0 -50
- data/lib/mongoid/orderable/listable.rb +0 -49
- data/lib/mongoid/orderable/movable.rb +0 -58
- data/lib/mongoid/orderable/orderable_class.rb +0 -51
- data/lib/mongoid_orderable/mongoid/contexts/enumerable.rb +0 -15
- data/lib/mongoid_orderable/mongoid/contexts/mongo.rb +0 -18
- data/lib/mongoid_orderable/mongoid/contextual/memory.rb +0 -15
- data/lib/mongoid_orderable/mongoid/criteria.rb +0 -4
- data/lib/mongoid_orderable/version.rb +0 -3
- data/mongoid_orderable.gemspec +0 -26
- data/spec/mongoid/orderable_spec.rb +0 -1413
@@ -1,49 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Listable
|
4
|
-
|
5
|
-
##
|
6
|
-
# Returns items above the current document.
|
7
|
-
# Items with a position lower than this document's position.
|
8
|
-
def previous_items(column=nil)
|
9
|
-
column = column || default_orderable_column
|
10
|
-
orderable_scoped(column).where(orderable_column(column).lt => send(column))
|
11
|
-
end
|
12
|
-
alias_method :prev_items, :previous_items
|
13
|
-
|
14
|
-
##
|
15
|
-
# Returns items below the current document.
|
16
|
-
# Items with a position greater than this document's position.
|
17
|
-
def next_items(column=nil)
|
18
|
-
column = column || default_orderable_column
|
19
|
-
orderable_scoped(column).where(orderable_column(column).gt => send(column))
|
20
|
-
end
|
21
|
-
|
22
|
-
# returns the previous item in the list
|
23
|
-
def previous_item(column=nil)
|
24
|
-
column = column || default_orderable_column
|
25
|
-
orderable_scoped(column).where(orderable_column(column) => send(column) - 1).first
|
26
|
-
end
|
27
|
-
alias_method :prev_item, :previous_item
|
28
|
-
|
29
|
-
# returns the next item in the list
|
30
|
-
def next_item(column=nil)
|
31
|
-
column = column || default_orderable_column
|
32
|
-
orderable_scoped(column).where(orderable_column(column) => send(column) + 1).first
|
33
|
-
end
|
34
|
-
|
35
|
-
def first?(column=nil)
|
36
|
-
in_list?(column) && orderable_position(column) == orderable_base(column)
|
37
|
-
end
|
38
|
-
|
39
|
-
def last?(column=nil)
|
40
|
-
in_list?(column) && orderable_position(column) == bottom_orderable_position(column)
|
41
|
-
end
|
42
|
-
|
43
|
-
def in_list?(column=nil)
|
44
|
-
!orderable_position(column).nil?
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Movable
|
4
|
-
|
5
|
-
def move_to!(target_position, options={})
|
6
|
-
move_column_to target_position, options
|
7
|
-
save
|
8
|
-
end
|
9
|
-
alias_method :insert_at!, :move_to!
|
10
|
-
|
11
|
-
def move_to(target_position, options={})
|
12
|
-
move_column_to target_position, options
|
13
|
-
end
|
14
|
-
alias_method :insert_at, :move_to
|
15
|
-
|
16
|
-
def move_to=(target_position, options={})
|
17
|
-
move_column_to target_position, options
|
18
|
-
end
|
19
|
-
alias_method :insert_at=, :move_to=
|
20
|
-
|
21
|
-
[:top, :bottom].each do |symbol|
|
22
|
-
class_eval <<-eos
|
23
|
-
def move_to_#{symbol}(options = {})
|
24
|
-
move_to :#{symbol}, options
|
25
|
-
end
|
26
|
-
|
27
|
-
def move_to_#{symbol}!(options = {})
|
28
|
-
move_to! :#{symbol}, options
|
29
|
-
end
|
30
|
-
eos
|
31
|
-
end
|
32
|
-
|
33
|
-
[:higher, :lower].each do |symbol|
|
34
|
-
class_eval <<-eos
|
35
|
-
def move_#{symbol}(options = {})
|
36
|
-
move_to :#{symbol}, options
|
37
|
-
end
|
38
|
-
|
39
|
-
def move_#{symbol}!(options = {})
|
40
|
-
move_to! :#{symbol}, options
|
41
|
-
end
|
42
|
-
eos
|
43
|
-
end
|
44
|
-
|
45
|
-
protected
|
46
|
-
|
47
|
-
def move_all
|
48
|
-
@move_all || {}
|
49
|
-
end
|
50
|
-
|
51
|
-
def move_column_to(position, options)
|
52
|
-
column = options[:column] || default_orderable_column
|
53
|
-
@move_all = move_all.merge(column => position)
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
class OrderableClass
|
4
|
-
include Mongoid::Orderable::Generator
|
5
|
-
|
6
|
-
attr_reader :klass, :configuration
|
7
|
-
|
8
|
-
def initialize klass, configuration
|
9
|
-
@klass = klass
|
10
|
-
@configuration = configuration
|
11
|
-
end
|
12
|
-
|
13
|
-
def setup
|
14
|
-
add_db_field
|
15
|
-
add_db_index if configuration[:index]
|
16
|
-
save_configuration
|
17
|
-
generate_all_helpers
|
18
|
-
add_callbacks
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.setup(klass, configuration={})
|
22
|
-
new(klass, configuration).setup
|
23
|
-
end
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
|
-
def add_db_field
|
28
|
-
klass.field configuration[:column], configuration[:field_opts]
|
29
|
-
end
|
30
|
-
|
31
|
-
def add_db_index
|
32
|
-
spec = [[configuration[:column], 1]]
|
33
|
-
spec.unshift([configuration[:scope], 1]) if configuration[:scope].is_a?(Symbol)
|
34
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
35
|
-
klass.index(spec)
|
36
|
-
else
|
37
|
-
klass.index(Hash[spec])
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def save_configuration
|
42
|
-
klass.orderable_configurations ||= {}
|
43
|
-
klass.orderable_configurations = klass.orderable_configurations.merge(column_name => configuration)
|
44
|
-
end
|
45
|
-
|
46
|
-
def add_callbacks
|
47
|
-
klass.add_orderable_callbacks
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module MongoidOrderable #:nodoc:
|
2
|
-
module Mongoid #:nodoc:
|
3
|
-
module Contexts #:nodoc:
|
4
|
-
module Enumerable #:nodoc:
|
5
|
-
def inc attribute, value
|
6
|
-
iterate do |doc|
|
7
|
-
MongoidOrderable.inc doc, attribute, value
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Mongoid::Contexts::Enumerable.send :include, MongoidOrderable::Mongoid::Contexts::Enumerable
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module MongoidOrderable #:nodoc:
|
2
|
-
module Mongoid #:nodoc:
|
3
|
-
module Contexts #:nodoc:
|
4
|
-
module Mongo #:nodoc:
|
5
|
-
def inc attribute, value
|
6
|
-
klass.collection.update(
|
7
|
-
selector,
|
8
|
-
{ "$inc" => {attribute => value} },
|
9
|
-
:multi => true,
|
10
|
-
:safe => ::Mongoid.persist_in_safe_mode
|
11
|
-
)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
Mongoid::Contexts::Mongo.send :include, MongoidOrderable::Mongoid::Contexts::Mongo
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module MongoidOrderable #:nodoc:
|
2
|
-
module Mongoid #:nodoc:
|
3
|
-
module Contextual #:nodoc:
|
4
|
-
module Memory #:nodoc:
|
5
|
-
def inc(* args)
|
6
|
-
each do |document|
|
7
|
-
document.inc *args
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Mongoid::Contextual::Memory.send :include, MongoidOrderable::Mongoid::Contextual::Memory
|
data/mongoid_orderable.gemspec
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "mongoid_orderable/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "mongoid_orderable"
|
7
|
-
s.version = MongoidOrderable::VERSION
|
8
|
-
s.authors = ["pyromaniac"]
|
9
|
-
s.email = ["kinwizard@gmail.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{Acts as list mongoid implementation}
|
12
|
-
s.description = %q{Gem allows mongoid model behave as orderable list}
|
13
|
-
|
14
|
-
s.rubyforge_project = "mongoid_orderable"
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
# specify any dependencies here; for example:
|
22
|
-
s.add_development_dependency "rake"
|
23
|
-
s.add_development_dependency "rspec"
|
24
|
-
s.add_runtime_dependency "mongoid"
|
25
|
-
s.add_runtime_dependency "mongoid-compatibility"
|
26
|
-
end
|
@@ -1,1413 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mongoid::Orderable do
|
4
|
-
|
5
|
-
class SimpleOrderable
|
6
|
-
include Mongoid::Document
|
7
|
-
include Mongoid::Orderable
|
8
|
-
|
9
|
-
orderable
|
10
|
-
end
|
11
|
-
|
12
|
-
class ScopedGroup
|
13
|
-
include Mongoid::Document
|
14
|
-
|
15
|
-
has_many :scoped_orderables
|
16
|
-
has_many :multiple_columns_orderables
|
17
|
-
end
|
18
|
-
|
19
|
-
class ScopedOrderable
|
20
|
-
include Mongoid::Document
|
21
|
-
include Mongoid::Orderable
|
22
|
-
|
23
|
-
field :group_id
|
24
|
-
belongs_to :scoped_group
|
25
|
-
|
26
|
-
orderable :scope => :group
|
27
|
-
end
|
28
|
-
|
29
|
-
class StringScopedOrderable
|
30
|
-
include Mongoid::Document
|
31
|
-
include Mongoid::Orderable
|
32
|
-
|
33
|
-
field :some_scope, :type => Integer
|
34
|
-
|
35
|
-
orderable :scope => 'some_scope'
|
36
|
-
end
|
37
|
-
|
38
|
-
class EmbedsOrderable
|
39
|
-
include Mongoid::Document
|
40
|
-
|
41
|
-
embeds_many :embedded_orderables
|
42
|
-
end
|
43
|
-
|
44
|
-
class EmbeddedOrderable
|
45
|
-
include Mongoid::Document
|
46
|
-
include Mongoid::Orderable
|
47
|
-
|
48
|
-
embedded_in :embeds_orderable
|
49
|
-
|
50
|
-
orderable
|
51
|
-
end
|
52
|
-
|
53
|
-
class CustomizedOrderable
|
54
|
-
include Mongoid::Document
|
55
|
-
include Mongoid::Orderable
|
56
|
-
|
57
|
-
orderable :column => :pos, :as => :my_position
|
58
|
-
end
|
59
|
-
|
60
|
-
class NoIndexOrderable
|
61
|
-
include Mongoid::Document
|
62
|
-
include Mongoid::Orderable
|
63
|
-
|
64
|
-
orderable :index => false
|
65
|
-
end
|
66
|
-
|
67
|
-
class ZeroBasedOrderable
|
68
|
-
include Mongoid::Document
|
69
|
-
include Mongoid::Orderable
|
70
|
-
|
71
|
-
orderable :base => 0
|
72
|
-
end
|
73
|
-
|
74
|
-
class Fruit
|
75
|
-
include Mongoid::Document
|
76
|
-
include Mongoid::Orderable
|
77
|
-
|
78
|
-
orderable :inherited => true
|
79
|
-
end
|
80
|
-
|
81
|
-
class Apple < Fruit
|
82
|
-
end
|
83
|
-
|
84
|
-
class Orange < Fruit
|
85
|
-
end
|
86
|
-
|
87
|
-
class ForeignKeyDiffersOrderable
|
88
|
-
include Mongoid::Document
|
89
|
-
include Mongoid::Orderable
|
90
|
-
|
91
|
-
belongs_to :different_scope, :class_name => "ForeignKeyDiffersOrderable",
|
92
|
-
:foreign_key => "different_orderable_id"
|
93
|
-
|
94
|
-
orderable :scope => :different_scope
|
95
|
-
end
|
96
|
-
|
97
|
-
class MultipleColumnsOrderable
|
98
|
-
include Mongoid::Document
|
99
|
-
include Mongoid::Orderable
|
100
|
-
|
101
|
-
field :group_id
|
102
|
-
|
103
|
-
belongs_to :scoped_group
|
104
|
-
|
105
|
-
orderable :column => :pos, :base => 0, :index => false, :as => :position
|
106
|
-
orderable :column => :serial_no, :default => true
|
107
|
-
orderable :column => :groups, :scope => :group
|
108
|
-
end
|
109
|
-
|
110
|
-
class MultipleScopedOrderable
|
111
|
-
include Mongoid::Document
|
112
|
-
include Mongoid::Orderable
|
113
|
-
|
114
|
-
belongs_to :apple
|
115
|
-
belongs_to :orange
|
116
|
-
|
117
|
-
orderable :column => :posa, :scope => :apple_id
|
118
|
-
orderable :column => :poso, :scope => :orange_id
|
119
|
-
end
|
120
|
-
|
121
|
-
describe SimpleOrderable do
|
122
|
-
|
123
|
-
before :each do
|
124
|
-
SimpleOrderable.delete_all
|
125
|
-
5.times do
|
126
|
-
SimpleOrderable.create!
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def positions
|
131
|
-
SimpleOrderable.all.map(&:position).sort
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'should have proper position column' do
|
135
|
-
expect(SimpleOrderable.fields.key?('position')).to be true
|
136
|
-
expect(SimpleOrderable.fields['position'].options[:type]).to eq(Integer)
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'should have index on position column' do
|
140
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
141
|
-
expect(SimpleOrderable.index_options[[[:position, 1]]]).not_to be_nil
|
142
|
-
elsif ::Mongoid::Compatibility::Version.mongoid3?
|
143
|
-
expect(SimpleOrderable.index_options[{:position => 1}]).not_to be_nil
|
144
|
-
else
|
145
|
-
expect(SimpleOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).not_to be_nil
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'should have a orderable base of 1' do
|
150
|
-
expect(SimpleOrderable.create!.orderable_base).to eq(1)
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'should set proper position while creation' do
|
154
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
155
|
-
end
|
156
|
-
|
157
|
-
describe 'removement' do
|
158
|
-
|
159
|
-
it 'top' do
|
160
|
-
SimpleOrderable.where(:position => 1).destroy
|
161
|
-
expect(positions).to eq([1, 2, 3, 4])
|
162
|
-
end
|
163
|
-
|
164
|
-
it 'bottom' do
|
165
|
-
SimpleOrderable.where(:position => 5).destroy
|
166
|
-
expect(positions).to eq([1, 2, 3, 4])
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'middle' do
|
170
|
-
SimpleOrderable.where(:position => 3).destroy
|
171
|
-
expect(positions).to eq([1, 2, 3, 4])
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe 'inserting' do
|
176
|
-
|
177
|
-
it 'top' do
|
178
|
-
newbie = SimpleOrderable.create! :move_to => :top
|
179
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
180
|
-
expect(newbie.position).to eq(1)
|
181
|
-
end
|
182
|
-
|
183
|
-
it 'bottom' do
|
184
|
-
newbie = SimpleOrderable.create! :move_to => :bottom
|
185
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
186
|
-
expect(newbie.position).to eq(6)
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'middle' do
|
190
|
-
newbie = SimpleOrderable.create! :move_to => 4
|
191
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
192
|
-
expect(newbie.position).to eq(4)
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'middle (with a numeric string)' do
|
196
|
-
newbie = SimpleOrderable.create! :move_to => '4'
|
197
|
-
expect(positions).to eq([1, 2, 3, 4, 5, 6])
|
198
|
-
expect(newbie.position).to eq(4)
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'middle (with a non-numeric string)' do
|
202
|
-
expect do
|
203
|
-
SimpleOrderable.create! :move_to => 'four'
|
204
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
describe 'movement' do
|
209
|
-
|
210
|
-
it 'higher from top' do
|
211
|
-
record = SimpleOrderable.where(:position => 1).first
|
212
|
-
record.update_attributes :move_to => :higher
|
213
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
214
|
-
expect(record.reload.position).to eq(1)
|
215
|
-
end
|
216
|
-
|
217
|
-
it 'higher from bottom' do
|
218
|
-
record = SimpleOrderable.where(:position => 5).first
|
219
|
-
record.update_attributes :move_to => :higher
|
220
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
221
|
-
expect(record.reload.position).to eq(4)
|
222
|
-
end
|
223
|
-
|
224
|
-
it 'higher from middle' do
|
225
|
-
record = SimpleOrderable.where(:position => 3).first
|
226
|
-
record.update_attributes :move_to => :higher
|
227
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
228
|
-
expect(record.reload.position).to eq(2)
|
229
|
-
end
|
230
|
-
|
231
|
-
it 'lower from top' do
|
232
|
-
record = SimpleOrderable.where(:position => 1).first
|
233
|
-
record.update_attributes :move_to => :lower
|
234
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
235
|
-
expect(record.reload.position).to eq(2)
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'lower from bottom' do
|
239
|
-
record = SimpleOrderable.where(:position => 5).first
|
240
|
-
record.update_attributes :move_to => :lower
|
241
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
242
|
-
expect(record.reload.position).to eq(5)
|
243
|
-
end
|
244
|
-
|
245
|
-
it 'lower from middle' do
|
246
|
-
record = SimpleOrderable.where(:position => 3).first
|
247
|
-
record.update_attributes :move_to => :lower
|
248
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
249
|
-
expect(record.reload.position).to eq(4)
|
250
|
-
end
|
251
|
-
|
252
|
-
it 'does nothing if position not change' do
|
253
|
-
record = SimpleOrderable.where(:position => 3).first
|
254
|
-
record.save
|
255
|
-
expect(positions).to eq([1, 2, 3, 4, 5])
|
256
|
-
expect(record.reload.position).to eq(3)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
describe 'utiity methods' do
|
261
|
-
|
262
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
263
|
-
record_1 = SimpleOrderable.where(:position => 1).first
|
264
|
-
record_2 = SimpleOrderable.where(:position => 2).first
|
265
|
-
record_3 = SimpleOrderable.where(:position => 3).first
|
266
|
-
record_4 = SimpleOrderable.where(:position => 4).first
|
267
|
-
record_5 = SimpleOrderable.where(:position => 5).first
|
268
|
-
expect(record_1.next_items.to_a).to eq([record_2, record_3, record_4, record_5])
|
269
|
-
expect(record_5.previous_items.to_a).to eq([record_1, record_2, record_3, record_4])
|
270
|
-
expect(record_3.previous_items.to_a).to eq([record_1, record_2])
|
271
|
-
expect(record_3.next_items.to_a).to eq([record_4, record_5])
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
describe ScopedOrderable do
|
277
|
-
|
278
|
-
before :each do
|
279
|
-
ScopedOrderable.delete_all
|
280
|
-
2.times do
|
281
|
-
ScopedOrderable.create! :group_id => 1
|
282
|
-
end
|
283
|
-
3.times do
|
284
|
-
ScopedOrderable.create! :group_id => 2
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
def positions
|
289
|
-
ScopedOrderable.order_by([:group_id, :asc], [:position, :asc]).map(&:position)
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'should set proper position while creation' do
|
293
|
-
expect(positions).to eq([1, 2, 1, 2, 3])
|
294
|
-
end
|
295
|
-
|
296
|
-
describe 'removement' do
|
297
|
-
|
298
|
-
it 'top' do
|
299
|
-
ScopedOrderable.where(:position => 1, :group_id => 1).destroy
|
300
|
-
expect(positions).to eq([1, 1, 2, 3])
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'bottom' do
|
304
|
-
ScopedOrderable.where(:position => 3, :group_id => 2).destroy
|
305
|
-
expect(positions).to eq([1, 2, 1, 2])
|
306
|
-
end
|
307
|
-
|
308
|
-
it 'middle' do
|
309
|
-
ScopedOrderable.where(:position => 2, :group_id => 2).destroy
|
310
|
-
expect(positions).to eq([1, 2, 1, 2])
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
describe 'inserting' do
|
315
|
-
|
316
|
-
it 'top' do
|
317
|
-
newbie = ScopedOrderable.create! :move_to => :top, :group_id => 1
|
318
|
-
expect(positions).to eq([1, 2, 3, 1, 2, 3])
|
319
|
-
expect(newbie.position).to eq(1)
|
320
|
-
end
|
321
|
-
|
322
|
-
it 'bottom' do
|
323
|
-
newbie = ScopedOrderable.create! :move_to => :bottom, :group_id => 2
|
324
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
325
|
-
expect(newbie.position).to eq(4)
|
326
|
-
end
|
327
|
-
|
328
|
-
it 'middle' do
|
329
|
-
newbie = ScopedOrderable.create! :move_to => 2, :group_id => 2
|
330
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
331
|
-
expect(newbie.position).to eq(2)
|
332
|
-
end
|
333
|
-
|
334
|
-
it 'middle (with a numeric string)' do
|
335
|
-
newbie = ScopedOrderable.create! :move_to => '2', :group_id => 2
|
336
|
-
expect(positions).to eq([1, 2, 1, 2, 3, 4])
|
337
|
-
expect(newbie.position).to eq(2)
|
338
|
-
end
|
339
|
-
|
340
|
-
it 'middle (with a non-numeric string)' do
|
341
|
-
expect do
|
342
|
-
ScopedOrderable.create! :move_to => 'two', :group_id => 2
|
343
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
describe 'index' do
|
348
|
-
|
349
|
-
it 'is not on position alone' do
|
350
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
351
|
-
expect(ScopedOrderable.index_options[[[:position, 1]]]).to be_nil
|
352
|
-
elsif ::Mongoid::Compatibility::Version.mongoid3?
|
353
|
-
expect(ScopedOrderable.index_options[{:position => 1}]).to be_nil
|
354
|
-
else
|
355
|
-
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).to be_nil
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
it 'is on compound fields' do
|
360
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
361
|
-
expect(ScopedOrderable.index_options[[[:group_id, 1], [:position, 1]]]).to_not be_nil
|
362
|
-
elsif ::Mongoid::Compatibility::Version.mongoid3?
|
363
|
-
expect(ScopedOrderable.index_options[{:group_id => 1, :position => 1}]).to_not be_nil
|
364
|
-
else
|
365
|
-
expect(ScopedOrderable.index_specifications.detect { |spec| spec.key == {:group_id => 1, :position => 1} }).to_not be_nil
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
describe 'scope movement' do
|
371
|
-
|
372
|
-
let(:record){ ScopedOrderable.where(:group_id => 2, :position => 2).first }
|
373
|
-
|
374
|
-
it 'to a new scope group' do
|
375
|
-
record.update_attributes :group_id => 3
|
376
|
-
expect(positions).to eq([1, 2, 1, 2, 1])
|
377
|
-
expect(record.position).to eq(1)
|
378
|
-
end
|
379
|
-
|
380
|
-
context 'when moving to an existing scope group' do
|
381
|
-
|
382
|
-
it 'without a position' do
|
383
|
-
record.update_attributes :group_id => 1
|
384
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
385
|
-
expect(record.reload.position).to eq(3)
|
386
|
-
end
|
387
|
-
|
388
|
-
it 'with symbol position' do
|
389
|
-
record.update_attributes :group_id => 1, :move_to => :top
|
390
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
391
|
-
expect(record.reload.position).to eq(1)
|
392
|
-
end
|
393
|
-
|
394
|
-
it 'with point position' do
|
395
|
-
record.update_attributes :group_id => 1, :move_to => 2
|
396
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
397
|
-
expect(record.reload.position).to eq(2)
|
398
|
-
end
|
399
|
-
|
400
|
-
it 'with point position (with a numeric string)' do
|
401
|
-
record.update_attributes :group_id => 1, :move_to => '2'
|
402
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
403
|
-
expect(record.reload.position).to eq(2)
|
404
|
-
end
|
405
|
-
|
406
|
-
it 'with point position (with a non-numeric string)' do
|
407
|
-
expect do
|
408
|
-
record.update_attributes :group_id => 1, :move_to => 'two'
|
409
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
410
|
-
end
|
411
|
-
end
|
412
|
-
end
|
413
|
-
|
414
|
-
if defined?(Mongoid::IdentityMap)
|
415
|
-
|
416
|
-
context 'when identity map is enabled' do
|
417
|
-
|
418
|
-
let(:record){ ScopedOrderable.where(:group_id => 2, :position => 2).first }
|
419
|
-
|
420
|
-
before do
|
421
|
-
Mongoid.identity_map_enabled = true
|
422
|
-
Mongoid::IdentityMap[ScopedOrderable.collection_name] = { record.id => record }
|
423
|
-
end
|
424
|
-
|
425
|
-
after do
|
426
|
-
Mongoid.identity_map_enabled = false
|
427
|
-
end
|
428
|
-
|
429
|
-
it 'to a new scope group' do
|
430
|
-
record.update_attributes :group_id => 3
|
431
|
-
expect(positions).to eq([1, 2, 1, 2, 1])
|
432
|
-
expect(record.position).to eq(1)
|
433
|
-
end
|
434
|
-
|
435
|
-
it 'to an existing scope group' do
|
436
|
-
record.update_attributes :group_id => 1, :move_to => 2
|
437
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
438
|
-
expect(record.reload.position).to eq(2)
|
439
|
-
end
|
440
|
-
|
441
|
-
it 'to an existing scope group (with a numeric string)' do
|
442
|
-
record.update_attributes :group_id => 1, :move_to => '2'
|
443
|
-
expect(positions).to eq([1, 2, 3, 1, 2])
|
444
|
-
expect(record.reload.position).to eq(2)
|
445
|
-
end
|
446
|
-
|
447
|
-
it 'to an existing scope group (with a non-numeric string)' do
|
448
|
-
expect do
|
449
|
-
record.update_attributes :group_id => 1, :move_to => 'two'
|
450
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
451
|
-
end
|
452
|
-
end
|
453
|
-
end
|
454
|
-
|
455
|
-
describe 'utility methods' do
|
456
|
-
|
457
|
-
before do
|
458
|
-
ScopedOrderable.delete_all
|
459
|
-
5.times { ScopedOrderable.create! }
|
460
|
-
end
|
461
|
-
|
462
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
463
|
-
record_1 = ScopedOrderable.where(:position => 1).first
|
464
|
-
record_2 = ScopedOrderable.where(:position => 2).first
|
465
|
-
record_3 = ScopedOrderable.where(:position => 3).first
|
466
|
-
record_4 = ScopedOrderable.where(:position => 4).first
|
467
|
-
record_5 = ScopedOrderable.where(:position => 5).first
|
468
|
-
expect(record_1.next_items.to_a).to eq([record_2, record_3, record_4, record_5])
|
469
|
-
expect(record_5.previous_items.to_a).to eq([record_1, record_2, record_3, record_4])
|
470
|
-
expect(record_3.previous_items.to_a).to eq([record_1, record_2])
|
471
|
-
expect(record_3.next_items.to_a).to eq([record_4, record_5])
|
472
|
-
# next_item & previous_item testing
|
473
|
-
expect(record_1.next_item).to eq(record_2)
|
474
|
-
expect(record_2.previous_item).to eq(record_1)
|
475
|
-
expect(record_1.previous_item).to eq(nil)
|
476
|
-
expect(record_5.next_item).to eq(nil)
|
477
|
-
end
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
describe StringScopedOrderable do
|
482
|
-
|
483
|
-
it 'uses the foreign key of the relationship as scope' do
|
484
|
-
orderable1 = StringScopedOrderable.create!(:some_scope => 1)
|
485
|
-
orderable2 = StringScopedOrderable.create!(:some_scope => 1)
|
486
|
-
orderable3 = StringScopedOrderable.create!(:some_scope => 2)
|
487
|
-
expect(orderable1.position).to eq 1
|
488
|
-
expect(orderable2.position).to eq 2
|
489
|
-
expect(orderable3.position).to eq 1
|
490
|
-
end
|
491
|
-
end
|
492
|
-
|
493
|
-
describe EmbeddedOrderable do
|
494
|
-
|
495
|
-
before :each do
|
496
|
-
EmbedsOrderable.delete_all
|
497
|
-
eo = EmbedsOrderable.create!
|
498
|
-
2.times do
|
499
|
-
eo.embedded_orderables.create!
|
500
|
-
end
|
501
|
-
eo = EmbedsOrderable.create!
|
502
|
-
3.times do
|
503
|
-
eo.embedded_orderables.create!
|
504
|
-
end
|
505
|
-
end
|
506
|
-
|
507
|
-
def positions
|
508
|
-
EmbedsOrderable.order_by(:position => 1).all.map { |eo| eo.embedded_orderables.map(&:position).sort }
|
509
|
-
end
|
510
|
-
|
511
|
-
it 'sets proper position while creation' do
|
512
|
-
expect(positions).to eq([[1, 2], [1, 2, 3]])
|
513
|
-
end
|
514
|
-
|
515
|
-
it 'moves an item returned by a query to position' do
|
516
|
-
embedded_orderable_1 = EmbedsOrderable.first.embedded_orderables.where(:position => 1).first
|
517
|
-
embedded_orderable_2 = EmbedsOrderable.first.embedded_orderables.where(:position => 2).first
|
518
|
-
embedded_orderable_1.move_to! 2
|
519
|
-
expect(embedded_orderable_2.reload.position).to eq(1)
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
describe CustomizedOrderable do
|
524
|
-
|
525
|
-
it 'does not have default position field' do
|
526
|
-
expect(CustomizedOrderable.fields).not_to have_key('position')
|
527
|
-
end
|
528
|
-
|
529
|
-
it 'should have custom pos field' do
|
530
|
-
expect(CustomizedOrderable.fields).to have_key('pos')
|
531
|
-
end
|
532
|
-
|
533
|
-
it 'should have an alias my_position which points to pos field on Mongoid 3+' do
|
534
|
-
if CustomizedOrderable.respond_to?(:database_field_name)
|
535
|
-
expect(CustomizedOrderable.database_field_name('my_position')).to eq('pos')
|
536
|
-
end
|
537
|
-
end
|
538
|
-
end
|
539
|
-
|
540
|
-
describe NoIndexOrderable do
|
541
|
-
|
542
|
-
it 'should not have index on position column' do
|
543
|
-
if ::Mongoid::Compatibility::Version.mongoid2? || ::Mongoid::Compatibility::Version.mongoid3?
|
544
|
-
expect(NoIndexOrderable.index_options[[[:position, 1]]]).to be_nil
|
545
|
-
else
|
546
|
-
expect(NoIndexOrderable.index_specifications.detect { |spec| spec.key == :position }).to be_nil
|
547
|
-
end
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
|
-
describe ZeroBasedOrderable do
|
552
|
-
|
553
|
-
before :each do
|
554
|
-
ZeroBasedOrderable.delete_all
|
555
|
-
5.times do
|
556
|
-
ZeroBasedOrderable.create!
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
def positions
|
561
|
-
ZeroBasedOrderable.all.map(&:position).sort
|
562
|
-
end
|
563
|
-
|
564
|
-
it 'should have a orderable base of 0' do
|
565
|
-
expect(ZeroBasedOrderable.create!.orderable_base).to eq(0)
|
566
|
-
end
|
567
|
-
|
568
|
-
it 'should set proper position while creation' do
|
569
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
570
|
-
end
|
571
|
-
|
572
|
-
describe 'reset position' do
|
573
|
-
before{ ZeroBasedOrderable.update_all({:position => nil}) }
|
574
|
-
it 'should properly reset position' do
|
575
|
-
ZeroBasedOrderable.all.map(&:save)
|
576
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
577
|
-
end
|
578
|
-
end
|
579
|
-
|
580
|
-
describe 'removement' do
|
581
|
-
|
582
|
-
it 'top' do
|
583
|
-
ZeroBasedOrderable.where(:position => 0).destroy
|
584
|
-
expect(positions).to eq([0, 1, 2, 3])
|
585
|
-
end
|
586
|
-
|
587
|
-
it 'bottom' do
|
588
|
-
ZeroBasedOrderable.where(:position => 4).destroy
|
589
|
-
expect(positions).to eq([0, 1, 2, 3])
|
590
|
-
end
|
591
|
-
|
592
|
-
it 'middle' do
|
593
|
-
ZeroBasedOrderable.where(:position => 2).destroy
|
594
|
-
expect(positions).to eq([0, 1, 2, 3])
|
595
|
-
end
|
596
|
-
end
|
597
|
-
|
598
|
-
describe 'inserting' do
|
599
|
-
|
600
|
-
it 'top' do
|
601
|
-
newbie = ZeroBasedOrderable.create! :move_to => :top
|
602
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
603
|
-
expect(newbie.position).to eq(0)
|
604
|
-
end
|
605
|
-
|
606
|
-
it 'bottom' do
|
607
|
-
newbie = ZeroBasedOrderable.create! :move_to => :bottom
|
608
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
609
|
-
expect(newbie.position).to eq(5)
|
610
|
-
end
|
611
|
-
|
612
|
-
it 'middle' do
|
613
|
-
newbie = ZeroBasedOrderable.create! :move_to => 3
|
614
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
615
|
-
expect(newbie.position).to eq(3)
|
616
|
-
end
|
617
|
-
|
618
|
-
it 'middle (with a numeric string)' do
|
619
|
-
newbie = ZeroBasedOrderable.create! :move_to => '3'
|
620
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
621
|
-
expect(newbie.position).to eq(3)
|
622
|
-
end
|
623
|
-
|
624
|
-
it 'middle (with a non-numeric string)' do
|
625
|
-
expect do
|
626
|
-
ZeroBasedOrderable.create! :move_to => 'three'
|
627
|
-
end.to raise_error Mongoid::Orderable::Errors::InvalidTargetPosition
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
describe 'movement' do
|
632
|
-
|
633
|
-
it 'higher from top' do
|
634
|
-
record = ZeroBasedOrderable.where(:position => 0).first
|
635
|
-
record.update_attributes :move_to => :higher
|
636
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
637
|
-
expect(record.reload.position).to eq(0)
|
638
|
-
end
|
639
|
-
|
640
|
-
it 'higher from bottom' do
|
641
|
-
record = ZeroBasedOrderable.where(:position => 4).first
|
642
|
-
record.update_attributes :move_to => :higher
|
643
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
644
|
-
expect(record.reload.position).to eq(3)
|
645
|
-
end
|
646
|
-
|
647
|
-
it 'higher from middle' do
|
648
|
-
record = ZeroBasedOrderable.where(:position => 3).first
|
649
|
-
record.update_attributes :move_to => :higher
|
650
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
651
|
-
expect(record.reload.position).to eq(2)
|
652
|
-
end
|
653
|
-
|
654
|
-
it 'lower from top' do
|
655
|
-
record = ZeroBasedOrderable.where(:position => 0).first
|
656
|
-
record.update_attributes :move_to => :lower
|
657
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
658
|
-
expect(record.reload.position).to eq(1)
|
659
|
-
end
|
660
|
-
|
661
|
-
it 'lower from bottom' do
|
662
|
-
record = ZeroBasedOrderable.where(:position => 4).first
|
663
|
-
record.update_attributes :move_to => :lower
|
664
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
665
|
-
expect(record.reload.position).to eq(4)
|
666
|
-
end
|
667
|
-
|
668
|
-
it 'lower from middle' do
|
669
|
-
record = ZeroBasedOrderable.where(:position => 2).first
|
670
|
-
record.update_attributes :move_to => :lower
|
671
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
672
|
-
expect(record.reload.position).to eq(3)
|
673
|
-
end
|
674
|
-
|
675
|
-
it 'does nothing if position not change' do
|
676
|
-
record = ZeroBasedOrderable.where(:position => 3).first
|
677
|
-
record.save
|
678
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
679
|
-
expect(record.reload.position).to eq(3)
|
680
|
-
end
|
681
|
-
end
|
682
|
-
|
683
|
-
describe 'utiity methods' do
|
684
|
-
|
685
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
686
|
-
record_1 = SimpleOrderable.where(:position => 1).first
|
687
|
-
record_2 = SimpleOrderable.where(:position => 2).first
|
688
|
-
record_3 = SimpleOrderable.where(:position => 3).first
|
689
|
-
record_4 = SimpleOrderable.where(:position => 4).first
|
690
|
-
record_5 = SimpleOrderable.where(:position => 5).first
|
691
|
-
expect(record_1.next_items.to_a).to eq([record_2, record_3, record_4, record_5])
|
692
|
-
expect(record_5.previous_items.to_a).to eq([record_1, record_2, record_3, record_4])
|
693
|
-
expect(record_3.previous_items.to_a).to eq([record_1, record_2])
|
694
|
-
expect(record_3.next_items.to_a).to eq([record_4, record_5])
|
695
|
-
# next_item & previous_item testing
|
696
|
-
expect(record_1.next_item).to eq(record_2)
|
697
|
-
expect(record_2.previous_item).to eq(record_1)
|
698
|
-
expect(record_1.previous_item).to eq(nil)
|
699
|
-
expect(record_5.next_item).to eq(nil)
|
700
|
-
end
|
701
|
-
end
|
702
|
-
end
|
703
|
-
|
704
|
-
describe Fruit do
|
705
|
-
|
706
|
-
it 'should set proper position' do
|
707
|
-
fruit1 = Apple.create
|
708
|
-
fruit2 = Orange.create
|
709
|
-
expect(fruit1.position).to eq(1)
|
710
|
-
expect(fruit2.position).to eq(2)
|
711
|
-
end
|
712
|
-
|
713
|
-
describe 'movement' do
|
714
|
-
before :each do
|
715
|
-
Fruit.delete_all
|
716
|
-
5.times do
|
717
|
-
Apple.create!
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
it 'with symbol position' do
|
722
|
-
first_apple = Apple.asc(:_id).first
|
723
|
-
top_pos = first_apple.position
|
724
|
-
bottom_pos = Apple.asc(:_id).last.position
|
725
|
-
expect do
|
726
|
-
first_apple.move_to! :bottom
|
727
|
-
end.to change(first_apple, :position).from(top_pos).to bottom_pos
|
728
|
-
end
|
729
|
-
|
730
|
-
it 'with point position' do
|
731
|
-
first_apple = Apple.asc(:_id).first
|
732
|
-
top_pos = first_apple.position
|
733
|
-
bottom_pos = Apple.asc(:_id).last.position
|
734
|
-
expect do
|
735
|
-
first_apple.move_to! bottom_pos
|
736
|
-
end.to change(first_apple, :position).from(top_pos).to bottom_pos
|
737
|
-
end
|
738
|
-
end
|
739
|
-
|
740
|
-
describe 'add orderable configurations in inherited class' do
|
741
|
-
it 'does not affect the orderable configurations of parent class and sibling class' do
|
742
|
-
class Apple
|
743
|
-
orderable :column => :serial
|
744
|
-
end
|
745
|
-
expect(Fruit.orderable_configurations).not_to eq Apple.orderable_configurations
|
746
|
-
expect(Orange.orderable_configurations).not_to eq Apple.orderable_configurations
|
747
|
-
expect(Fruit.orderable_configurations).to eq Orange.orderable_configurations
|
748
|
-
end
|
749
|
-
end
|
750
|
-
end
|
751
|
-
|
752
|
-
describe ForeignKeyDiffersOrderable do
|
753
|
-
|
754
|
-
it 'uses the foreign key of the relationship as scope' do
|
755
|
-
orderable1, orderable2, orderable3 = nil
|
756
|
-
parent_scope1 = ForeignKeyDiffersOrderable.create
|
757
|
-
parent_scope2 = ForeignKeyDiffersOrderable.create
|
758
|
-
expect do
|
759
|
-
orderable1 = ForeignKeyDiffersOrderable.create!(:different_scope => parent_scope1)
|
760
|
-
orderable2 = ForeignKeyDiffersOrderable.create!(:different_scope => parent_scope1)
|
761
|
-
orderable3 = ForeignKeyDiffersOrderable.create!(:different_scope => parent_scope2)
|
762
|
-
end.to_not raise_error
|
763
|
-
expect(orderable1.position).to eq 1
|
764
|
-
expect(orderable2.position).to eq 2
|
765
|
-
expect(orderable3.position).to eq 1
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
describe MultipleColumnsOrderable do
|
770
|
-
|
771
|
-
before :each do
|
772
|
-
MultipleColumnsOrderable.delete_all
|
773
|
-
5.times do
|
774
|
-
MultipleColumnsOrderable.create!
|
775
|
-
end
|
776
|
-
end
|
777
|
-
|
778
|
-
context 'default orderable' do
|
779
|
-
let(:serial_nos){ MultipleColumnsOrderable.all.map(&:serial_no).sort }
|
780
|
-
|
781
|
-
describe 'inserting' do
|
782
|
-
let(:newbie){ MultipleColumnsOrderable.create! }
|
783
|
-
|
784
|
-
before { @position = newbie.position }
|
785
|
-
|
786
|
-
it 'top' do
|
787
|
-
newbie.move_to! :top
|
788
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
789
|
-
expect(newbie.serial_no).to eq(1)
|
790
|
-
expect(newbie.position).to eq(@position)
|
791
|
-
end
|
792
|
-
|
793
|
-
it 'bottom' do
|
794
|
-
newbie.move_to! :bottom
|
795
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
796
|
-
expect(newbie.serial_no).to eq(6)
|
797
|
-
expect(newbie.position).to eq(@position)
|
798
|
-
end
|
799
|
-
|
800
|
-
it 'middle' do
|
801
|
-
newbie.move_to! 4
|
802
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
803
|
-
expect(newbie.serial_no).to eq(4)
|
804
|
-
expect(newbie.position).to eq(@position)
|
805
|
-
end
|
806
|
-
end
|
807
|
-
|
808
|
-
describe 'movement' do
|
809
|
-
it 'higher from top' do
|
810
|
-
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
811
|
-
position = record.position
|
812
|
-
record.move_higher!
|
813
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
814
|
-
expect(record.serial_no).to eq(1)
|
815
|
-
expect(record.position).to eq(position)
|
816
|
-
end
|
817
|
-
|
818
|
-
it 'higher from bottom' do
|
819
|
-
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
820
|
-
position = record.position
|
821
|
-
record.move_higher!
|
822
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
823
|
-
expect(record.serial_no).to eq(4)
|
824
|
-
expect(record.position).to eq(position)
|
825
|
-
end
|
826
|
-
|
827
|
-
it 'higher from middle' do
|
828
|
-
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
829
|
-
position = record.position
|
830
|
-
record.move_higher!
|
831
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
832
|
-
expect(record.serial_no).to eq(2)
|
833
|
-
expect(record.position).to eq(position)
|
834
|
-
end
|
835
|
-
|
836
|
-
it 'lower from top' do
|
837
|
-
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
838
|
-
position = record.position
|
839
|
-
record.move_lower!
|
840
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
841
|
-
expect(record.serial_no).to eq(2)
|
842
|
-
expect(record.position).to eq(position)
|
843
|
-
end
|
844
|
-
|
845
|
-
it 'lower from bottom' do
|
846
|
-
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
847
|
-
position = record.position
|
848
|
-
record.move_lower!
|
849
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
850
|
-
expect(record.serial_no).to eq(5)
|
851
|
-
expect(record.position).to eq(position)
|
852
|
-
end
|
853
|
-
|
854
|
-
it 'lower from middle' do
|
855
|
-
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
856
|
-
position = record.position
|
857
|
-
record.move_lower!
|
858
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
859
|
-
expect(record.serial_no).to eq(4)
|
860
|
-
expect(record.position).to eq(position)
|
861
|
-
end
|
862
|
-
end
|
863
|
-
|
864
|
-
describe 'utility methods' do
|
865
|
-
|
866
|
-
before do
|
867
|
-
@record_1 = MultipleColumnsOrderable.where(:serial_no => 1).first
|
868
|
-
@record_2 = MultipleColumnsOrderable.where(:serial_no => 2).first
|
869
|
-
@record_3 = MultipleColumnsOrderable.where(:serial_no => 3).first
|
870
|
-
@record_4 = MultipleColumnsOrderable.where(:serial_no => 4).first
|
871
|
-
@record_5 = MultipleColumnsOrderable.where(:serial_no => 5).first
|
872
|
-
end
|
873
|
-
|
874
|
-
it "should return the lower/higher item on the list for next_item/previous_item" do
|
875
|
-
expect(@record_1.next_item).to eq(@record_2)
|
876
|
-
expect(@record_3.next_item).to eq(@record_4)
|
877
|
-
expect(@record_5.next_item).to eq(nil)
|
878
|
-
expect(@record_1.prev_item).to eq(nil)
|
879
|
-
expect(@record_3.prev_item).to eq(@record_2)
|
880
|
-
expect(@record_5.prev_item).to eq(@record_4)
|
881
|
-
end
|
882
|
-
|
883
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
884
|
-
expect(@record_1.next_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
885
|
-
expect(@record_3.next_items.to_a).to eq([@record_4, @record_5])
|
886
|
-
expect(@record_5.next_items.to_a).to eq([])
|
887
|
-
expect(@record_1.previous_items.to_a).to eq([])
|
888
|
-
expect(@record_3.previous_items.to_a).to eq([@record_1, @record_2])
|
889
|
-
expect(@record_5.previous_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
890
|
-
end
|
891
|
-
end
|
892
|
-
end
|
893
|
-
|
894
|
-
context 'serial_no orderable' do
|
895
|
-
|
896
|
-
let(:serial_nos){ MultipleColumnsOrderable.all.map(&:serial_no).sort }
|
897
|
-
|
898
|
-
it 'should have proper serial_no column' do
|
899
|
-
expect(MultipleColumnsOrderable.fields.key?('serial_no')).to be true
|
900
|
-
expect(MultipleColumnsOrderable.fields['serial_no'].options[:type]).to eq(Integer)
|
901
|
-
end
|
902
|
-
|
903
|
-
it 'should have index on serial_no column' do
|
904
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
905
|
-
expect(MultipleColumnsOrderable.index_options[[[:serial_no, 1]]]).not_to be_nil
|
906
|
-
elsif ::Mongoid::Compatibility::Version.mongoid3?
|
907
|
-
expect(MultipleColumnsOrderable.index_options[{:serial_no => 1}]).not_to be_nil
|
908
|
-
else
|
909
|
-
expect(MultipleColumnsOrderable.index_specifications.detect { |spec| spec.key == {:serial_no => 1} }).not_to be_nil
|
910
|
-
end
|
911
|
-
end
|
912
|
-
|
913
|
-
it 'should have a orderable base of 1' do
|
914
|
-
expect(MultipleColumnsOrderable.first.orderable_base(:serial_no)).to eq(1)
|
915
|
-
end
|
916
|
-
|
917
|
-
it 'should set proper position while creation' do
|
918
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
919
|
-
end
|
920
|
-
|
921
|
-
describe 'removement' do
|
922
|
-
|
923
|
-
it 'top' do
|
924
|
-
MultipleColumnsOrderable.where(:serial_no => 1).destroy
|
925
|
-
expect(serial_nos).to eq([1, 2, 3, 4])
|
926
|
-
end
|
927
|
-
|
928
|
-
it 'bottom' do
|
929
|
-
MultipleColumnsOrderable.where(:serial_no => 5).destroy
|
930
|
-
expect(serial_nos).to eq([1, 2, 3, 4])
|
931
|
-
end
|
932
|
-
|
933
|
-
it 'middle' do
|
934
|
-
MultipleColumnsOrderable.where(:serial_no => 3).destroy
|
935
|
-
expect(serial_nos).to eq([1, 2, 3, 4])
|
936
|
-
end
|
937
|
-
end
|
938
|
-
|
939
|
-
describe 'inserting' do
|
940
|
-
let(:newbie){ MultipleColumnsOrderable.create! }
|
941
|
-
|
942
|
-
before { @position = newbie.position }
|
943
|
-
|
944
|
-
it 'top' do
|
945
|
-
newbie.move_serial_no_to! :top
|
946
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
947
|
-
expect(newbie.serial_no).to eq(1)
|
948
|
-
expect(newbie.position).to eq(@position)
|
949
|
-
end
|
950
|
-
|
951
|
-
it 'bottom' do
|
952
|
-
newbie.move_serial_no_to! :bottom
|
953
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
954
|
-
expect(newbie.serial_no).to eq(6)
|
955
|
-
expect(newbie.position).to eq(@position)
|
956
|
-
end
|
957
|
-
|
958
|
-
it 'middle' do
|
959
|
-
newbie.move_serial_no_to! 4
|
960
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5, 6])
|
961
|
-
expect(newbie.serial_no).to eq(4)
|
962
|
-
expect(newbie.position).to eq(@position)
|
963
|
-
end
|
964
|
-
end
|
965
|
-
|
966
|
-
describe 'movement' do
|
967
|
-
it 'higher from top' do
|
968
|
-
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
969
|
-
position = record.position
|
970
|
-
record.move_serial_no_higher!
|
971
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
972
|
-
expect(record.serial_no).to eq(1)
|
973
|
-
expect(record.position).to eq(position)
|
974
|
-
end
|
975
|
-
|
976
|
-
it 'higher from bottom' do
|
977
|
-
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
978
|
-
position = record.position
|
979
|
-
record.move_serial_no_higher!
|
980
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
981
|
-
expect(record.serial_no).to eq(4)
|
982
|
-
expect(record.position).to eq(position)
|
983
|
-
end
|
984
|
-
|
985
|
-
it 'higher from middle' do
|
986
|
-
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
987
|
-
position = record.position
|
988
|
-
record.move_serial_no_higher!
|
989
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
990
|
-
expect(record.serial_no).to eq(2)
|
991
|
-
expect(record.position).to eq(position)
|
992
|
-
end
|
993
|
-
|
994
|
-
it 'lower from top' do
|
995
|
-
record = MultipleColumnsOrderable.where(:serial_no => 1).first
|
996
|
-
position = record.position
|
997
|
-
record.move_serial_no_lower!
|
998
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
999
|
-
expect(record.serial_no).to eq(2)
|
1000
|
-
expect(record.position).to eq(position)
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
it 'lower from bottom' do
|
1004
|
-
record = MultipleColumnsOrderable.where(:serial_no => 5).first
|
1005
|
-
position = record.position
|
1006
|
-
record.move_serial_no_lower!
|
1007
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
1008
|
-
expect(record.serial_no).to eq(5)
|
1009
|
-
expect(record.position).to eq(position)
|
1010
|
-
end
|
1011
|
-
|
1012
|
-
it 'lower from middle' do
|
1013
|
-
record = MultipleColumnsOrderable.where(:serial_no => 3).first
|
1014
|
-
position = record.position
|
1015
|
-
record.move_serial_no_lower!
|
1016
|
-
expect(serial_nos).to eq([1, 2, 3, 4, 5])
|
1017
|
-
expect(record.serial_no).to eq(4)
|
1018
|
-
expect(record.position).to eq(position)
|
1019
|
-
end
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
describe 'utility methods' do
|
1023
|
-
|
1024
|
-
before do
|
1025
|
-
@record_1 = MultipleColumnsOrderable.where(:serial_no => 1).first
|
1026
|
-
@record_2 = MultipleColumnsOrderable.where(:serial_no => 2).first
|
1027
|
-
@record_3 = MultipleColumnsOrderable.where(:serial_no => 3).first
|
1028
|
-
@record_4 = MultipleColumnsOrderable.where(:serial_no => 4).first
|
1029
|
-
@record_5 = MultipleColumnsOrderable.where(:serial_no => 5).first
|
1030
|
-
end
|
1031
|
-
|
1032
|
-
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1033
|
-
expect(@record_1.next_serial_no_item).to eq(@record_2)
|
1034
|
-
expect(@record_3.next_serial_no_item).to eq(@record_4)
|
1035
|
-
expect(@record_5.next_serial_no_item).to eq(nil)
|
1036
|
-
expect(@record_1.prev_serial_no_item).to eq(nil)
|
1037
|
-
expect(@record_3.prev_serial_no_item).to eq(@record_2)
|
1038
|
-
expect(@record_5.prev_serial_no_item).to eq(@record_4)
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1042
|
-
expect(@record_1.next_serial_no_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
1043
|
-
expect(@record_3.next_serial_no_items.to_a).to eq([@record_4, @record_5])
|
1044
|
-
expect(@record_5.next_serial_no_items.to_a).to eq([])
|
1045
|
-
expect(@record_1.previous_serial_no_items.to_a).to eq([])
|
1046
|
-
expect(@record_3.previous_serial_no_items.to_a).to eq([@record_1, @record_2])
|
1047
|
-
expect(@record_5.previous_serial_no_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
1048
|
-
end
|
1049
|
-
end
|
1050
|
-
|
1051
|
-
end
|
1052
|
-
|
1053
|
-
context 'position orderable' do
|
1054
|
-
|
1055
|
-
let(:positions){ MultipleColumnsOrderable.all.map(&:position).sort }
|
1056
|
-
|
1057
|
-
it 'should not have default position field' do
|
1058
|
-
expect(MultipleColumnsOrderable.fields).not_to have_key('position')
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
it 'should have custom pos field' do
|
1062
|
-
expect(MultipleColumnsOrderable.fields).to have_key('pos')
|
1063
|
-
expect(MultipleColumnsOrderable.fields['pos'].options[:type]).to eq(Integer)
|
1064
|
-
end
|
1065
|
-
|
1066
|
-
it 'should have index on position column' do
|
1067
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
1068
|
-
expect(MultipleColumnsOrderable.index_options[[[:position, 1]]]).to be_nil
|
1069
|
-
elsif ::Mongoid::Compatibility::Version.mongoid3?
|
1070
|
-
expect(MultipleColumnsOrderable.index_options[{:position => 1}]).to be_nil
|
1071
|
-
else
|
1072
|
-
expect(MultipleColumnsOrderable.index_specifications.detect { |spec| spec.key == {:position => 1} }).to be_nil
|
1073
|
-
end
|
1074
|
-
end
|
1075
|
-
|
1076
|
-
it 'should have a orderable base of 0' do
|
1077
|
-
expect(MultipleColumnsOrderable.first.orderable_base(:position)).to eq(0)
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
it 'should set proper position while creation' do
|
1081
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
describe 'removement' do
|
1085
|
-
|
1086
|
-
it 'top' do
|
1087
|
-
MultipleColumnsOrderable.where(:pos => 1).destroy
|
1088
|
-
expect(positions).to eq([0, 1, 2, 3])
|
1089
|
-
end
|
1090
|
-
|
1091
|
-
it 'bottom' do
|
1092
|
-
MultipleColumnsOrderable.where(:pos => 4).destroy
|
1093
|
-
expect(positions).to eq([0, 1, 2, 3])
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
it 'middle' do
|
1097
|
-
MultipleColumnsOrderable.where(:pos => 3).destroy
|
1098
|
-
expect(positions).to eq([0, 1, 2, 3])
|
1099
|
-
end
|
1100
|
-
end
|
1101
|
-
|
1102
|
-
describe 'inserting' do
|
1103
|
-
let(:newbie){ MultipleColumnsOrderable.create! }
|
1104
|
-
|
1105
|
-
before { @serial_no = newbie.serial_no }
|
1106
|
-
|
1107
|
-
it 'top' do
|
1108
|
-
newbie.move_position_to! :top
|
1109
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1110
|
-
expect(newbie.position).to eq(0)
|
1111
|
-
expect(newbie.serial_no).to eq(@serial_no)
|
1112
|
-
end
|
1113
|
-
|
1114
|
-
it 'bottom' do
|
1115
|
-
newbie.move_position_to! :bottom
|
1116
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1117
|
-
expect(newbie.position).to eq(5)
|
1118
|
-
expect(newbie.serial_no).to eq(@serial_no)
|
1119
|
-
end
|
1120
|
-
|
1121
|
-
it 'middle' do
|
1122
|
-
newbie.move_position_to! 4
|
1123
|
-
expect(positions).to eq([0, 1, 2, 3, 4, 5])
|
1124
|
-
expect(newbie.position).to eq(4)
|
1125
|
-
expect(newbie.serial_no).to eq(@serial_no)
|
1126
|
-
end
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
describe 'movement' do
|
1130
|
-
it 'higher from top' do
|
1131
|
-
record = MultipleColumnsOrderable.where(:pos => 0).first
|
1132
|
-
position = record.serial_no
|
1133
|
-
record.move_position_higher!
|
1134
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1135
|
-
expect(record.position).to eq(0)
|
1136
|
-
expect(record.serial_no).to eq(position)
|
1137
|
-
end
|
1138
|
-
|
1139
|
-
it 'higher from bottom' do
|
1140
|
-
record = MultipleColumnsOrderable.where(:pos => 4).first
|
1141
|
-
position = record.serial_no
|
1142
|
-
record.move_position_higher!
|
1143
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1144
|
-
expect(record.position).to eq(3)
|
1145
|
-
expect(record.serial_no).to eq(position)
|
1146
|
-
end
|
1147
|
-
|
1148
|
-
it 'higher from middle' do
|
1149
|
-
record = MultipleColumnsOrderable.where(:pos => 3).first
|
1150
|
-
position = record.serial_no
|
1151
|
-
record.move_position_higher!
|
1152
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1153
|
-
expect(record.position).to eq(2)
|
1154
|
-
expect(record.serial_no).to eq(position)
|
1155
|
-
end
|
1156
|
-
|
1157
|
-
it 'lower from top' do
|
1158
|
-
record = MultipleColumnsOrderable.where(:pos => 0).first
|
1159
|
-
position = record.serial_no
|
1160
|
-
record.move_position_lower!
|
1161
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1162
|
-
expect(record.position).to eq(1)
|
1163
|
-
expect(record.serial_no).to eq(position)
|
1164
|
-
end
|
1165
|
-
|
1166
|
-
it 'lower from bottom' do
|
1167
|
-
record = MultipleColumnsOrderable.where(:pos => 4).first
|
1168
|
-
position = record.serial_no
|
1169
|
-
record.move_position_lower!
|
1170
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1171
|
-
expect(record.position).to eq(4)
|
1172
|
-
expect(record.serial_no).to eq(position)
|
1173
|
-
end
|
1174
|
-
|
1175
|
-
it 'lower from middle' do
|
1176
|
-
record = MultipleColumnsOrderable.where(:pos => 3).first
|
1177
|
-
position = record.serial_no
|
1178
|
-
record.move_position_lower!
|
1179
|
-
expect(positions).to eq([0, 1, 2, 3, 4])
|
1180
|
-
expect(record.position).to eq(4)
|
1181
|
-
expect(record.serial_no).to eq(position)
|
1182
|
-
end
|
1183
|
-
end
|
1184
|
-
|
1185
|
-
describe 'utility methods' do
|
1186
|
-
|
1187
|
-
before do
|
1188
|
-
@record_1 = MultipleColumnsOrderable.where(:pos => 0).first
|
1189
|
-
@record_2 = MultipleColumnsOrderable.where(:pos => 1).first
|
1190
|
-
@record_3 = MultipleColumnsOrderable.where(:pos => 2).first
|
1191
|
-
@record_4 = MultipleColumnsOrderable.where(:pos => 3).first
|
1192
|
-
@record_5 = MultipleColumnsOrderable.where(:pos => 4).first
|
1193
|
-
end
|
1194
|
-
|
1195
|
-
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1196
|
-
expect(@record_1.next_position_item).to eq(@record_2)
|
1197
|
-
expect(@record_3.next_position_item).to eq(@record_4)
|
1198
|
-
expect(@record_5.next_position_item).to eq(nil)
|
1199
|
-
expect(@record_1.prev_position_item).to eq(nil)
|
1200
|
-
expect(@record_3.prev_position_item).to eq(@record_2)
|
1201
|
-
expect(@record_5.prev_position_item).to eq(@record_4)
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1205
|
-
expect(@record_1.next_position_items.to_a).to eq([@record_2, @record_3, @record_4, @record_5])
|
1206
|
-
expect(@record_3.next_position_items.to_a).to eq([@record_4, @record_5])
|
1207
|
-
expect(@record_5.next_position_items.to_a).to eq([])
|
1208
|
-
expect(@record_1.previous_position_items.to_a).to eq([])
|
1209
|
-
expect(@record_3.previous_position_items.to_a).to eq([@record_1, @record_2])
|
1210
|
-
expect(@record_5.previous_position_items.to_a).to eq([@record_1, @record_2, @record_3, @record_4])
|
1211
|
-
end
|
1212
|
-
end
|
1213
|
-
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
context 'group_count orderable' do
|
1217
|
-
before :each do
|
1218
|
-
MultipleColumnsOrderable.delete_all
|
1219
|
-
2.times { MultipleColumnsOrderable.create! :group_id => 1 }
|
1220
|
-
3.times { MultipleColumnsOrderable.create! :group_id => 2 }
|
1221
|
-
end
|
1222
|
-
|
1223
|
-
let(:all_groups){ MultipleColumnsOrderable.order_by([:group_id, :asc], [:groups, :asc]).map(&:groups) }
|
1224
|
-
|
1225
|
-
it 'should set proper position while creation' do
|
1226
|
-
expect(all_groups).to eq([1, 2, 1, 2, 3])
|
1227
|
-
end
|
1228
|
-
|
1229
|
-
describe 'removement' do
|
1230
|
-
|
1231
|
-
it 'top' do
|
1232
|
-
MultipleColumnsOrderable.where(:groups => 1, :group_id => 1).destroy
|
1233
|
-
expect(all_groups).to eq([1, 1, 2, 3])
|
1234
|
-
end
|
1235
|
-
|
1236
|
-
it 'bottom' do
|
1237
|
-
MultipleColumnsOrderable.where(:groups => 3, :group_id => 2).destroy
|
1238
|
-
expect(all_groups).to eq([1, 2, 1, 2])
|
1239
|
-
end
|
1240
|
-
|
1241
|
-
it 'middle' do
|
1242
|
-
MultipleColumnsOrderable.where(:groups => 2, :group_id => 2).destroy
|
1243
|
-
expect(all_groups).to eq([1, 2, 1, 2])
|
1244
|
-
end
|
1245
|
-
end
|
1246
|
-
|
1247
|
-
describe 'inserting' do
|
1248
|
-
|
1249
|
-
it 'top' do
|
1250
|
-
newbie = MultipleColumnsOrderable.create! :group_id => 1
|
1251
|
-
newbie.move_groups_to! :top
|
1252
|
-
expect(all_groups).to eq([1, 2, 3, 1, 2, 3])
|
1253
|
-
expect(newbie.groups).to eq(1)
|
1254
|
-
end
|
1255
|
-
|
1256
|
-
it 'bottom' do
|
1257
|
-
newbie = MultipleColumnsOrderable.create! :group_id => 2
|
1258
|
-
newbie.move_groups_to! :bottom
|
1259
|
-
expect(all_groups).to eq([1, 2, 1, 2, 3, 4])
|
1260
|
-
expect(newbie.groups).to eq(4)
|
1261
|
-
end
|
1262
|
-
|
1263
|
-
it 'middle' do
|
1264
|
-
newbie = MultipleColumnsOrderable.create! :group_id => 2
|
1265
|
-
newbie.move_groups_to! 2
|
1266
|
-
expect(all_groups).to eq([1, 2, 1, 2, 3, 4])
|
1267
|
-
expect(newbie.groups).to eq(2)
|
1268
|
-
end
|
1269
|
-
end
|
1270
|
-
|
1271
|
-
describe 'scope movement' do
|
1272
|
-
|
1273
|
-
let(:record){ MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first }
|
1274
|
-
|
1275
|
-
it 'to a new scope group' do
|
1276
|
-
record.update_attributes :group_id => 3
|
1277
|
-
expect(all_groups).to eq([1, 2, 1, 2, 1])
|
1278
|
-
expect(record.groups).to eq(1)
|
1279
|
-
end
|
1280
|
-
|
1281
|
-
context 'when moving to an existing scope group' do
|
1282
|
-
|
1283
|
-
it 'without a position' do
|
1284
|
-
record.update_attributes :group_id => 1
|
1285
|
-
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1286
|
-
expect(record.reload.groups).to eq(3)
|
1287
|
-
end
|
1288
|
-
|
1289
|
-
it 'with symbol position' do
|
1290
|
-
record.update_attributes :group_id => 1
|
1291
|
-
record.move_groups_to! :top
|
1292
|
-
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1293
|
-
expect(record.reload.groups).to eq(1)
|
1294
|
-
end
|
1295
|
-
|
1296
|
-
it 'with point position' do
|
1297
|
-
record.update_attributes :group_id => 1
|
1298
|
-
record.move_groups_to! 2
|
1299
|
-
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1300
|
-
expect(record.reload.groups).to eq(2)
|
1301
|
-
end
|
1302
|
-
end
|
1303
|
-
end
|
1304
|
-
|
1305
|
-
if defined?(Mongoid::IdentityMap)
|
1306
|
-
|
1307
|
-
context 'when identity map is enabled' do
|
1308
|
-
|
1309
|
-
let(:record){ MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first }
|
1310
|
-
|
1311
|
-
before do
|
1312
|
-
Mongoid.identity_map_enabled = true
|
1313
|
-
Mongoid::IdentityMap[MultipleColumnsOrderable.collection_name] = { record.id => record }
|
1314
|
-
end
|
1315
|
-
|
1316
|
-
after { Mongoid.identity_map_enabled = false }
|
1317
|
-
|
1318
|
-
it 'to a new scope group' do
|
1319
|
-
record.update_attributes :group_id => 3
|
1320
|
-
expect(all_groups).to eq([1, 2, 1, 2, 1])
|
1321
|
-
expect(record.groups).to eq(1)
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
it 'to an existing scope group' do
|
1325
|
-
record.update_attributes :group_id => 1
|
1326
|
-
record.move_groups_to! 2
|
1327
|
-
expect(all_groups).to eq([1, 2, 3, 1, 2])
|
1328
|
-
expect(record.groups).to eq(2)
|
1329
|
-
end
|
1330
|
-
end
|
1331
|
-
end
|
1332
|
-
|
1333
|
-
describe 'utility methods' do
|
1334
|
-
|
1335
|
-
before do
|
1336
|
-
@record_1 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 1).first
|
1337
|
-
@record_2 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 2).first
|
1338
|
-
@record_3 = MultipleColumnsOrderable.where(:group_id => 2, :groups => 3).first
|
1339
|
-
@record_4 = MultipleColumnsOrderable.where(:group_id => 1, :groups => 1).first
|
1340
|
-
@record_5 = MultipleColumnsOrderable.where(:group_id => 1, :groups => 2).first
|
1341
|
-
end
|
1342
|
-
|
1343
|
-
it "should return the lower/higher item on the list for next_item/previous_item" do
|
1344
|
-
expect(@record_1.next_groups_item).to eq(@record_2)
|
1345
|
-
expect(@record_4.next_groups_item).to eq(@record_5)
|
1346
|
-
expect(@record_3.next_groups_item).to eq(nil)
|
1347
|
-
expect(@record_1.prev_groups_item).to eq(nil)
|
1348
|
-
expect(@record_3.prev_groups_item).to eq(@record_2)
|
1349
|
-
expect(@record_5.prev_groups_item).to eq(@record_4)
|
1350
|
-
end
|
1351
|
-
|
1352
|
-
it "should return a collection of items lower/higher on the list for next_items/previous_items" do
|
1353
|
-
expect(@record_1.next_groups_items.to_a).to eq([@record_2, @record_3])
|
1354
|
-
expect(@record_3.next_groups_items.to_a).to eq([])
|
1355
|
-
expect(@record_4.next_groups_items.to_a).to eq([@record_5])
|
1356
|
-
expect(@record_1.previous_groups_items.to_a).to eq([])
|
1357
|
-
expect(@record_3.previous_groups_items.to_a).to eq([@record_1, @record_2])
|
1358
|
-
expect(@record_5.previous_groups_items.to_a).to eq([@record_4])
|
1359
|
-
end
|
1360
|
-
end
|
1361
|
-
end
|
1362
|
-
end
|
1363
|
-
|
1364
|
-
describe MultipleScopedOrderable do
|
1365
|
-
before :each do
|
1366
|
-
Apple.delete_all; Orange.delete_all;
|
1367
|
-
MultipleScopedOrderable.delete_all
|
1368
|
-
|
1369
|
-
3.times do
|
1370
|
-
Apple.create; Orange.create
|
1371
|
-
end
|
1372
|
-
|
1373
|
-
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 1
|
1374
|
-
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 1
|
1375
|
-
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 2
|
1376
|
-
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 3
|
1377
|
-
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 1
|
1378
|
-
MultipleScopedOrderable.create! :apple_id => 3, :orange_id => 3
|
1379
|
-
MultipleScopedOrderable.create! :apple_id => 2, :orange_id => 3
|
1380
|
-
MultipleScopedOrderable.create! :apple_id => 3, :orange_id => 2
|
1381
|
-
MultipleScopedOrderable.create! :apple_id => 1, :orange_id => 3
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
def apple_positions
|
1385
|
-
MultipleScopedOrderable.order_by([:apple_id, :asc], [:posa, :asc]).map(&:posa)
|
1386
|
-
end
|
1387
|
-
|
1388
|
-
def orange_positions
|
1389
|
-
MultipleScopedOrderable.order_by([:orange_id, :asc], [:poso, :asc]).map(&:poso)
|
1390
|
-
end
|
1391
|
-
|
1392
|
-
describe 'default positions' do
|
1393
|
-
it { expect(apple_positions).to eq([1, 2, 3, 4, 1, 2, 3, 1, 2]) }
|
1394
|
-
it { expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4]) }
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
describe 'change the scope of the apple' do
|
1398
|
-
let(:record) { MultipleScopedOrderable.first }
|
1399
|
-
before do
|
1400
|
-
record.update_attribute(:apple_id, 2)
|
1401
|
-
end
|
1402
|
-
|
1403
|
-
it 'should properly set the apple positions' do
|
1404
|
-
expect(apple_positions).to eq([1, 2, 3, 1, 2, 3, 4, 1, 2])
|
1405
|
-
end
|
1406
|
-
|
1407
|
-
it 'should not affect the orange positions' do
|
1408
|
-
expect(orange_positions).to eq([1, 2, 3, 1, 2, 1, 2, 3, 4])
|
1409
|
-
end
|
1410
|
-
end
|
1411
|
-
end
|
1412
|
-
|
1413
|
-
end
|