ajax-datatables-rails 0.4.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.travis.yml +6 -41
  4. data/Appraisals +0 -8
  5. data/CHANGELOG.md +8 -1
  6. data/README.md +152 -26
  7. data/ajax-datatables-rails.gemspec +3 -4
  8. data/doc/migrate.md +53 -0
  9. data/lib/ajax-datatables-rails/active_record.rb +7 -0
  10. data/lib/ajax-datatables-rails/base.rb +7 -23
  11. data/lib/ajax-datatables-rails/config.rb +3 -6
  12. data/lib/ajax-datatables-rails/datatable/column.rb +18 -13
  13. data/lib/ajax-datatables-rails/datatable/column/date_filter.rb +10 -20
  14. data/lib/ajax-datatables-rails/datatable/column/order.rb +1 -1
  15. data/lib/ajax-datatables-rails/datatable/column/search.rb +29 -20
  16. data/lib/ajax-datatables-rails/datatable/datatable.rb +1 -7
  17. data/lib/ajax-datatables-rails/datatable/simple_order.rb +4 -2
  18. data/lib/ajax-datatables-rails/datatable/simple_search.rb +2 -0
  19. data/lib/ajax-datatables-rails/version.rb +1 -1
  20. data/lib/ajax_datatables_rails.rb +2 -1
  21. data/lib/generators/datatable/config_generator.rb +4 -4
  22. data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +0 -3
  23. data/lib/generators/rails/templates/datatable.rb +1 -1
  24. data/spec/ajax-datatables-rails/base_spec.rb +81 -41
  25. data/spec/ajax-datatables-rails/configuration_spec.rb +0 -9
  26. data/spec/ajax-datatables-rails/datatable/column_spec.rb +58 -12
  27. data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +1 -2
  28. data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +2 -3
  29. data/spec/ajax-datatables-rails/extended_spec.rb +1 -2
  30. data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +84 -137
  31. data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +1 -2
  32. data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +4 -5
  33. data/spec/ajax-datatables-rails/orm/active_record_spec.rb +3 -4
  34. data/spec/spec_helper.rb +0 -2
  35. data/spec/support/datatable_cond_numeric.rb +1 -1
  36. data/spec/support/datatable_cond_string.rb +1 -1
  37. data/spec/support/test_helpers.rb +1 -1
  38. metadata +8 -8
  39. data/gemfiles/rails_4.0.13.gemfile +0 -14
  40. data/gemfiles/rails_4.1.16.gemfile +0 -14
@@ -0,0 +1,53 @@
1
+ ## To migrate from `v0.4.x` to `v1.0.0`
2
+
3
+ 1) To mitigate the first change (Datatables no longer inherits from `AjaxDatatablesRails::Base` but from `AjaxDatatablesRails::ActiveRecord`)
4
+
5
+ Create a new `ApplicationDatatable` class and make all your classes inherits from it :
6
+
7
+ ```ruby
8
+ class ApplicationDatatable < AjaxDatatablesRails::ActiveRecord
9
+ end
10
+
11
+ class PostDatatable < ApplicationDatatable
12
+ end
13
+ ```
14
+
15
+ **Note :** This is now in the [ProTips™](https://github.com/jbox-web/ajax-datatables-rails#protips) section of the documentation.
16
+
17
+ 2) To mitigate the second change (The `view_context` is no longer injected in Datatables)
18
+
19
+ Update the `ApplicationDatatable` class :
20
+
21
+ ```ruby
22
+ class ApplicationDatatable < AjaxDatatablesRails::ActiveRecord
23
+ extend Forwardable
24
+ attr_reader :view
25
+ def initialize(params, opts = {})
26
+ @view = opts[:view_context]
27
+ super
28
+ end
29
+ end
30
+ ```
31
+
32
+ and update your controllers :
33
+
34
+ ```ruby
35
+ # before
36
+ respond_to do |format|
37
+ format.json { render json: UserDatatable.new(view_context) }
38
+ end
39
+
40
+ # after
41
+ respond_to do |format|
42
+ format.json { render json: UserDatatable.new(params, view_context: view_context) }
43
+ end
44
+
45
+ # if you need to inject some options
46
+ respond_to do |format|
47
+ format.json { render json: UserDatatable.new(params, view_context: view_context, my: 'options') }
48
+ end
49
+ ```
50
+
51
+ This way, you can still use `def_delegators` in your datatables [as in the documentation](https://github.com/jbox-web/ajax-datatables-rails#using-view-helpers).
52
+
53
+ Note that the recommanded way is to use [Draper gem](https://github.com/drapergem/draper) to separate filtering logic from view/presentation logic [as in the documentation](https://github.com/jbox-web/ajax-datatables-rails#using-view-decorators).
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AjaxDatatablesRails
4
+ class ActiveRecord < AjaxDatatablesRails::Base
5
+ include AjaxDatatablesRails::ORM::ActiveRecord
6
+ end
7
+ end
@@ -2,21 +2,15 @@
2
2
 
3
3
  module AjaxDatatablesRails
4
4
  class Base
5
- extend Forwardable
6
5
 
7
- attr_reader :view, :options
8
- def_delegator :@view, :params
6
+ attr_reader :params, :options, :datatable
9
7
 
10
8
  GLOBAL_SEARCH_DELIMITER = ' '
11
9
 
12
- def initialize(view, options = {})
13
- @view = view
14
- @options = options
15
- load_orm_extension
16
- end
17
-
18
- def datatable
19
- @datatable ||= Datatable::Datatable.new(self)
10
+ def initialize(params, options = {})
11
+ @params = params
12
+ @options = options
13
+ @datatable = Datatable::Datatable.new(self)
20
14
  end
21
15
 
22
16
  def view_columns
@@ -37,9 +31,9 @@ module AjaxDatatablesRails
37
31
 
38
32
  def as_json(*)
39
33
  {
40
- recordsTotal: records_total_count,
34
+ recordsTotal: records_total_count,
41
35
  recordsFiltered: records_filtered_count,
42
- data: sanitize(data)
36
+ data: sanitize(data)
43
37
  }.merge(get_additional_data)
44
38
  end
45
39
 
@@ -113,16 +107,6 @@ module AjaxDatatablesRails
113
107
  filter_records(fetch_records).count(:all)
114
108
  end
115
109
 
116
- # Private helper methods
117
- def load_orm_extension
118
- case AjaxDatatablesRails.config.orm
119
- when :active_record
120
- extend ORM::ActiveRecord
121
- when :mongoid
122
- nil
123
- end
124
- end
125
-
126
110
  def global_search_delimiter
127
111
  GLOBAL_SEARCH_DELIMITER
128
112
  end
@@ -4,10 +4,12 @@ require 'active_support/configurable'
4
4
 
5
5
  module AjaxDatatablesRails
6
6
 
7
- # configure AjaxDatatablesRails global settings
7
+ # Configure AjaxDatatablesRails global settings
8
+ #
8
9
  # AjaxDatatablesRails.configure do |config|
9
10
  # config.db_adapter = :postgresql
10
11
  # end
12
+
11
13
  def self.configure
12
14
  yield @config ||= AjaxDatatablesRails::Configuration.new
13
15
  end
@@ -17,14 +19,9 @@ module AjaxDatatablesRails
17
19
  @config ||= AjaxDatatablesRails::Configuration.new
18
20
  end
19
21
 
20
- def self.old_rails?
21
- Rails::VERSION::MAJOR == 4 && (Rails::VERSION::MINOR == 1 || Rails::VERSION::MINOR == 0)
22
- end
23
-
24
22
  class Configuration
25
23
  include ActiveSupport::Configurable
26
24
 
27
- config_accessor(:orm) { :active_record }
28
25
  config_accessor(:db_adapter) { :postgresql }
29
26
  config_accessor(:nulls_last) { false }
30
27
  end
@@ -4,13 +4,18 @@ module AjaxDatatablesRails
4
4
  module Datatable
5
5
  class Column
6
6
 
7
+ TYPE_CAST_DEFAULT = 'VARCHAR'
8
+ TYPE_CAST_MYSQL = 'CHAR'
9
+ TYPE_CAST_SQLITE = 'TEXT'
10
+ TYPE_CAST_ORACLE = 'VARCHAR2(4000)'
11
+
7
12
  DB_ADAPTER_TYPE_CAST = {
8
- mysql: 'CHAR',
9
- mysql2: 'CHAR',
10
- sqlite: 'TEXT',
11
- sqlite3: 'TEXT',
12
- oracle: 'VARCHAR2(4000)',
13
- oracleenhanced: 'VARCHAR2(4000)'
13
+ mysql: TYPE_CAST_MYSQL,
14
+ mysql2: TYPE_CAST_MYSQL,
15
+ sqlite: TYPE_CAST_SQLITE,
16
+ sqlite3: TYPE_CAST_SQLITE,
17
+ oracle: TYPE_CAST_ORACLE,
18
+ oracleenhanced: TYPE_CAST_ORACLE
14
19
  }.freeze
15
20
 
16
21
  attr_reader :datatable, :index, :options
@@ -18,7 +23,7 @@ module AjaxDatatablesRails
18
23
 
19
24
  include Search
20
25
  include Order
21
- prepend DateFilter unless AjaxDatatablesRails.old_rails?
26
+ include DateFilter
22
27
 
23
28
 
24
29
  def initialize(datatable, index, options)
@@ -52,20 +57,20 @@ module AjaxDatatablesRails
52
57
  !source.include?('.')
53
58
  end
54
59
 
55
- # Add formater option to allow modification of the value
60
+ # Add formatter option to allow modification of the value
56
61
  # before passing it to the database
57
- def formater
58
- @view_column[:formater]
62
+ def formatter
63
+ @view_column[:formatter]
59
64
  end
60
65
 
61
- def formated_value
62
- formater ? formater.call(search.value) : search.value
66
+ def formatted_value
67
+ formatter ? formatter.call(search.value) : search.value
63
68
  end
64
69
 
65
70
  private
66
71
 
67
72
  def type_cast
68
- @type_cast ||= (DB_ADAPTER_TYPE_CAST[AjaxDatatablesRails.config.db_adapter] || 'VARCHAR')
73
+ @type_cast ||= DB_ADAPTER_TYPE_CAST.fetch(AjaxDatatablesRails.config.db_adapter, TYPE_CAST_DEFAULT)
69
74
  end
70
75
 
71
76
  def casted_column
@@ -5,6 +5,8 @@ module AjaxDatatablesRails
5
5
  class Column
6
6
  module DateFilter
7
7
 
8
+ RANGE_DELIMITER = '-'
9
+
8
10
  class DateRange
9
11
  attr_reader :begin, :end
10
12
 
@@ -20,23 +22,23 @@ module AjaxDatatablesRails
20
22
 
21
23
  # Add delimiter option to handle range search
22
24
  def delimiter
23
- @view_column[:delimiter] || '-'
24
- end
25
-
26
- def empty_range_search?
27
- (formated_value == delimiter) || (range_start.blank? && range_end.blank?)
25
+ @delimiter ||= @view_column.fetch(:delimiter, RANGE_DELIMITER)
28
26
  end
29
27
 
30
28
  # A range value is in form '<range_start><delimiter><range_end>'
31
29
  # This returns <range_start>
32
30
  def range_start
33
- @range_start ||= formated_value.split(delimiter)[0]
31
+ @range_start ||= formatted_value.split(delimiter)[0]
34
32
  end
35
33
 
36
34
  # A range value is in form '<range_start><delimiter><range_end>'
37
35
  # This returns <range_end>
38
36
  def range_end
39
- @range_end ||= formated_value.split(delimiter)[1]
37
+ @range_end ||= formatted_value.split(delimiter)[1]
38
+ end
39
+
40
+ def empty_range_search?
41
+ (formatted_value == delimiter) || (range_start.blank? && range_end.blank?)
40
42
  end
41
43
 
42
44
  # Do a range search
@@ -47,14 +49,6 @@ module AjaxDatatablesRails
47
49
 
48
50
  private
49
51
 
50
- def non_regex_search
51
- if cond == :date_range
52
- date_range_search
53
- else
54
- super
55
- end
56
- end
57
-
58
52
  def range_start_casted
59
53
  range_start.blank? ? parse_date('01/01/1970') : parse_date(range_start)
60
54
  end
@@ -64,11 +58,7 @@ module AjaxDatatablesRails
64
58
  end
65
59
 
66
60
  def parse_date(date)
67
- if Time.zone
68
- Time.zone.parse(date)
69
- else
70
- Time.parse(date)
71
- end
61
+ Time.zone ? Time.zone.parse(date) : Time.parse(date)
72
62
  end
73
63
 
74
64
  end
@@ -11,7 +11,7 @@ module AjaxDatatablesRails
11
11
 
12
12
  # Add sort_field option to allow overriding of sort field
13
13
  def sort_field
14
- @view_column[:sort_field] || field
14
+ @view_column.fetch(:sort_field, field)
15
15
  end
16
16
 
17
17
  def sort_query
@@ -5,19 +5,21 @@ module AjaxDatatablesRails
5
5
  class Column
6
6
  module Search
7
7
 
8
- SMALLEST_PQ_INTEGER = -2147483648
9
- LARGEST_PQ_INTEGER = 2147483647
8
+ SMALLEST_PQ_INTEGER = -2_147_483_648
9
+ LARGEST_PQ_INTEGER = 2_147_483_647
10
+ NOT_NULL_VALUE = '!NULL'
11
+ EMPTY_VALUE = ''
10
12
 
11
13
  def searchable?
12
14
  @view_column.fetch(:searchable, true)
13
15
  end
14
16
 
15
17
  def cond
16
- @view_column[:cond] || :like
18
+ @view_column.fetch(:cond, :like)
17
19
  end
18
20
 
19
21
  def filter
20
- @view_column[:cond].call(self, formated_value)
22
+ @view_column[:cond].call(self, formatted_value)
21
23
  end
22
24
 
23
25
  def search
@@ -46,33 +48,37 @@ module AjaxDatatablesRails
46
48
  # The solution is to bypass regex_search and use non_regex_search with :in operator
47
49
  def regex_search
48
50
  if use_regex?
49
- ::Arel::Nodes::Regexp.new((custom_field? ? field : table[field]), ::Arel::Nodes.build_quoted(formated_value))
51
+ ::Arel::Nodes::Regexp.new((custom_field? ? field : table[field]), ::Arel::Nodes.build_quoted(formatted_value))
50
52
  else
51
53
  non_regex_search
52
54
  end
53
55
  end
54
56
 
57
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
55
58
  def non_regex_search
56
59
  case cond
57
60
  when Proc
58
61
  filter
59
62
  when :eq, :not_eq, :lt, :gt, :lteq, :gteq, :in
60
- is_searchable_integer? ? raw_search(cond) : empty_search
63
+ searchable_integer? ? raw_search(cond) : empty_search
61
64
  when :null_value
62
65
  null_value_search
63
66
  when :start_with
64
- casted_column.matches("#{formated_value}%")
67
+ casted_column.matches("#{formatted_value}%")
65
68
  when :end_with
66
- casted_column.matches("%#{formated_value}")
69
+ casted_column.matches("%#{formatted_value}")
67
70
  when :like
68
- casted_column.matches("%#{formated_value}%")
71
+ casted_column.matches("%#{formatted_value}%")
69
72
  when :string_eq
70
73
  raw_search(:eq)
74
+ when :date_range
75
+ date_range_search
71
76
  end
72
77
  end
78
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
73
79
 
74
80
  def null_value_search
75
- if formated_value == '!NULL'
81
+ if formatted_value == NOT_NULL_VALUE
76
82
  table[field].not_eq(nil)
77
83
  else
78
84
  table[field].eq(nil)
@@ -81,31 +87,34 @@ module AjaxDatatablesRails
81
87
 
82
88
  def raw_search(cond)
83
89
  if custom_field?
84
- ::Arel::Nodes::SqlLiteral.new(field).eq(formated_value)
90
+ ::Arel::Nodes::SqlLiteral.new(field).eq(formatted_value)
85
91
  else
86
- table[field].send(cond, formated_value)
92
+ table[field].send(cond, formatted_value)
87
93
  end
88
94
  end
89
95
 
90
96
  def empty_search
91
- casted_column.matches('')
97
+ casted_column.matches(EMPTY_VALUE)
92
98
  end
93
99
 
94
- def is_searchable_integer?
95
- if formated_value.is_a?(Array)
96
- valids = formated_value.map { |v| is_integer?(v) && !is_out_of_range?(v) }
100
+ def searchable_integer?
101
+ if formatted_value.is_a?(Array)
102
+ valids = formatted_value.map { |v| integer?(v) && !out_of_range?(v) }
97
103
  !valids.include?(false)
98
104
  else
99
- is_integer?(formated_value) && !is_out_of_range?(formated_value)
105
+ integer?(formatted_value) && !out_of_range?(formatted_value)
100
106
  end
101
107
  end
102
108
 
103
- def is_out_of_range?(search_value)
109
+ def out_of_range?(search_value)
104
110
  Integer(search_value) > LARGEST_PQ_INTEGER || Integer(search_value) < SMALLEST_PQ_INTEGER
105
111
  end
106
112
 
107
- def is_integer?(string)
108
- true if Integer(string) rescue false
113
+ def integer?(string)
114
+ Integer(string)
115
+ true
116
+ rescue ArgumentError
117
+ false
109
118
  end
110
119
 
111
120
  end
@@ -3,8 +3,6 @@
3
3
  module AjaxDatatablesRails
4
4
  module Datatable
5
5
 
6
- TRUE_VALUE = 'true'
7
-
8
6
  class Datatable
9
7
  attr_reader :datatable, :options
10
8
 
@@ -70,11 +68,7 @@ module AjaxDatatablesRails
70
68
  end
71
69
 
72
70
  def get_param(param)
73
- if AjaxDatatablesRails.old_rails?
74
- options[param]
75
- else
76
- options[param].to_unsafe_h.with_indifferent_access
77
- end
71
+ options[param].to_unsafe_h.with_indifferent_access
78
72
  end
79
73
 
80
74
  end
@@ -4,7 +4,9 @@ module AjaxDatatablesRails
4
4
  module Datatable
5
5
  class SimpleOrder
6
6
 
7
- DIRECTIONS = %w[DESC ASC].freeze
7
+ DIRECTION_ASC = 'ASC'
8
+ DIRECTION_DESC = 'DESC'
9
+ DIRECTIONS = [DIRECTION_ASC, DIRECTION_DESC].freeze
8
10
 
9
11
  def initialize(datatable, options = {})
10
12
  @datatable = datatable
@@ -24,7 +26,7 @@ module AjaxDatatablesRails
24
26
  end
25
27
 
26
28
  def direction
27
- DIRECTIONS.find { |dir| dir == column_direction } || 'ASC'
29
+ DIRECTIONS.find { |dir| dir == column_direction } || DIRECTION_ASC
28
30
  end
29
31
 
30
32
  private
@@ -4,6 +4,8 @@ module AjaxDatatablesRails
4
4
  module Datatable
5
5
  class SimpleSearch
6
6
 
7
+ TRUE_VALUE = 'true'
8
+
7
9
  def initialize(options = {})
8
10
  @options = options
9
11
  end