activerecord-sort 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9ad6ad083d32b5354b090af30d25fb20c5b43c74
4
+ data.tar.gz: 9cbb97bae8eefbae937cf0ebc82154fbae1020e8
5
+ SHA512:
6
+ metadata.gz: 589a24220b64270fc59cb5e75f286fb51858150a451f1f4d464a3c45137c163c0d4e02f64d6946181b77fc41fce2a46cda96db965fb379349c5aaf09c17147bf
7
+ data.tar.gz: 63024dc5a854cf4f18ddadc8d5e13e6816ce671c2fcf9a7cdef34ad636b18ed63642330447401bcb750b81885b989bcf0828f6b63dc226aa0e193c6f08c9a4e7
@@ -0,0 +1,2 @@
1
+ # activerecord-sort
2
+ A safe way to accept user parameters and order against your ActiveRecord Models
@@ -0,0 +1,120 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+
4
+ # ordering:
5
+ # :id
6
+ # :name, :id
7
+ # :id => :desc
8
+ # :id => {:desc => :nulls_last}
9
+ # :listings => :id
10
+ # :listings => {:id => {:asc => :nulls_first}}
11
+ def sort(*ordering)
12
+ resource = all
13
+ ordering.compact!
14
+ ordering.flatten!
15
+ return resource if ordering.size == 0
16
+
17
+ ordering.each do |order|
18
+ order = sort_order_to_column_and_options(order)
19
+
20
+ order.each do |column_or_relation, options|
21
+ if self.column_names.include?(column_or_relation.to_s)
22
+ resource = resource.sort_for_column(column_or_relation, options)
23
+ elsif reflect_on_association(column_or_relation.to_sym)
24
+ resource = resource.select(resource.klass.arel_table[Arel::Nodes::SqlLiteral.new('*')])
25
+ resource = resource.sort_for_relation(column_or_relation.to_sym, options)
26
+ else
27
+ raise ActiveRecord::StatementInvalid.new("Unkown column #{column_or_relation}")
28
+ end
29
+ end
30
+ end
31
+
32
+ resource
33
+ end
34
+
35
+ def sort_for_column(column, options)
36
+ column = self.arel_table[column.to_s.underscore]
37
+ direction = (options.is_a?(Hash) ? options.keys.first.to_sym : options.to_s.downcase.to_sym)
38
+
39
+ nulls = (options.is_a?(Hash) ? options.values.first.to_sym : nil)
40
+ if direction == :desc
41
+ self.order(Arel::Nodes::Descending.new(column, nulls))
42
+ elsif direction == :asc || direction == :''
43
+ self.order(Arel::Nodes::Ascending.new(column, nulls))
44
+ else
45
+ raise ActiveRecord::StatementInvalid.new("Unkown ordering #{direction}")
46
+ end
47
+ end
48
+
49
+ def sort_for_relation(relation, options)
50
+ resource = self
51
+ relation = reflect_on_association(relation)
52
+
53
+ if relation.macro == :has_many
54
+ options = [options] if !options.is_a?(Array)
55
+
56
+ options.each do |order|
57
+ order = sort_order_to_column_and_options(order)
58
+ order.each do |column, options|
59
+ column = relation.klass.arel_table[column]
60
+ direction = (options.is_a?(Hash) ? options.keys.first.to_sym : options.to_s.downcase.to_sym)
61
+
62
+ nulls = (options.is_a?(Hash) ? options.values.first.to_sym : nil)
63
+ if direction == :desc
64
+ # aggregation = Arel::Nodes::Max.new([column], "max_#{relation.name}_#{column.name}")
65
+ # order = Arel::Nodes::Descending.new(Arel::Nodes::SqlLiteral.new("max_#{relation.name}_#{column.name}"), nulls)
66
+
67
+ if relation.options[:through]
68
+ resource = resource.joins(relation.options[:through] => relation.source_reflection_name)
69
+ else
70
+ resource = resource.joins(relation.name)
71
+ end
72
+ # resource = resource.select(aggregation)
73
+ # resource = resource.order(order)
74
+ resource = resource.order(Arel::Nodes::Descending.new(column, nulls))
75
+ else
76
+ # aggregation = Arel::Nodes::Min.new([column], "min_#{relation.name}_#{column.name}")
77
+ order = Arel::Nodes::Ascending.new(Arel::Nodes::SqlLiteral.new("min_#{relation.name}_#{column.name}"), nulls)
78
+
79
+ resource = resource.joins(relation.name)
80
+ # resource = resource.select(aggregation)
81
+ # resource = resource.order(order)
82
+ resource = resource.order(Arel::Nodes::Ascending.new(column, nulls))
83
+ end
84
+ end
85
+ end
86
+ elsif relation.macro == :belongs_to || relation.macro == :has_one
87
+ options = [options] if !options.is_a?(Array)
88
+
89
+ options.each do |order|
90
+ order = sort_order_to_column_and_options(order)
91
+ order.each do |column, options|
92
+ column = relation.klass.arel_table[column]
93
+ direction = (options.is_a?(Hash) ? options.keys.first.to_sym : options.to_s.downcase.to_sym)
94
+
95
+ nulls = (options.is_a?(Hash) ? options.values.first.to_sym : nil)
96
+ if direction == :asc
97
+ order = Arel::Nodes::Ascending.new(column, nulls)
98
+ else
99
+ order = Arel::Nodes::Descending.new(column, nulls)
100
+ end
101
+
102
+ resource = resource.joins(relation.name)
103
+ resource = resource.order(order)
104
+ end
105
+ end
106
+ end
107
+
108
+ resource
109
+ end
110
+
111
+ def sort_order_to_column_and_options(column)
112
+ if column.is_a?(Symbol)
113
+ [column]
114
+ else
115
+ column
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,15 @@
1
+ module Arel
2
+ module Nodes
3
+ class Ascending < Ordering
4
+
5
+ attr_accessor :nulls
6
+
7
+ def initialize expr, nulls=nil
8
+ super(expr)
9
+ @expr = expr
10
+ @nulls = nulls
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Arel
2
+ module Nodes
3
+ class Descending < Ordering
4
+
5
+ attr_accessor :nulls
6
+
7
+ def initialize expr, nulls=nil
8
+ super(expr)
9
+ @expr = expr
10
+ @nulls = nulls
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ # Ordering with :nulls_last, :nulls_first options
2
+ module Arel
3
+ module OrderPredications
4
+
5
+ def asc(nulls=nil)
6
+ Nodes::Ascending.new self, nulls
7
+ end
8
+
9
+ def desc(nulls=nil)
10
+ Nodes::Descending.new self, nulls
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module Arel
2
+ module Visitors
3
+ class PostgreSQL
4
+ private
5
+
6
+ def visit_Arel_Nodes_Ascending o, collector
7
+ case o.nulls
8
+ when :nulls_first then visit(o.expr, collector) << ' ASC NULLS FIRST'
9
+ when :nulls_last then visit(o.expr, collector) << ' ASC NULLS LAST'
10
+ else visit(o.expr, collector) << ' ASC'
11
+ end
12
+ end
13
+
14
+ def visit_Arel_Nodes_Descending o, collector
15
+ case o.nulls
16
+ when :nulls_first then visit(o.expr, collector) << ' DESC NULLS FIRST'
17
+ when :nulls_last then visit(o.expr, collector) << ' DESC NULLS LAST'
18
+ else visit(o.expr, collector) << ' DESC'
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ require 'active_record'
2
+
3
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/order_predications'))
4
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/nodes/ascending'))
5
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/nodes/descending'))
6
+ require File.expand_path(File.join(__FILE__, '../../../ext/arel/visitors/postgresql'))
7
+ require File.expand_path(File.join(__FILE__, '../../../ext/active_record/base'))
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module Sort
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-sort
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Bracy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
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: rake
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: minitest
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: minitest-reporters
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: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_girl_rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: faker
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: A safe way to accept user parameters and order against your ActiveRecord
140
+ Models
141
+ email:
142
+ - jonbracy@gmail.com
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files:
146
+ - README.md
147
+ files:
148
+ - README.md
149
+ - ext/active_record/base.rb
150
+ - ext/arel/nodes/ascending.rb
151
+ - ext/arel/nodes/descending.rb
152
+ - ext/arel/order_predications.rb
153
+ - ext/arel/visitors/postgresql.rb
154
+ - lib/active_record/sort.rb
155
+ - lib/active_record/sort/version.rb
156
+ homepage: https://github.com/malomalo/activerecord-sort
157
+ licenses:
158
+ - MIT
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options:
162
+ - "--main"
163
+ - README.md
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubyforge_project:
178
+ rubygems_version: 2.4.5
179
+ signing_key:
180
+ specification_version: 4
181
+ summary: A safe way to accept user parameters and order against your ActiveRecord
182
+ Models
183
+ test_files: []