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
data/.gitignore
DELETED
data/.rspec
DELETED
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm use 2.2@mongoid_orderable --create
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
# Specify your gem's dependencies in mongoid_orderable.gemspec
|
4
|
-
gemspec
|
5
|
-
|
6
|
-
case version = ENV['MONGOID_VERSION'] || '5.0'
|
7
|
-
when /^5/
|
8
|
-
gem 'mongoid', '~> 5.0'
|
9
|
-
when /^4/
|
10
|
-
gem 'mongoid', '~> 4.0'
|
11
|
-
when /^3/
|
12
|
-
gem 'mongoid', '~> 3.1'
|
13
|
-
when /^2/
|
14
|
-
gem 'mongoid', '~> 2.0'
|
15
|
-
gem 'bson_ext', platforms: :ruby
|
16
|
-
else
|
17
|
-
gem 'mongoid', version
|
18
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Callbacks
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
included do
|
7
|
-
|
8
|
-
protected
|
9
|
-
|
10
|
-
def add_to_list
|
11
|
-
self.orderable_keys.each do |column|
|
12
|
-
apply_position column, move_all[column]
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def remove_from_list
|
17
|
-
self.orderable_keys.each do |column|
|
18
|
-
remove_position_from_list column
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def remove_position_from_list(column)
|
23
|
-
col, pos = orderable_column(column), orderable_position(column)
|
24
|
-
MongoidOrderable.inc orderable_scoped(column).where(col.gt => pos), col, -1
|
25
|
-
end
|
26
|
-
|
27
|
-
def apply_position column, target_position
|
28
|
-
if persisted? && !embedded? && orderable_scope_changed?(column)
|
29
|
-
self.class.unscoped.find(_id).remove_position_from_list(column)
|
30
|
-
self.send("orderable_#{column}_position=", nil)
|
31
|
-
end
|
32
|
-
|
33
|
-
return if !target_position && in_list?(column)
|
34
|
-
|
35
|
-
target_position = target_position_to_position column, target_position
|
36
|
-
scope, col, pos = orderable_scoped(column), orderable_column(column), orderable_position(column)
|
37
|
-
|
38
|
-
unless in_list?(column)
|
39
|
-
MongoidOrderable.inc scope.where(col.gte => target_position), col, 1
|
40
|
-
else
|
41
|
-
MongoidOrderable.inc(scope.where(col.gte => target_position, col.lt => pos), col, 1) if target_position < pos
|
42
|
-
MongoidOrderable.inc(scope.where(col.gt => pos, col.lte => target_position), col, -1) if target_position > pos
|
43
|
-
end
|
44
|
-
|
45
|
-
self.send("orderable_#{column}_position=", target_position)
|
46
|
-
end
|
47
|
-
|
48
|
-
def target_position_to_position column, target_position
|
49
|
-
target_position = :bottom unless target_position
|
50
|
-
|
51
|
-
target_position = case target_position.to_s
|
52
|
-
when 'top' then orderable_base(column)
|
53
|
-
when 'bottom' then bottom_orderable_position(column)
|
54
|
-
when 'higher' then orderable_position(column).pred
|
55
|
-
when 'lower' then orderable_position(column).next
|
56
|
-
when /\A\d+\Z/ then target_position.to_i
|
57
|
-
else raise Mongoid::Orderable::Errors::InvalidTargetPosition.new target_position
|
58
|
-
end unless target_position.is_a? Numeric
|
59
|
-
|
60
|
-
target_position = orderable_base(column) if target_position < orderable_base(column)
|
61
|
-
target_position = bottom_orderable_position(column) if target_position > bottom_orderable_position(column)
|
62
|
-
target_position
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
module ClassMethods
|
68
|
-
def add_orderable_callbacks
|
69
|
-
before_save :add_to_list
|
70
|
-
after_destroy :remove_from_list
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
class Configuration
|
4
|
-
|
5
|
-
CONFIG_OPTIONS = %w(column scope foreign_key inherited base index default).map(&:to_sym)
|
6
|
-
FIELD_OPTIONS = %w(as).map(&:to_sym)
|
7
|
-
VALID_OPTIONS = CONFIG_OPTIONS + FIELD_OPTIONS
|
8
|
-
|
9
|
-
attr_reader :orderable_class, :options
|
10
|
-
|
11
|
-
def initialize(parent, options = {})
|
12
|
-
@orderable_class = parent
|
13
|
-
set_options(options)
|
14
|
-
set_field_options
|
15
|
-
set_orderable_scope
|
16
|
-
end
|
17
|
-
|
18
|
-
def default_configuration
|
19
|
-
{ :column => :position,
|
20
|
-
:index => true,
|
21
|
-
:scope => nil,
|
22
|
-
:base => 1,
|
23
|
-
:field_opts => { :type => Integer }}
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.build(parent, options = {})
|
27
|
-
new(parent, options).options
|
28
|
-
end
|
29
|
-
|
30
|
-
protected
|
31
|
-
|
32
|
-
def set_options(options)
|
33
|
-
@options = default_configuration
|
34
|
-
return unless options.is_a? Hash
|
35
|
-
@options.merge! options.symbolize_keys.slice(*VALID_OPTIONS)
|
36
|
-
end
|
37
|
-
|
38
|
-
def set_field_options
|
39
|
-
FIELD_OPTIONS.each do |key|
|
40
|
-
next unless options.has_key? key
|
41
|
-
@options[:field_opts][key] = options.delete(key)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def set_orderable_scope
|
46
|
-
if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
|
47
|
-
scope_relation = @orderable_class.relations[options[:scope].to_s]
|
48
|
-
if scope_relation
|
49
|
-
@options[:scope] = scope_relation.key.to_sym
|
50
|
-
else
|
51
|
-
@options[:scope] = "#{options[:scope]}_id".to_sym
|
52
|
-
end
|
53
|
-
elsif options[:scope].is_a?(String)
|
54
|
-
@options[:scope] = options[:scope].to_sym
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Mongoid::Orderable
|
2
|
-
module Errors
|
3
|
-
class MongoidOrderableError < ::Mongoid::Errors::MongoidError
|
4
|
-
|
5
|
-
if ::Mongoid::Compatibility::Version.mongoid2?
|
6
|
-
def translate key, options
|
7
|
-
[:message, :summary, :resolution].map do |section|
|
8
|
-
::I18n.translate "#{BASE_KEY}.#{key}.#{section}", options
|
9
|
-
end.join ' '
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
include Mongoid::Orderable::Generator::Scope
|
5
|
-
include Mongoid::Orderable::Generator::Position
|
6
|
-
include Mongoid::Orderable::Generator::Movable
|
7
|
-
include Mongoid::Orderable::Generator::Listable
|
8
|
-
include Mongoid::Orderable::Generator::Helpers
|
9
|
-
|
10
|
-
def column_name
|
11
|
-
configuration[:field_opts][:as] || configuration[:column]
|
12
|
-
end
|
13
|
-
|
14
|
-
def order_scope
|
15
|
-
configuration[:scope]
|
16
|
-
end
|
17
|
-
|
18
|
-
def generate_all_helpers
|
19
|
-
generate_scope_helpers(column_name, order_scope)
|
20
|
-
generate_position_helpers(column_name)
|
21
|
-
generate_movable_helpers(column_name)
|
22
|
-
generate_listable_helpers(column_name)
|
23
|
-
generate_orderable_helpers
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
def generate_method(name, &block)
|
29
|
-
klass.send(:define_method, name, &block)
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
module Helpers
|
5
|
-
|
6
|
-
def generate_orderable_helpers
|
7
|
-
self_class = klass
|
8
|
-
|
9
|
-
klass.class_eval <<-eos
|
10
|
-
def orderable_base(column = nil)
|
11
|
-
column ||= default_orderable_column
|
12
|
-
#{self_class}.orderable_configurations[column][:base]
|
13
|
-
end
|
14
|
-
|
15
|
-
def orderable_column(column = nil)
|
16
|
-
column ||= default_orderable_column
|
17
|
-
#{self_class}.orderable_configurations[column][:column]
|
18
|
-
end
|
19
|
-
eos
|
20
|
-
|
21
|
-
generate_method(:orderable_inherited_class) do
|
22
|
-
self_class.orderable_configurations.any?{ |col, conf| conf[:inherited] } ? self_class : self.class
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
module Listable
|
5
|
-
|
6
|
-
def generate_listable_helpers(column_name)
|
7
|
-
generate_list_helpers(column_name)
|
8
|
-
generate_aliased_helpers(column_name)
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
|
13
|
-
def generate_list_helpers(column_name)
|
14
|
-
generate_method("next_#{column_name}_item") do
|
15
|
-
next_item(column_name)
|
16
|
-
end
|
17
|
-
|
18
|
-
generate_method("next_#{column_name}_items") do
|
19
|
-
next_items(column_name)
|
20
|
-
end
|
21
|
-
|
22
|
-
generate_method("previous_#{column_name}_item") do
|
23
|
-
previous_item(column_name)
|
24
|
-
end
|
25
|
-
|
26
|
-
generate_method("previous_#{column_name}_items") do
|
27
|
-
previous_items(column_name)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def generate_aliased_helpers(column_name)
|
32
|
-
klass.class_eval do
|
33
|
-
alias_method "prev_#{column_name}_items", "previous_#{column_name}_items"
|
34
|
-
alias_method "prev_#{column_name}_item", "previous_#{column_name}_item"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
module Movable
|
5
|
-
|
6
|
-
def generate_movable_helpers(column_name)
|
7
|
-
generate_move_to_helpers(column_name)
|
8
|
-
generate_insert_at_helpers(column_name)
|
9
|
-
generate_shorthand_helpers(column_name)
|
10
|
-
end
|
11
|
-
|
12
|
-
protected
|
13
|
-
|
14
|
-
def generate_move_to_helpers(column_name)
|
15
|
-
generate_method("move_#{column_name}_to") do |target_position|
|
16
|
-
move_column_to target_position, :column => column_name
|
17
|
-
end
|
18
|
-
|
19
|
-
generate_method("move_#{column_name}_to!") do |target_position|
|
20
|
-
move_column_to target_position, :column => column_name
|
21
|
-
save
|
22
|
-
end
|
23
|
-
|
24
|
-
generate_method("move_#{column_name}_to=") do |target_position|
|
25
|
-
move_column_to target_position, :column => column_name
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def generate_insert_at_helpers(column_name)
|
30
|
-
klass.class_eval do
|
31
|
-
alias_method "insert_#{column_name}_at!", "move_#{column_name}_to!"
|
32
|
-
alias_method "insert_#{column_name}_at", "move_#{column_name}_to"
|
33
|
-
alias_method "insert_#{column_name}_at=", "move_#{column_name}_to="
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def generate_shorthand_helpers(column_name)
|
38
|
-
[:top, :bottom].each do |symbol|
|
39
|
-
generate_method "move_#{column_name}_to_#{symbol}" do
|
40
|
-
move_to symbol, :column => column_name
|
41
|
-
end
|
42
|
-
|
43
|
-
generate_method "move_#{column_name}_to_#{symbol}!" do
|
44
|
-
move_to! symbol, :column => column_name
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
[:higher, :lower].each do |symbol|
|
49
|
-
generate_method "move_#{column_name}_#{symbol}" do
|
50
|
-
move_to symbol, :column => column_name
|
51
|
-
end
|
52
|
-
|
53
|
-
generate_method "move_#{column_name}_#{symbol}!" do
|
54
|
-
move_to! symbol, :column => column_name
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
module Position
|
5
|
-
|
6
|
-
def generate_position_helpers(column_name)
|
7
|
-
klass.class_eval <<-eos
|
8
|
-
def orderable_position(column = nil)
|
9
|
-
column ||= default_orderable_column
|
10
|
-
send "orderable_\#{column}_position"
|
11
|
-
end
|
12
|
-
eos
|
13
|
-
|
14
|
-
generate_method("orderable_#{column_name}_position") do
|
15
|
-
send column_name
|
16
|
-
end
|
17
|
-
|
18
|
-
generate_method("orderable_#{column_name}_position=") do |value|
|
19
|
-
send "#{column_name}=", value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Generator
|
4
|
-
module Scope
|
5
|
-
def generate_scope_helpers(column_name, order_scope)
|
6
|
-
klass.class_eval do
|
7
|
-
scope "orderable_#{column_name}_scope", case order_scope
|
8
|
-
when Symbol then lambda { |document| where(order_scope => document.send(order_scope)) }
|
9
|
-
when Proc then order_scope
|
10
|
-
else lambda { |document| where({}) }
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Orderable
|
3
|
-
module Helpers
|
4
|
-
|
5
|
-
def orderable_keys
|
6
|
-
Array orderable_inherited_class.orderable_configurations.try(:keys)
|
7
|
-
end
|
8
|
-
|
9
|
-
def default_orderable_column
|
10
|
-
self.class.orderable_configurations.detect{ |c, conf| conf[:default] }.try(:first) || self.orderable_keys.first
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def orderable_scoped(column = nil)
|
16
|
-
column ||= default_orderable_column
|
17
|
-
|
18
|
-
if embedded?
|
19
|
-
send(MongoidOrderable.metadata(self).inverse).send(MongoidOrderable.metadata(self).name).send("orderable_#{column}_scope", self)
|
20
|
-
else
|
21
|
-
self.orderable_inherited_class.send("orderable_#{column}_scope", self)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def orderable_scope_changed?(column)
|
26
|
-
if Mongoid.respond_to?(:unit_of_work)
|
27
|
-
Mongoid.unit_of_work do
|
28
|
-
orderable_scope_changed_query(column)
|
29
|
-
end
|
30
|
-
else
|
31
|
-
orderable_scope_changed_query(column)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def orderable_scope_changed_query(column)
|
36
|
-
!orderable_scoped(column).where(:_id => _id).exists?
|
37
|
-
end
|
38
|
-
|
39
|
-
def bottom_orderable_position(column = nil)
|
40
|
-
column ||= default_orderable_column
|
41
|
-
@bottom_orderable_position = begin
|
42
|
-
positions_list = orderable_scoped(column).distinct(orderable_column(column)).compact
|
43
|
-
return orderable_base(column) if positions_list.empty?
|
44
|
-
max = positions_list.map(&:to_i).max.to_i
|
45
|
-
in_list?(column) ? max : max.next
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|