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 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