active-record-data-tables 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/Gemfile.lock +2 -0
- data/VERSION +1 -1
- data/active-record-data-tables.gemspec +63 -0
- data/lib/active-record-data-tables.rb +106 -9
- metadata +20 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "active-record-data-tables"
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["kaspernj"]
|
12
|
+
s.date = "2013-06-04"
|
13
|
+
s.description = "Helping functionality for filtering, sorting and stuff like that with data-tables and ActiveRecord."
|
14
|
+
s.email = "k@spernj.org"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"active-record-data-tables.gemspec",
|
29
|
+
"lib/active-record-data-tables.rb",
|
30
|
+
"spec/active-record-data-tables_spec.rb",
|
31
|
+
"spec/spec_helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = "http://github.com/kaspernj/active-record-data-tables"
|
34
|
+
s.licenses = ["MIT"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = "1.8.23"
|
37
|
+
s.summary = "Helping functionality for filtering, sorting and stuff like that with data-tables and ActiveRecord."
|
38
|
+
|
39
|
+
if s.respond_to? :specification_version then
|
40
|
+
s.specification_version = 3
|
41
|
+
|
42
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<string-cases>, [">= 0"])
|
44
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
45
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
46
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
47
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<string-cases>, [">= 0"])
|
50
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
51
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
52
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
53
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<string-cases>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
58
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
59
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
60
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -1,21 +1,85 @@
|
|
1
|
+
require "string-cases"
|
2
|
+
|
1
3
|
class ActiveRecordDataTables
|
2
4
|
def initialize(args)
|
3
5
|
@args = args
|
4
6
|
@params = @args[:params]
|
7
|
+
@filter_params = @args[:filter_params]
|
8
|
+
@force_filter_for = @args[:force_filter_for]
|
9
|
+
@dts = @params[:dataTables]
|
5
10
|
@columns = @args[:columns]
|
11
|
+
|
12
|
+
@model = @args[:model]
|
13
|
+
raise "No ':model' was given." unless @model
|
14
|
+
@model_method_name = StringCases.camel_to_snake(@model.name)
|
15
|
+
|
16
|
+
@joins = {}
|
17
|
+
@sort_columns = [:title, :name]
|
18
|
+
@executed = false
|
6
19
|
end
|
7
20
|
|
8
21
|
def execute
|
9
|
-
@
|
22
|
+
@executed = true
|
23
|
+
@query = @model
|
24
|
+
|
25
|
+
filter
|
10
26
|
sorting
|
11
27
|
limit
|
28
|
+
|
29
|
+
return @query
|
30
|
+
end
|
31
|
+
|
32
|
+
def json(final_query = nil)
|
33
|
+
unless final_query
|
34
|
+
execute unless @executed
|
35
|
+
final_query = @query
|
36
|
+
end
|
37
|
+
|
38
|
+
dis_rec_count = final_query.limit(nil).count
|
39
|
+
dis_rec_count = dis_rec_count.length if dis_rec_count.is_a?(Hash)
|
40
|
+
|
41
|
+
res = {
|
42
|
+
:sEcho => @dts[:sEcho] ? @dts[:sEcho].to_i : 1,
|
43
|
+
:iTotalRecords => @model.count,
|
44
|
+
:iTotalDisplayRecords => dis_rec_count,
|
45
|
+
:aaData => []
|
46
|
+
}
|
12
47
|
end
|
13
48
|
|
14
49
|
private
|
15
50
|
|
51
|
+
def filter
|
52
|
+
@filter_params.each do |key, val|
|
53
|
+
if key.start_with?("#{@model_method_name}_")
|
54
|
+
key = key.slice(@model_method_name.length + 1, key.length)
|
55
|
+
end
|
56
|
+
|
57
|
+
if @force_filter_for && @force_filter_for.include?(key)
|
58
|
+
ret = @args[:filter].call(:key => key, :val => val, :query => @query)
|
59
|
+
@query = ret if ret
|
60
|
+
elsif @model.column_names.include?(key)
|
61
|
+
@query = @query.where(key => val)
|
62
|
+
elsif match = key.to_s.match(/^(.+)_like$/) and @model.column_names.include?(match[1])
|
63
|
+
next if val.blank?
|
64
|
+
table = @model.arel_table
|
65
|
+
@query = @query.where(table[match[1].to_sym].matches("%#{escape(val)}%"))
|
66
|
+
elsif @args[:filter]
|
67
|
+
ret = @args[:filter].call(:key => key, :val => val, :query => @query)
|
68
|
+
@query = ret if ret
|
69
|
+
else
|
70
|
+
raise "Dont know what to do regarding filter with key: '#{key}'."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
16
75
|
def limit
|
17
|
-
|
18
|
-
|
76
|
+
raise "'iDisplayStart' was not given? #{@dts}" unless @dts.key?("iDisplayStart")
|
77
|
+
raise "'iDisplayEnd' was not given? #{@dts}" unless @dts.key?("iDisplayLength")
|
78
|
+
|
79
|
+
disp_start = @dts["iDisplayStart"].to_i
|
80
|
+
disp_length = @dts["iDisplayLength"].to_i
|
81
|
+
|
82
|
+
@query = @query.page((disp_start / disp_length) + 1).per(disp_length)
|
19
83
|
end
|
20
84
|
|
21
85
|
def sorting
|
@@ -23,30 +87,63 @@ class ActiveRecordDataTables
|
|
23
87
|
sorts = []
|
24
88
|
|
25
89
|
loop do
|
90
|
+
sorted = false
|
26
91
|
name_col = "iSortCol_#{sort_no}"
|
27
92
|
name_mode = "sSortDir_#{sort_no}"
|
28
|
-
sort_col = @
|
93
|
+
sort_col = @dts[name_col]
|
29
94
|
break if !sort_col
|
30
95
|
|
31
|
-
col_name = @columns[
|
96
|
+
col_name = @columns[sort_col.to_i]
|
32
97
|
next if !col_name
|
33
98
|
|
34
|
-
if name_mode == "desc"
|
99
|
+
if @dts[name_mode] == "desc"
|
35
100
|
sort_mode = "DESC"
|
36
101
|
else
|
37
102
|
sort_mode = "ASC"
|
38
103
|
end
|
39
104
|
|
40
|
-
|
105
|
+
if match = col_name.to_s.match(/^(.+)_id$/)
|
106
|
+
method_name = match[1]
|
107
|
+
sub_model_name = StringCases.snake_to_camel(col_name.slice(0, col_name.length - 3))
|
108
|
+
|
109
|
+
if Kernel.const_defined?(sub_model_name)
|
110
|
+
sub_model_const = Kernel.const_get(sub_model_name)
|
111
|
+
unless @joins.key?(method_name)
|
112
|
+
@query = @query.includes(method_name)
|
113
|
+
@joins[method_name] = true
|
114
|
+
end
|
115
|
+
|
116
|
+
@sort_columns.each do |sort_col_name|
|
117
|
+
if sub_model_const.column_names.include?(sort_col_name.to_s)
|
118
|
+
sorts << "`#{sub_model_const.table_name}`.`#{escape_col(sort_col_name)}` #{sort_mode}"
|
119
|
+
sorted = true
|
120
|
+
break
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if @model.column_names.include?(col_name.to_s)
|
127
|
+
sorts << "`#{@model.table_name}`.`#{escape_col(col_name)}` #{sort_mode}"
|
128
|
+
elsif @args[:sort]
|
129
|
+
res = @args[:sort].call(:key => col_name, :sort_mode => sort_mode, :query => @query)
|
130
|
+
@query = res if res
|
131
|
+
else
|
132
|
+
raise "Unknown sort-column: '#{col_name}'."
|
133
|
+
end
|
41
134
|
|
42
135
|
sort_no += 1
|
43
136
|
end
|
44
137
|
|
45
|
-
@
|
138
|
+
@query = @query.order(sorts.join(", "))
|
139
|
+
end
|
140
|
+
|
141
|
+
def escape(str)
|
142
|
+
return ActiveRecord::Base.connection.quote(str).slice(1, str.length - 1)
|
46
143
|
end
|
47
144
|
|
48
145
|
def escape_col(name)
|
49
|
-
raise "Possible SQL injection hack: '#{name}'." unless name.to_s.match(/\A[A-z\d_
|
146
|
+
raise "Possible SQL injection hack: '#{name}'." unless name.to_s.match(/\A[A-z\d_]+\Z/)
|
50
147
|
return name
|
51
148
|
end
|
52
149
|
end
|
metadata
CHANGED
@@ -2,15 +2,31 @@
|
|
2
2
|
name: active-record-data-tables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- kaspernj
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
none: false
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
name: string-cases
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
version_requirements: !ruby/object:Gem::Requirement
|
16
32
|
none: false
|
@@ -92,6 +108,7 @@ files:
|
|
92
108
|
- README.rdoc
|
93
109
|
- Rakefile
|
94
110
|
- VERSION
|
111
|
+
- active-record-data-tables.gemspec
|
95
112
|
- lib/active-record-data-tables.rb
|
96
113
|
- spec/active-record-data-tables_spec.rb
|
97
114
|
- spec/spec_helper.rb
|
@@ -109,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
109
126
|
- !ruby/object:Gem::Version
|
110
127
|
segments:
|
111
128
|
- 0
|
112
|
-
hash:
|
129
|
+
hash: 2526805225709928991
|
113
130
|
version: '0'
|
114
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
132
|
none: false
|