activesorting 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,163 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ activesorting (0.5.0)
5
+ activerecord (>= 4.0.0)
6
+ railties (>= 4.0.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (5.0.0.beta3)
12
+ actionpack (= 5.0.0.beta3)
13
+ nio4r (~> 1.2)
14
+ websocket-driver (~> 0.6.1)
15
+ actionmailer (5.0.0.beta3)
16
+ actionpack (= 5.0.0.beta3)
17
+ actionview (= 5.0.0.beta3)
18
+ activejob (= 5.0.0.beta3)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 1.0, >= 1.0.5)
21
+ actionpack (5.0.0.beta3)
22
+ actionview (= 5.0.0.beta3)
23
+ activesupport (= 5.0.0.beta3)
24
+ rack (~> 2.x)
25
+ rack-test (~> 0.6.3)
26
+ rails-dom-testing (~> 1.0, >= 1.0.5)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (5.0.0.beta3)
29
+ activesupport (= 5.0.0.beta3)
30
+ builder (~> 3.1)
31
+ erubis (~> 2.7.0)
32
+ rails-dom-testing (~> 1.0, >= 1.0.5)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
34
+ activejob (5.0.0.beta3)
35
+ activesupport (= 5.0.0.beta3)
36
+ globalid (>= 0.3.6)
37
+ activemodel (5.0.0.beta3)
38
+ activesupport (= 5.0.0.beta3)
39
+ activerecord (5.0.0.beta3)
40
+ activemodel (= 5.0.0.beta3)
41
+ activesupport (= 5.0.0.beta3)
42
+ arel (~> 7.0)
43
+ activesupport (5.0.0.beta3)
44
+ concurrent-ruby (~> 1.0)
45
+ i18n (~> 0.7)
46
+ minitest (~> 5.1)
47
+ tzinfo (~> 1.1)
48
+ appraisal (2.1.0)
49
+ bundler
50
+ rake
51
+ thor (>= 0.14.0)
52
+ arel (7.0.0)
53
+ builder (3.2.2)
54
+ concurrent-ruby (1.0.1)
55
+ coveralls (0.8.13)
56
+ json (~> 1.8)
57
+ simplecov (~> 0.11.0)
58
+ term-ansicolor (~> 1.3)
59
+ thor (~> 0.19.1)
60
+ tins (~> 1.6.0)
61
+ diff-lcs (1.2.5)
62
+ docile (1.1.5)
63
+ erubis (2.7.0)
64
+ globalid (0.3.6)
65
+ activesupport (>= 4.1.0)
66
+ i18n (0.7.0)
67
+ json (1.8.3)
68
+ loofah (2.0.3)
69
+ nokogiri (>= 1.5.9)
70
+ mail (2.6.4)
71
+ mime-types (>= 1.16, < 4)
72
+ method_source (0.8.2)
73
+ mime-types (3.0)
74
+ mime-types-data (~> 3.2015)
75
+ mime-types-data (3.2016.0221)
76
+ mini_portile2 (2.0.0)
77
+ minitest (5.8.4)
78
+ nio4r (1.2.1)
79
+ nokogiri (1.6.7.2)
80
+ mini_portile2 (~> 2.0.0.rc2)
81
+ rack (2.0.0.alpha)
82
+ json
83
+ rack-test (0.6.3)
84
+ rack (>= 1.0)
85
+ rails (5.0.0.beta3)
86
+ actioncable (= 5.0.0.beta3)
87
+ actionmailer (= 5.0.0.beta3)
88
+ actionpack (= 5.0.0.beta3)
89
+ actionview (= 5.0.0.beta3)
90
+ activejob (= 5.0.0.beta3)
91
+ activemodel (= 5.0.0.beta3)
92
+ activerecord (= 5.0.0.beta3)
93
+ activesupport (= 5.0.0.beta3)
94
+ bundler (>= 1.3.0, < 2.0)
95
+ railties (= 5.0.0.beta3)
96
+ sprockets-rails (>= 2.0.0)
97
+ rails-deprecated_sanitizer (1.0.3)
98
+ activesupport (>= 4.2.0.alpha)
99
+ rails-dom-testing (1.0.7)
100
+ activesupport (>= 4.2.0.beta, < 5.0)
101
+ nokogiri (~> 1.6.0)
102
+ rails-deprecated_sanitizer (>= 1.0.1)
103
+ rails-html-sanitizer (1.0.3)
104
+ loofah (~> 2.0)
105
+ railties (5.0.0.beta3)
106
+ actionpack (= 5.0.0.beta3)
107
+ activesupport (= 5.0.0.beta3)
108
+ method_source
109
+ rake (>= 0.8.7)
110
+ thor (>= 0.18.1, < 2.0)
111
+ rake (10.5.0)
112
+ rspec (3.4.0)
113
+ rspec-core (~> 3.4.0)
114
+ rspec-expectations (~> 3.4.0)
115
+ rspec-mocks (~> 3.4.0)
116
+ rspec-core (3.4.4)
117
+ rspec-support (~> 3.4.0)
118
+ rspec-expectations (3.4.0)
119
+ diff-lcs (>= 1.2.0, < 2.0)
120
+ rspec-support (~> 3.4.0)
121
+ rspec-mocks (3.4.1)
122
+ diff-lcs (>= 1.2.0, < 2.0)
123
+ rspec-support (~> 3.4.0)
124
+ rspec-support (3.4.1)
125
+ simplecov (0.11.2)
126
+ docile (~> 1.1.0)
127
+ json (~> 1.8)
128
+ simplecov-html (~> 0.10.0)
129
+ simplecov-html (0.10.0)
130
+ sprockets (3.5.2)
131
+ concurrent-ruby (~> 1.0)
132
+ rack (> 1, < 3)
133
+ sprockets-rails (3.0.4)
134
+ actionpack (>= 4.0)
135
+ activesupport (>= 4.0)
136
+ sprockets (>= 3.0.0)
137
+ sqlite3 (1.3.11)
138
+ term-ansicolor (1.3.2)
139
+ tins (~> 1.0)
140
+ thor (0.19.1)
141
+ thread_safe (0.3.5)
142
+ tins (1.6.0)
143
+ tzinfo (1.2.2)
144
+ thread_safe (~> 0.1)
145
+ websocket-driver (0.6.3)
146
+ websocket-extensions (>= 0.1.0)
147
+ websocket-extensions (0.1.2)
148
+
149
+ PLATFORMS
150
+ ruby
151
+
152
+ DEPENDENCIES
153
+ appraisal
154
+ bundler (~> 1.11)
155
+ coveralls
156
+ rails (= 5.0.0.beta3)
157
+ rake (~> 10.0)
158
+ rspec
159
+ sqlite3
160
+ activesorting!
161
+
162
+ BUNDLED WITH
163
+ 1.11.2
@@ -0,0 +1,7 @@
1
+ module ActiveSorting
2
+ class Engine < Rails::Engine # :nodoc:
3
+ ActiveSupport.on_load(:active_record) do
4
+ ActiveRecord::Base.send(:include, ActiveSorting::Model)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,159 @@
1
+ module ActiveSorting
2
+ module Model # :nodoc:
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ # Patches ActiveRecord models
8
+ module ClassMethods
9
+ # Track all sortable arguments
10
+ attr_accessor :active_sorting_options
11
+
12
+ # Sets the sortable options
13
+ #
14
+ # +name+ sortable field name
15
+ # Accepts a Hash of options:
16
+ # +order+ sorting direction, defaults to :asc
17
+ # +step+ stepping value, defaults to 500
18
+ # +scope+ scope field name, defaults to []
19
+ def sortable(name, opts = {})
20
+ self.active_sorting_options = active_sorting_default_options.merge(opts)
21
+ active_sorting_options[:name] = name
22
+ active_sorting_check_options
23
+ validates active_sorting_options[:name], presence: true
24
+ before_validation :active_sorting_callback_before_validation
25
+ end
26
+
27
+ # Default sorting options
28
+ def active_sorting_default_options
29
+ {
30
+ order: :asc,
31
+ step: 500,
32
+ scope: []
33
+ }
34
+ end
35
+
36
+ # Check provided options
37
+ def active_sorting_check_options
38
+ unless columns_hash[active_sorting_field.to_s].type == :integer
39
+ raise ArgumentError, 'Sortable field should be of type Integer'
40
+ end
41
+ unless active_sorting_step.is_a?(Fixnum)
42
+ raise ArgumentError, 'Sortable step should be of type Fixnum'
43
+ end
44
+ end
45
+
46
+ # Calculate the least possible changes required to
47
+ # reorder items in +old_list+ to match +new_list+ order
48
+ # by comparing two proposals from
49
+ # +active_sorting_calculate_changes+
50
+ def active_sorting_changes_required(old_list, new_list)
51
+ changes = []
52
+ if old_list.count != new_list.count
53
+ raise ArgumentError, "Size mismatch between new (#{new_list.count}) and old (#{old_list.count}) array of items"
54
+ end
55
+ proposal1 = active_sorting_calculate_changes(old_list.dup, new_list.dup)
56
+ if proposal1.count >= (new_list.count / 4)
57
+ proposal2 = active_sorting_calculate_changes(old_list.reverse, new_list.reverse)
58
+ changes = proposal1.count < proposal2.count ? proposal1 : proposal2
59
+ else
60
+ changes = proposal1
61
+ end
62
+ changes
63
+ end
64
+
65
+ # Calculate the possible changes required to
66
+ # reorder items in +old_list+ to match +new_list+ order
67
+ def active_sorting_calculate_changes(old_list, new_list, changes = [])
68
+ new_list.each_with_index do |id, index|
69
+ next unless old_list[index] != id
70
+ # This item has changed
71
+ changes << id
72
+ # Remove it from both lists, rinse and repeat
73
+ new_list.delete(id)
74
+ old_list.delete(id)
75
+ # Recur...
76
+ active_sorting_calculate_changes(old_list, new_list, changes)
77
+ break
78
+ end
79
+ changes
80
+ end
81
+
82
+ # Commit changes to database
83
+ def active_sorting_make_changes(new_list, changes)
84
+ new_list.each_with_index do |id, index|
85
+ next unless changes.include?(id)
86
+ if index == new_list.count.pred
87
+ # We're moving an item to last position,
88
+ # increase the count of last item's position
89
+ # by the step
90
+ n1 = find(index.pred).active_sorting_value
91
+ n2 = n1 + active_sorting_step
92
+ elsif index == 0
93
+ # We're moving an item to first position
94
+ # Calculate the gap between following 2 items
95
+ n1 = find(index.next).active_sorting_value
96
+ n2 = find(index.next.next).active_sorting_value
97
+ else
98
+ # We're moving a non-terminal item
99
+ n1 = find(index.pred).active_sorting_value
100
+ n2 = find(index.next).active_sorting_value
101
+ end
102
+ find(id).active_sorting_center_item(n1, n2)
103
+ end
104
+ end
105
+
106
+ def active_sorting_field
107
+ active_sorting_options[:name]
108
+ end
109
+
110
+ def active_sorting_step
111
+ active_sorting_options[:step]
112
+ end
113
+
114
+ def active_sorting_order
115
+ active_sorting_options[:order]
116
+ end
117
+ end
118
+
119
+ def active_sorting_value
120
+ send(self.class.active_sorting_field)
121
+ end
122
+
123
+ def active_sorting_value=(new_value)
124
+ send("#{self.class.active_sorting_field}=", new_value)
125
+ end
126
+
127
+ # Centers an item between the given two positions
128
+ def active_sorting_center_item(n1, n2)
129
+ delta = (n1 - n2).abs
130
+ smaller = [n1, n2].min
131
+ if delta == 1
132
+ new_position = smaller + delta
133
+ elsif delta > 1
134
+ new_position = smaller + (delta / 2)
135
+ end
136
+ self.active_sorting_value = new_position
137
+ save!
138
+ self
139
+ end
140
+
141
+ # Generate the next stepping
142
+ def active_sorting_next_step
143
+ # Get the maximum value for the sortable field name
144
+ # TODO: scopes
145
+ max = self.class.unscoped.maximum(self.class.active_sorting_field)
146
+ # First value will always be 0
147
+ return 0 if max.nil?
148
+ # Increment by the step value configured
149
+ max + self.class.active_sorting_step
150
+ end
151
+
152
+ ## Callbacks
153
+ # Generates a new code based on given options
154
+ def active_sorting_callback_before_validation
155
+ field_name = self.class.active_sorting_field
156
+ send("#{field_name}=", active_sorting_next_step) if send(field_name).nil?
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveSorting
2
+ VERSION = '0.5.0'.freeze
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'rails/engine'
2
+ require 'active_record'
3
+ require 'active_sorting/version'
4
+ require 'active_sorting/model'
5
+ require 'active_sorting/engine'
@@ -0,0 +1 @@
1
+ require 'active_sorting'
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activesorting
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Omar Abdel-Wahab
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: sqlite3
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: coveralls
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
+ - !ruby/object:Gem::Dependency
84
+ name: appraisal
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activerecord
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 4.0.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 4.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: railties
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 4.0.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 4.0.0
125
+ description:
126
+ email:
127
+ - owahab@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".codeclimate.yml"
133
+ - ".coveralls.yml"
134
+ - ".gitignore"
135
+ - ".rubocop.yml"
136
+ - ".travis.yml"
137
+ - Appraisals
138
+ - CONTRIBUTING.md
139
+ - Gemfile
140
+ - LICENSE
141
+ - README.md
142
+ - Rakefile
143
+ - activesorting.gemspec
144
+ - bin/console
145
+ - bin/setup
146
+ - gemfiles/40.gemfile
147
+ - gemfiles/40.gemfile.lock
148
+ - gemfiles/41.gemfile
149
+ - gemfiles/41.gemfile.lock
150
+ - gemfiles/42.gemfile
151
+ - gemfiles/42.gemfile.lock
152
+ - gemfiles/50.gemfile
153
+ - gemfiles/50.gemfile.lock
154
+ - lib/active_sorting.rb
155
+ - lib/active_sorting/engine.rb
156
+ - lib/active_sorting/model.rb
157
+ - lib/active_sorting/version.rb
158
+ - lib/activesorting.rb
159
+ homepage: http://github.com/owahab/active_sorting
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.4.5
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Adds ability to sort models using a custom field
183
+ test_files: []