active-record-data-tables 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
+ gem "string-cases"
7
+
6
8
  # Add dependencies to develop your gem here.
7
9
  # Include everything needed to run rake, tests, features, etc.
8
10
  group :development do
data/Gemfile.lock CHANGED
@@ -20,6 +20,7 @@ GEM
20
20
  rspec-expectations (2.8.0)
21
21
  diff-lcs (~> 1.1.2)
22
22
  rspec-mocks (2.8.0)
23
+ string-cases (0.0.0)
23
24
 
24
25
  PLATFORMS
25
26
  ruby
@@ -29,3 +30,4 @@ DEPENDENCIES
29
30
  jeweler (~> 1.8.4)
30
31
  rdoc (~> 3.12)
31
32
  rspec (~> 2.8.0)
33
+ string-cases
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.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
- @obj = @args[:model]
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
- disp_start = @params["iDisplayStart"].to_i
18
- disp_length = @params["iDisplayLength"].to_i
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 = @params[name]
93
+ sort_col = @dts[name_col]
29
94
  break if !sort_col
30
95
 
31
- col_name = @columns[name_col]
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
- sorts << "`#{escape_col(col_name)}` #{sort_mode}"
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
- @obj = @obj.order(sorts.join(" "))
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_+]\Z/)
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.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-03 00:00:00.000000000 Z
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: 344081574259786733
129
+ hash: 2526805225709928991
113
130
  version: '0'
114
131
  required_rubygems_version: !ruby/object:Gem::Requirement
115
132
  none: false