data_tables-responder 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b8e8b8bde92df9cf464672c0272403a5b10025e
4
- data.tar.gz: f777b05dc78a0b3e2e5cc6cbeeb021069502b162
3
+ metadata.gz: e79c11cbef86746b623368d109260dbc13752ba5
4
+ data.tar.gz: 7420babe2bad5e577d259f337d52edce56c6c54b
5
5
  SHA512:
6
- metadata.gz: a50cabb76cb4539b913fd7a4d839fec3400dfa3a3862a51a1a0106234b2dd4c81a225abe823670ffc300eba6edee6e690ff64d9c47e575c7ab2b8f51402f1927
7
- data.tar.gz: d6a683c1f43ad56869ec4d4adcfed6aec6a785c898e84f57ae9d742f38444632486bb08ecf4465a2f62014b8ef429313f4c1a626e322a1b28827c2467c513196
6
+ metadata.gz: 628bb80e343d030ed42a07735b38c841231cc9b14c3b74dede6e308af88e97b073e38e53aa469b829b7999ca7654c537b54a187b695906d4af530e21df27b02d
7
+ data.tar.gz: 0049ae6598ae3ac3eaa0bd1c15d343f49f72cf99264434f96e5dae80375e293e25c8bb56bd14109e66ccd88d85dedc4b0606dd86c4426c5c5b5131663880fa30
@@ -26,9 +26,14 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ['lib']
28
28
 
29
+ rails_versions = ['>= 4.1', '< 6']
30
+
29
31
  spec.add_dependency 'active_model_serializers', '~> 0.10.4'
30
- spec.add_dependency 'count_estimate'
32
+ spec.add_dependency 'railties', rails_versions
33
+ spec.add_dependency 'quick_count', ['>= 0.0.3', '< 0.1.0']
31
34
 
35
+ spec.add_development_dependency 'activerecord', rails_versions
36
+ spec.add_development_dependency 'pry-byebug'
32
37
  spec.add_development_dependency 'bundler', '~> 1.12'
33
38
  spec.add_development_dependency 'rake', '~> 10.0'
34
39
  spec.add_development_dependency 'rspec', '~> 3.0'
@@ -29,15 +29,16 @@ module DataTables
29
29
  private
30
30
 
31
31
  def get_records_filtered
32
- if records_total < 1_000_000
33
- @collection.unscope(:limit, :offset).count(@collection.model.primary_key).to_i
32
+ to_filter = @collection.unscope(:limit, :offset)
33
+ if !to_filter.respond_to?(:count_estimate) || records_total < 1_000_000
34
+ to_filter.count(@collection.model.primary_key).to_i
34
35
  else
35
- @collection.unscope(:limit, :offset).count_estimate.to_i
36
+ to_filter.count_estimate.to_i
36
37
  end
37
38
  end
38
39
 
39
40
  def get_records_total
40
- count = @collection.model.all.count_estimate.to_i
41
+ count = @collection.model.quick_count
41
42
  if count < 1_000_000
42
43
  count = @collection.model.all.count(@collection.model.primary_key).to_i
43
44
  end
@@ -0,0 +1,63 @@
1
+ module DataTables
2
+ module Modules
3
+ class Order
4
+
5
+ attr_reader :scope, :context
6
+
7
+ def initialize(scope, request_parameters)
8
+ @scope = scope.dup
9
+ @request_parameters = request_parameters
10
+ end
11
+
12
+ def order
13
+ # default_order = @request_parameters.dig(:order, :value)
14
+
15
+ model = @scope.try(:model) || @scope
16
+ columns = orderable_columns(@request_parameters[:order], @request_parameters[:columns])
17
+
18
+ orders = DataTables::Responder.flat_keys_to_nested columns
19
+
20
+ order_by, join_hash = build_order(model, orders)
21
+
22
+ @scope = @scope.joins(join_hash)
23
+
24
+ order_by.inject(@scope) { |r, o| r.order(o) }
25
+ end
26
+
27
+ def build_order(model, in_hash, join_hash = nil)
28
+ # Tuple!
29
+ return in_hash.inject([]) { |sum, (k, h)|
30
+ case h
31
+ when Hash
32
+ if (klass = model.reflect_on_association(k).try(:klass))
33
+
34
+ new_sum, join_class = build_order(klass, h)
35
+
36
+ join_hash = join_class.nil? ? [k] : {k => join_class}
37
+
38
+ sum += new_sum
39
+ else
40
+ warn("trying to reflect on #{k} but #{model.class.name} has no such association.")
41
+ end
42
+ else
43
+ sum << model.arel_table[k].send(h) if model.column_names.include?(k.to_s)
44
+ end
45
+ sum
46
+ }, join_hash
47
+ end
48
+
49
+ protected
50
+
51
+ def orderable_columns(orders, columns)
52
+ sums = {}
53
+ (orders || []).inject(sums) do |sum, order|
54
+ if (name = columns[order[:column]][:data]).present?
55
+ sum[name] = order[:dir]
56
+ end
57
+ end
58
+ sums
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -1,4 +1,3 @@
1
- require 'count_estimate'
2
1
 
3
2
  module DataTables
4
3
  module Modules
@@ -2,67 +2,71 @@ module DataTables
2
2
  module Modules
3
3
  class Search
4
4
 
5
- attr_reader :collection, :context
5
+ attr_reader :scope, :context
6
6
 
7
- def initialize(collection, request_parameters)
8
- @collection = collection
7
+ def initialize(scope, request_parameters)
8
+ @scope = scope
9
9
  @request_parameters = request_parameters
10
10
  end
11
11
 
12
12
  def search
13
13
  default_search = @request_parameters.dig(:search, :value)
14
14
 
15
- model = @collection.try(:model) || @collection
16
- arel_table = model.arel_table
15
+ model = @scope.try(:model) || @scope
17
16
  columns = searchable_columns(default_search)
18
17
 
19
18
  searches = DataTables::Responder.flat_keys_to_nested columns
20
19
 
21
- search_by = build_search(model, searches)
20
+ search_by, join_hash = build_search(model, searches)
22
21
 
23
- @collection.where(search_by.reduce(:and))
24
- end
22
+ @scope = @scope.joins(join_hash)
25
23
 
26
- def build_search(model, searches)
27
- # join_type = Arel::Nodes::OuterJoin
28
- join_type = Arel::Nodes::InnerJoin
24
+ @scope.where(search_by.reduce(:and))
25
+ end
29
26
 
30
- searches.inject([]) do |queries, junk|
31
- column, query = junk
27
+ def build_search(model, in_hash, join_hash = nil)
28
+ # Tuple!
29
+ return in_hash.inject([]) { |queries, (column, query)|
32
30
  case query
33
31
  when Hash
34
- assoc = model.reflect_on_association(column)
35
- assoc_klass = assoc.klass
36
-
37
- join = join_type.new(assoc_klass.arel_table,
38
- Arel::Nodes::On.new(
39
- model.arel_table[assoc.foreign_key].eq(assoc_klass.arel_table[assoc.active_record_primary_key])
40
- ))
41
- @collection = @collection.joins(join)
42
- queries << build_search(assoc_klass, query).reduce(:and)
32
+ if (assoc = model.reflect_on_association(column))
33
+ new_queries, join_class = build_search(assoc.klass, query)
34
+
35
+ join_hash = join_class.nil? ? [column] : {column => join_class}
36
+
37
+ queries << new_queries.reduce(:and)
38
+ else
39
+ warn("trying to reflect on #{column} but #{model.class.name} has no such association.")
40
+ end
43
41
  else
44
- col_s = column.to_s
45
- case (k = model.columns.find(nil) { |c| c.name == col_s })&.type
46
- when :string
47
- # I'm pretty sure this is safe from SQL Injection
48
- queries << model.arel_table[k.name].matches("%#{query}%")
49
- when :integer
50
- if value = query&.to_i
51
- queries << model.arel_table[k.name].eq(value)
52
- end
53
- when :datetime
54
- datetime = Time.parse(query)
55
- range = (datetime-1.second)..(datetime+1.second)
56
- queries << model.arel_table[k.name].between(range)
42
+ search_by_type(model, column, query) do |result|
43
+ queries << result
57
44
  end
58
45
  end
59
-
60
46
  queries
61
- end
47
+ }, join_hash
62
48
  end
63
49
 
64
50
  protected
65
51
 
52
+ def search_by_type(model, column, query, &block)
53
+ result = case model.columns_hash[column.to_s]&.type
54
+ when :string
55
+ # I'm pretty sure this is safe from SQL Injection
56
+ model.arel_table[column].matches("%#{query}%")
57
+ when :integer
58
+ model.arel_table[column].eq(value) if value = query&.to_i
59
+ when :datetime
60
+ datetime = Time.parse(query)
61
+ range = (datetime-1.second)..(datetime+1.second)
62
+ model.arel_table[column].between(range)
63
+ end
64
+
65
+ yield(result) if !result.nil? && block_given?
66
+
67
+ result
68
+ end
69
+
66
70
  def searchable_columns(default_search)
67
71
  @searchable_columns = {}
68
72
  @request_parameters[:columns]&.inject(@searchable_columns) do |a, b|
@@ -77,8 +81,6 @@ module DataTables
77
81
  @searchable_columns
78
82
  end
79
83
 
80
- private
81
-
82
84
  end
83
85
  end
84
86
  end
@@ -1,6 +1,7 @@
1
1
  require 'rails/railtie'
2
2
  require 'action_controller'
3
3
  require 'action_controller/railtie'
4
+ require 'quick_count/railtie'
4
5
 
5
6
  module DataTables
6
7
  module Responder
@@ -1,5 +1,5 @@
1
1
  module DataTables
2
2
  module Responder
3
- VERSION = '0.3.2'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -1,7 +1,9 @@
1
+ require 'data_tables'
1
2
  require "data_tables/responder/version"
2
3
 
3
4
  require 'data_tables/modules/pagination'
4
5
  require 'data_tables/modules/search'
6
+ require 'data_tables/modules/order'
5
7
 
6
8
  require 'data_tables/active_model_serializers/adapter'
7
9
  require 'data_tables/responder/railtie' if defined? ::Rails::Railtie
@@ -12,26 +14,14 @@ module DataTables
12
14
  def self.respond(original_scope, params)
13
15
  model = original_scope.try(:model) || original_scope
14
16
 
15
- filtered_results = original_scope&.dup || model.none
16
- hashed_orders = transmute_datatable_order(params[:order], params[:columns])
17
- orders = flat_keys_to_nested hashed_orders
17
+ filtered_scope = original_scope&.dup || model.none
18
18
 
19
- order_by = orders.collect do |k, order|
20
- if order.is_a? Hash
21
- if (klass = model.reflect_on_association(k).try(:klass))
22
- filtered_results = filtered_results.joins(k)
23
- klass.arel_table[order.first.first].send(order.first.last)
24
- end
25
- else
26
- { k => order }
27
- end
28
- end
19
+ filtered_scope = order(filtered_scope, params)
29
20
 
30
- filtered_results = search(filtered_results, params)
21
+ filtered_scope = search(filtered_scope, params)
31
22
 
32
23
  # Rails.logger.warn "SEARCH BY: #{search_by}"
33
- filtered_results = order_by.inject(filtered_results) { |r, o| r.order(o) }
34
- filtered_results = paginate(original_scope, filtered_results, params)
24
+ filtered_scope = paginate(original_scope, filtered_scope, params)
35
25
  end
36
26
 
37
27
  def self.flat_keys_to_nested(hash)
@@ -42,27 +32,17 @@ module DataTables
42
32
  end
43
33
  end
44
34
 
45
-
46
- def self.paginate(original_scope, filtered_results, params)
47
- Modules::Pagination.new(original_scope, filtered_results, params).paginate
35
+ def self.paginate(original_scope, filtered_scope, params)
36
+ Modules::Pagination.new(original_scope, filtered_scope, params).paginate
48
37
  end
49
38
 
50
- def self.search(filtered_results, params)
51
- Modules::Search.new(filtered_results, params).search
39
+ def self.search(filtered_scope, params)
40
+ Modules::Search.new(filtered_scope, params).search
52
41
  end
53
42
 
54
- def self.transmute_datatable_order(orders, columns)
55
- Hash[if orders.is_a? Array
56
- orders.collect do |order|
57
- if (name = columns[order[:column]][:data]).present?
58
- [name, order[:dir]]
59
- else
60
- nil
61
- end
62
- end
63
- else
64
- []
65
- end.compact]
43
+ def self.order(filtered_scope, params)
44
+ Modules::Order.new(filtered_scope, params).order
66
45
  end
46
+
67
47
  end
68
48
  end
@@ -0,0 +1,6 @@
1
+
2
+ module DataTables
3
+ def self.root
4
+ @root ||= Pathname.new(File.dirname(File.expand_path(File.dirname(__FILE__), '/../')))
5
+ end
6
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_tables-responder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Stevens
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-01 00:00:00.000000000 Z
11
+ date: 2017-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -25,14 +25,74 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.10.4
27
27
  - !ruby/object:Gem::Dependency
28
- name: count_estimate
28
+ name: railties
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '4.1'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '6'
34
37
  type: :runtime
35
38
  prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '4.1'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: quick_count
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 0.0.3
54
+ - - "<"
55
+ - !ruby/object:Gem::Version
56
+ version: 0.1.0
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.0.3
64
+ - - "<"
65
+ - !ruby/object:Gem::Version
66
+ version: 0.1.0
67
+ - !ruby/object:Gem::Dependency
68
+ name: activerecord
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '4.1'
74
+ - - "<"
75
+ - !ruby/object:Gem::Version
76
+ version: '6'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '4.1'
84
+ - - "<"
85
+ - !ruby/object:Gem::Version
86
+ version: '6'
87
+ - !ruby/object:Gem::Dependency
88
+ name: pry-byebug
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ type: :development
95
+ prerelease: false
36
96
  version_requirements: !ruby/object:Gem::Requirement
37
97
  requirements:
38
98
  - - ">="
@@ -96,10 +156,12 @@ files:
96
156
  - bin/console
97
157
  - bin/setup
98
158
  - data_tables-responder.gemspec
159
+ - lib/data_tables.rb
99
160
  - lib/data_tables/active_model_serializers/adapter.rb
100
161
  - lib/data_tables/active_model_serializers/adapter/meta.rb
101
162
  - lib/data_tables/active_model_serializers/adapter/pagination.rb
102
163
  - lib/data_tables/active_model_serializers/register_dt_renderer.rb
164
+ - lib/data_tables/modules/order.rb
103
165
  - lib/data_tables/modules/pagination.rb
104
166
  - lib/data_tables/modules/search.rb
105
167
  - lib/data_tables/responder.rb