datatables-net 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +73 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +618 -0
  6. data/Rakefile +14 -0
  7. data/lib/ajax-datatables-rails.rb +11 -0
  8. data/lib/ajax-datatables-rails/base.rb +205 -0
  9. data/lib/ajax-datatables-rails/config.rb +24 -0
  10. data/lib/ajax-datatables-rails/datatable/column.rb +106 -0
  11. data/lib/ajax-datatables-rails/datatable/datatable.rb +69 -0
  12. data/lib/ajax-datatables-rails/datatable/simple_order.rb +31 -0
  13. data/lib/ajax-datatables-rails/datatable/simple_search.rb +19 -0
  14. data/lib/ajax-datatables-rails/orm/active_record.rb +52 -0
  15. data/lib/ajax-datatables-rails/version.rb +3 -0
  16. data/lib/generators/datatable/config_generator.rb +17 -0
  17. data/lib/generators/datatable/templates/ajax_datatables_rails_config.rb +7 -0
  18. data/lib/generators/rails/datatable_generator.rb +27 -0
  19. data/lib/generators/rails/templates/datatable.rb +41 -0
  20. data/spec/ajax-datatables-rails/base_spec.rb +140 -0
  21. data/spec/ajax-datatables-rails/configuration_spec.rb +43 -0
  22. data/spec/ajax-datatables-rails/datatable/column_spec.rb +65 -0
  23. data/spec/ajax-datatables-rails/datatable/datatable_spec.rb +97 -0
  24. data/spec/ajax-datatables-rails/datatable/simple_order_spec.rb +12 -0
  25. data/spec/ajax-datatables-rails/datatable/simple_search_spec.rb +16 -0
  26. data/spec/ajax-datatables-rails/orm/active_record_filter_records_spec.rb +154 -0
  27. data/spec/ajax-datatables-rails/orm/active_record_paginate_records_spec.rb +51 -0
  28. data/spec/ajax-datatables-rails/orm/active_record_sort_records_spec.rb +42 -0
  29. data/spec/ajax-datatables-rails/orm/active_record_spec.rb +34 -0
  30. data/spec/schema.rb +43 -0
  31. data/spec/spec_helper.rb +10 -0
  32. data/spec/test_helpers.rb +66 -0
  33. data/spec/test_models.rb +20 -0
  34. metadata +202 -0
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::Datatable::SimpleOrder' do
4
+ let(:options) { ActiveSupport::HashWithIndifferentAccess.new({"column"=>"1", "dir"=>"desc"}) }
5
+ let(:simple_order) { AjaxDatatablesRails::Datatable::SimpleOrder.new nil, options }
6
+
7
+ describe 'option methods' do
8
+ it 'sql query' do
9
+ expect(simple_order.query('firstname')).to eq('firstname DESC')
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::Datatable::SimpleSearch' do
4
+ let(:options) { ActiveSupport::HashWithIndifferentAccess.new({"value"=>"search value", "regex"=>"true"}) }
5
+ let(:simple_search) { AjaxDatatablesRails::Datatable::SimpleSearch.new options }
6
+
7
+ describe 'option methods' do
8
+ it 'regexp?' do
9
+ expect(simple_search.regexp?).to be(true)
10
+ end
11
+
12
+ it 'value' do
13
+ expect(simple_search.value).to eq("search value")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::ORM::ActiveRecord#filter_records' do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { ComplexDatatable.new(view) }
6
+
7
+ before(:each) do
8
+ AjaxDatatablesRails.configure do |config|
9
+ config.db_adapter = :sqlite
10
+ config.orm = :active_record
11
+ end
12
+
13
+ User.create(username: 'johndoe', email: 'johndoe@example.com')
14
+ User.create(username: 'msmith', email: 'mary.smith@example.com')
15
+ end
16
+
17
+ after(:each) do
18
+ User.destroy_all
19
+ end
20
+
21
+ describe 'filter records' do
22
+ let(:records) { User.all }
23
+
24
+ it 'requires a records collection as argument' do
25
+ expect { datatable.send(:filter_records) }.to raise_error
26
+ end
27
+
28
+ it 'performs a simple search first' do
29
+ datatable.params[:search] = { value: 'msmith' }
30
+ expect(datatable).to receive(:build_conditions_for_datatable)
31
+ datatable.send(:filter_records, records)
32
+ end
33
+
34
+ it 'performs a composite search second' do
35
+ datatable.params[:search] = { value: '' }
36
+ expect(datatable).to receive(:build_conditions_for_selected_columns)
37
+ datatable.send(:filter_records, records)
38
+ end
39
+
40
+ describe '#build_conditions_for_datatable' do
41
+ it 'returns an Arel object' do
42
+ datatable.params[:search] = { value: 'msmith' }
43
+ result = datatable.send(:build_conditions_for_datatable)
44
+ expect(result).to be_a(Arel::Nodes::Grouping)
45
+ end
46
+
47
+ context 'no search query' do
48
+ it 'returns empty query' do
49
+ datatable.params[:search] = { value: '' }
50
+ expect(datatable.send(:build_conditions_for_datatable)).to be_blank
51
+ end
52
+ end
53
+
54
+ context 'none of columns are connected' do
55
+ before(:each) do
56
+ allow(datatable).to receive(:searchable_columns) { [] }
57
+ end
58
+
59
+ it 'returns empty query result' do
60
+ datatable.params[:search] = { value: 'msmith' }
61
+ expect(datatable.send(:build_conditions_for_datatable)).to be_blank
62
+ end
63
+ end
64
+
65
+ context 'with search query' do
66
+ before(:each) do
67
+ datatable.params[:search] = { value: "John", regex: "false" }
68
+ end
69
+
70
+ it 'returns a filtering query' do
71
+ query = datatable.send(:build_conditions_for_datatable)
72
+ results = records.where(query).map(&:username)
73
+ expect(results).to include('johndoe')
74
+ expect(results).not_to include('msmith')
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#build_conditions_for_selected_columns' do
80
+ context 'columns include search query' do
81
+ before do
82
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
83
+ datatable.params[:columns]['1'][:search][:value] = 'example'
84
+ end
85
+
86
+ it 'returns an Arel object' do
87
+ result = datatable.send(:build_conditions_for_selected_columns)
88
+ expect(result).to be_a(Arel::Nodes::And)
89
+ end
90
+
91
+ it 'can call #to_sql on returned object' do
92
+ result = datatable.send(:build_conditions_for_selected_columns)
93
+ expect(result).to respond_to(:to_sql)
94
+ expect(result.to_sql).to eq(
95
+ "CAST(\"users\".\"username\" AS TEXT) LIKE '%doe%' AND CAST(\"users\".\"email\" AS TEXT) LIKE '%example%'"
96
+ )
97
+ end
98
+ end
99
+
100
+ it 'calls #build_conditions_for_selected_columns' do
101
+ expect(datatable).to receive(:build_conditions_for_selected_columns)
102
+ datatable.send(:build_conditions)
103
+ end
104
+
105
+ context 'with search values in columns' do
106
+ before(:each) do
107
+ datatable.params[:columns]['0'][:search][:value] = 'doe'
108
+ end
109
+
110
+ it 'returns a filtered set of records' do
111
+ query = datatable.send(:build_conditions_for_selected_columns)
112
+ results = records.where(query).map(&:username)
113
+ expect(results).to include('johndoe')
114
+ expect(results).not_to include('msmith')
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#typecast helper method' do
120
+ let(:view) { double('view', params: sample_params) }
121
+ let(:column) { ComplexDatatable.new(view).datatable.columns.first }
122
+
123
+ it 'returns VARCHAR if :db_adapter is :pg' do
124
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :pg }
125
+ expect(column.send(:typecast)).to eq('VARCHAR')
126
+ end
127
+
128
+ it 'returns VARCHAR if :db_adapter is :postgre' do
129
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :postgre }
130
+ expect(column.send(:typecast)).to eq('VARCHAR')
131
+ end
132
+
133
+ it 'returns CHAR if :db_adapter is :mysql2' do
134
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :mysql2 }
135
+ expect(column.send(:typecast)).to eq('CHAR')
136
+ end
137
+
138
+ it 'returns CHAR if :db_adapter is :mysql' do
139
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :mysql }
140
+ expect(column.send(:typecast)).to eq('CHAR')
141
+ end
142
+
143
+ it 'returns TEXT if :db_adapter is :sqlite' do
144
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :sqlite }
145
+ expect(column.send(:typecast)).to eq('TEXT')
146
+ end
147
+
148
+ it 'returns TEXT if :db_adapter is :sqlite3' do
149
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:db_adapter) { :sqlite3 }
150
+ expect(column.send(:typecast)).to eq('TEXT')
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::ORM::ActiveRecord#paginate_records' do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { SampleDatatable.new(view) }
6
+
7
+ before(:each) do
8
+ AjaxDatatablesRails.configure do |config|
9
+ config.db_adapter = :sqlite
10
+ config.orm = :active_record
11
+ end
12
+
13
+ User.create(username: 'johndoe', email: 'johndoe@example.com')
14
+ User.create(username: 'msmith', email: 'mary.smith@example.com')
15
+ end
16
+
17
+ after(:each) do
18
+ User.destroy_all
19
+ end
20
+
21
+ describe 'paginate records' do
22
+ let(:records) { User.all }
23
+
24
+ it 'requires a records collection argument' do
25
+ expect { datatable.send(:paginate_records) }.to raise_error
26
+ end
27
+
28
+ it 'paginates records properly' do
29
+ expect(datatable.send(:paginate_records, records).to_sql).to include(
30
+ "LIMIT 10 OFFSET 0"
31
+ )
32
+
33
+ datatable.params[:start] = "26"
34
+ datatable.params[:length] = "25"
35
+ expect(datatable.send(:paginate_records, records).to_sql).to include(
36
+ "LIMIT 25 OFFSET 25"
37
+ )
38
+ end
39
+
40
+ it 'depends on the value of #offset' do
41
+ expect(datatable.datatable).to receive(:offset)
42
+ datatable.send(:paginate_records, records)
43
+ end
44
+
45
+ it 'depends on the value of #per_page' do
46
+ expect(datatable.datatable).to receive(:per_page).at_least(:once) { 10 }
47
+ datatable.send(:paginate_records, records)
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::ORM::ActiveRecord#sort_records' do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { ComplexDatatable.new(view) }
6
+
7
+ before(:each) do
8
+ AjaxDatatablesRails.configure do |config|
9
+ config.db_adapter = :sqlite
10
+ config.orm = :active_record
11
+ end
12
+
13
+ User.create(username: 'johndoe', email: 'johndoe@example.com')
14
+ User.create(username: 'msmith', email: 'mary.smith@example.com')
15
+ end
16
+
17
+ after(:each) do
18
+ User.destroy_all
19
+ end
20
+
21
+ describe 'sort records' do
22
+ let(:records) { User.all }
23
+
24
+ it 'returns a records collection sorted by :order params' do
25
+ # set to order Users by email in descending order
26
+ datatable.params[:order]['0'] = { column: '1', dir: 'desc' }
27
+ expect(datatable.send(:sort_records, records).map(&:email)).to match(
28
+ ['mary.smith@example.com', 'johndoe@example.com']
29
+ )
30
+ end
31
+
32
+ it 'can handle multiple sorting columns' do
33
+ # set to order by Users username in ascending order, and
34
+ # by Users email in descending order
35
+ datatable.params[:order]['0'] = { column: '0', dir: 'asc' }
36
+ datatable.params[:order]['1'] = { column: '1', dir: 'desc' }
37
+ expect(datatable.send(:sort_records, records).to_sql).to include(
38
+ "ORDER BY users.username ASC, users.email DESC"
39
+ )
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::ORM::ActiveRecord#fetch_records' do
4
+ context 'Private API' do
5
+ let(:view) { double('view', params: sample_params) }
6
+ let(:datatable) { SampleDatatable.new(view) }
7
+
8
+ before(:each) do
9
+ AjaxDatatablesRails.configure do |config|
10
+ config.db_adapter = :sqlite
11
+ config.orm = :active_record
12
+ end
13
+
14
+ User.create(username: 'johndoe', email: 'johndoe@example.com')
15
+ User.create(username: 'msmith', email: 'mary.smith@example.com')
16
+ end
17
+
18
+ after(:each) do
19
+ User.destroy_all
20
+ end
21
+
22
+ describe 'fetch records' do
23
+ it 'calls #get_raw_records' do
24
+ expect(datatable).to receive(:get_raw_records) { User.all }
25
+ datatable.send(:fetch_records)
26
+ end
27
+
28
+ it 'returns a collection of records' do
29
+ expect(datatable).to receive(:get_raw_records) { User.all }
30
+ expect(datatable.send(:fetch_records)).to be_a(ActiveRecord::Relation)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ ActiveRecord::Schema.define do
2
+ self.verbose = false
3
+
4
+ create_table :users, :force => true do |t|
5
+ t.string :username
6
+ t.string :email
7
+ t.string :first_name
8
+ t.string :last_name
9
+
10
+ t.timestamps null: false
11
+ end
12
+
13
+ create_table :addresses, :force => true do |t|
14
+ t.string :address_line1
15
+ t.string :address_line2
16
+ t.string :city
17
+ t.string :zip_code
18
+ t.string :state
19
+ t.string :country
20
+
21
+ t.timestamps null: false
22
+ end
23
+
24
+ create_table :purchased_orders, :force => true do |t|
25
+ t.string :foo
26
+ t.string :bar
27
+
28
+ t.timestamps null: false
29
+ end
30
+
31
+ create_table :statistics_requests, :force => true do |t|
32
+ t.string :baz
33
+
34
+ t.timestamps null: false
35
+ end
36
+
37
+ create_table :statistics_sessions, :force => true do |t|
38
+ t.string :foo
39
+ t.integer :bar
40
+
41
+ t.timestamps null: false
42
+ end
43
+ end
@@ -0,0 +1,10 @@
1
+ require 'pry'
2
+ require 'rails'
3
+ require 'active_record'
4
+ require 'ajax-datatables-rails'
5
+
6
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
7
+
8
+ load File.dirname(__FILE__) + '/schema.rb'
9
+ load File.dirname(__FILE__) + '/test_helpers.rb'
10
+ require File.dirname(__FILE__) + '/test_models.rb'
@@ -0,0 +1,66 @@
1
+ def sample_params
2
+ ActiveSupport::HashWithIndifferentAccess.new(
3
+ {
4
+ "draw"=>"1",
5
+ "columns"=> {
6
+ "0"=> {
7
+ "data"=>"username", "name"=>"", "searchable"=>"true", "orderable"=>"true",
8
+ "search"=> {
9
+ "value"=>"", "regex"=>"false"
10
+ }
11
+ },
12
+ "1"=> {
13
+ "data"=>"email", "name"=>"", "searchable"=>"true", "orderable"=>"true",
14
+ "search"=> {
15
+ "value"=>"", "regex"=>"false"
16
+ }
17
+ },
18
+ "2"=> {
19
+ "data"=>"first_name", "name"=>"", "searchable"=>"false", "orderable"=>"false",
20
+ "search"=> {
21
+ "value"=>"", "regex"=>"false"
22
+ }
23
+ },
24
+ "3"=> {
25
+ "data"=>"last_name", "name"=>"", "searchable"=>"false", "orderable"=>"true",
26
+ "search"=> {
27
+ "value"=>"", "regex"=>"false"
28
+ }
29
+ },
30
+ },
31
+ "order"=> {
32
+ "0"=> {"column"=>"0", "dir"=>"asc"}
33
+ },
34
+ "start"=>"0", "length"=>"10", "search"=>{
35
+ "value"=>"", "regex"=>"false"
36
+ },
37
+ "_"=>"1423364387185"
38
+ }
39
+ )
40
+ end
41
+
42
+ class SampleDatatable < AjaxDatatablesRails::Base
43
+ def view_columns
44
+ @view_columns ||= ['User.username', 'User.email', 'User.first_name', 'User.last_name']
45
+ end
46
+
47
+ def data
48
+ [{}, {}]
49
+ end
50
+
51
+ def get_raw_records
52
+ User.all
53
+ end
54
+ end
55
+
56
+
57
+ class ComplexDatatable < SampleDatatable
58
+ def view_columns
59
+ @view_columns ||= {
60
+ username: { source: 'User.username' },
61
+ email: { source: 'User.email' },
62
+ first_name: { source: 'User.first_name' },
63
+ last_name: { source: 'User.last_name' }
64
+ }
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ class User < ActiveRecord::Base
2
+ end
3
+
4
+ class Address < ActiveRecord::Base
5
+ end
6
+
7
+ class PurchasedOrder < ActiveRecord::Base
8
+ end
9
+
10
+ module Statistics
11
+ def self.table_name_prefix
12
+ "statistics_"
13
+ end
14
+ end
15
+
16
+ class Statistics::Request < ActiveRecord::Base
17
+ end
18
+
19
+ class Statistics::Session < ActiveRecord::Base
20
+ end