datatables-net 0.4.0

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.
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,19 @@
1
+ module AjaxDatatablesRails
2
+ module Datatable
3
+ class SimpleSearch
4
+ attr_reader :options
5
+
6
+ def initialize options
7
+ @options = options || {}
8
+ end
9
+
10
+ def value
11
+ options[:value]
12
+ end
13
+
14
+ def regexp?
15
+ options[:regex] == TRUE_VALUE
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ module AjaxDatatablesRails
2
+ module ORM
3
+ module ActiveRecord
4
+
5
+ def fetch_records
6
+ get_raw_records
7
+ end
8
+
9
+ def filter_records records
10
+ records.where(build_conditions)
11
+ end
12
+
13
+ def sort_records records
14
+ sort_by = datatable.orders.inject([]) do |queries, order|
15
+ column = order.column
16
+ queries << order.query(column.sort_query) if column
17
+ end
18
+ records.order(sort_by.join(", "))
19
+ end
20
+
21
+ def paginate_records records
22
+ records.offset(datatable.offset).limit(datatable.per_page)
23
+ end
24
+
25
+ # ----------------- SEARCH HELPER METHODS --------------------
26
+
27
+ def build_conditions
28
+ if datatable.searchable?
29
+ build_conditions_for_datatable
30
+ else
31
+ build_conditions_for_selected_columns
32
+ end
33
+ end
34
+
35
+ def build_conditions_for_datatable
36
+ search_for = datatable.search.value.split(' ')
37
+ criteria = search_for.inject([]) do |criteria, atom|
38
+ search = Datatable::SimpleSearch.new({ value: atom, regex: datatable.search.regexp? })
39
+ criteria << searchable_columns.map do |simple_column|
40
+ simple_column.search = search
41
+ simple_column.search_query
42
+ end.reduce(:or)
43
+ end.reduce(:and)
44
+ criteria
45
+ end
46
+
47
+ def build_conditions_for_selected_columns
48
+ search_columns.map(&:search_query).reduce(:and)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module AjaxDatatablesRails
2
+ VERSION = '0.4.0'
3
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails/generators'
2
+
3
+ module Datatable
4
+ module Generators
5
+ class ConfigGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
7
+ desc <<DESC
8
+ Description:
9
+ Creates an initializer file for AjaxDatatablesRails configuration at config/initializers.
10
+ DESC
11
+
12
+ def copy_config_file
13
+ template 'ajax_datatables_rails_config.rb', 'config/initializers/ajax_datatables_rails.rb'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ AjaxDatatablesRails.configure do |config|
2
+ # available options for db_adapter are: :pg, :mysql, :mysql2, :sqlite, :sqlite3, :oracle
3
+ # config.db_adapter = :pg
4
+
5
+ # available options for orm are: :active_record, :mongoid
6
+ # config.orm = :active_record
7
+ end
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+
3
+ module Rails
4
+ module Generators
5
+ class DatatableGenerator < ::Rails::Generators::Base
6
+ desc 'Creates a *_datatable model in the app/datatables directory.'
7
+ source_root File.expand_path('../templates', __FILE__)
8
+ argument :name, type: :string
9
+
10
+ def generate_datatable
11
+ template 'datatable.rb', File.join(
12
+ 'app/datatables', "#{datatable_path}.rb"
13
+ )
14
+ end
15
+
16
+ def datatable_name
17
+ datatable_path.classify
18
+ end
19
+
20
+ private
21
+ def datatable_path
22
+ "#{name.underscore}_datatable"
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,41 @@
1
+ class <%= datatable_name %> < AjaxDatatablesRails::Base
2
+
3
+ def view_columns
4
+ # Declare strings in this format: ModelName.column_name
5
+ # or in aliased_join_table.column_name format
6
+ @view_columns ||= {
7
+ # id: { source: "User.id", cond: :eq },
8
+ # name: { source: "User.name", cond: :like }
9
+ }
10
+ end
11
+
12
+ def data
13
+ records.map do |record|
14
+ {
15
+ # example:
16
+ # id: record.id,
17
+ # name: record.name
18
+ }
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def get_raw_records
25
+ # insert query here
26
+ end
27
+
28
+ # ==== These methods represent the basic operations to perform on records
29
+ # and feel free to override them
30
+
31
+ # def filter_records(records)
32
+ # end
33
+
34
+ # def sort_records(records)
35
+ # end
36
+
37
+ # def paginate_records(records)
38
+ # end
39
+
40
+ # ==== Insert 'presenter'-like methods below if necessary
41
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails::Base do
4
+ describe 'an instance' do
5
+ let(:view) { double('view', params: sample_params) }
6
+
7
+ it 'requires a view_context' do
8
+ expect { AjaxDatatablesRails::Base.new }.to raise_error ArgumentError
9
+ end
10
+
11
+ it 'accepts an options hash' do
12
+ datatable = AjaxDatatablesRails::Base.new(view, foo: 'bar')
13
+ expect(datatable.options).to eq(foo: 'bar')
14
+ end
15
+ end
16
+
17
+ context 'Public API' do
18
+ let(:view) { double('view', params: sample_params) }
19
+ let(:datatable) { AjaxDatatablesRails::Base.new(view) }
20
+
21
+ describe '#view_columns' do
22
+ it 'raises an error if not defined by the user' do
23
+ expect { datatable.view_columns }.to raise_error AjaxDatatablesRails::NotImplemented
24
+ end
25
+
26
+ context 'child class implements view_columns' do
27
+ it 'expects an array based defining columns' do
28
+ datatable = SampleDatatable.new(view)
29
+ expect(datatable.view_columns).to be_a(Array)
30
+ end
31
+
32
+ it 'expects a hash based defining columns' do
33
+ datatable = ComplexDatatable.new(view)
34
+ expect(datatable.view_columns).to be_a(Hash)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '#data' do
40
+ it 'raises an error if not defined by the user' do
41
+ expect { datatable.data }.to raise_error AjaxDatatablesRails::NotImplemented
42
+ end
43
+
44
+ context 'child class implements data' do
45
+ let(:datatable) { ComplexDatatable.new(view) }
46
+
47
+ it 'can return an array of hashes' do
48
+ allow(datatable).to receive(:data) { [{}, {}] }
49
+ expect(datatable.data).to be_a(Array)
50
+ item = datatable.data.first
51
+ expect(item).to be_a(Hash)
52
+ end
53
+
54
+ it 'can return an array of arrays' do
55
+ allow(datatable).to receive(:data) { [[], []] }
56
+ expect(datatable.data).to be_a(Array)
57
+ item = datatable.data.first
58
+ expect(item).to be_a(Array)
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ describe '#get_raw_records' do
65
+ it 'raises an error if not defined by the user' do
66
+ expect { datatable.get_raw_records }.to raise_error AjaxDatatablesRails::NotImplemented
67
+ end
68
+ end
69
+ end
70
+
71
+ context 'Private API' do
72
+ let(:view) { double('view', params: sample_params) }
73
+ let(:datatable) { ComplexDatatable.new(view) }
74
+
75
+ before(:each) do
76
+ allow_any_instance_of(AjaxDatatablesRails::Configuration).to receive(:orm) { nil }
77
+ end
78
+
79
+ describe 'fetch records' do
80
+ it 'raises an error if it does not include an ORM module' do
81
+ expect { datatable.send(:fetch_records) }.to raise_error
82
+ end
83
+ end
84
+
85
+ describe 'filter records' do
86
+ it 'raises an error if it does not include an ORM module' do
87
+ expect { datatable.send(:filter_records) }.to raise_error
88
+ end
89
+ end
90
+
91
+ describe 'sort records' do
92
+ it 'raises an error if it does not include an ORM module' do
93
+ expect { datatable.send(:sort_records) }.to raise_error
94
+ end
95
+ end
96
+
97
+ describe 'paginate records' do
98
+ it 'raises an error if it does not include an ORM module' do
99
+ expect { datatable.send(:paginate_records) }.to raise_error
100
+ end
101
+ end
102
+
103
+ describe 'helper methods' do
104
+ describe '#offset' do
105
+ it 'defaults to 0' do
106
+ default_view = double('view', params: {})
107
+ datatable = AjaxDatatablesRails::Base.new(default_view)
108
+ expect(datatable.datatable.send(:offset)).to eq(0)
109
+ end
110
+
111
+ it 'matches the value on view params[:start] minus 1' do
112
+ paginated_view = double('view', params: { start: '11' })
113
+ datatable = AjaxDatatablesRails::Base.new(paginated_view)
114
+ expect(datatable.datatable.send(:offset)).to eq(10)
115
+ end
116
+ end
117
+
118
+ describe '#page' do
119
+ it 'calculates page number from params[:start] and #per_page' do
120
+ paginated_view = double('view', params: { start: '11' })
121
+ datatable = AjaxDatatablesRails::Base.new(paginated_view)
122
+ expect(datatable.datatable.send(:page)).to eq(2)
123
+ end
124
+ end
125
+
126
+ describe '#per_page' do
127
+ it 'defaults to 10' do
128
+ datatable = AjaxDatatablesRails::Base.new(view)
129
+ expect(datatable.datatable.send(:per_page)).to eq(10)
130
+ end
131
+
132
+ it 'matches the value on view params[:length]' do
133
+ other_view = double('view', params: { length: 20 })
134
+ datatable = AjaxDatatablesRails::Base.new(other_view)
135
+ expect(datatable.datatable.send(:per_page)).to eq(20)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe AjaxDatatablesRails do
4
+ describe "configurations" do
5
+ context "configurable from outside" do
6
+ before(:each) do
7
+ AjaxDatatablesRails.configure do |config|
8
+ config.db_adapter = :mysql
9
+ end
10
+ end
11
+
12
+ it "should have custom value" do
13
+ expect(AjaxDatatablesRails.config.db_adapter).to eq(:mysql)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ describe AjaxDatatablesRails::Configuration do
20
+ let(:config) { AjaxDatatablesRails::Configuration.new }
21
+
22
+ describe "default config" do
23
+ it "default orm should :active_record" do
24
+ expect(config.orm).to eq(:active_record)
25
+ end
26
+
27
+ it "default db_adapter should :pg (postgresql)" do
28
+ expect(config.db_adapter).to eq(:pg)
29
+ end
30
+ end
31
+
32
+ describe "custom config" do
33
+ it 'should accept db_adapter custom value' do
34
+ config.db_adapter = :mysql
35
+ expect(config.db_adapter).to eq(:mysql)
36
+ end
37
+
38
+ it 'accepts a custom orm value' do
39
+ config.orm = :mongoid
40
+ expect(config.orm).to eq(:mongoid)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::Datatable::Column' do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { ComplexDatatable.new(view) }
6
+ before {
7
+ datatable.params[:columns] = {"0"=>{"data"=>"username", "name"=>"", "searchable"=>"true", "orderable"=>"true", "search"=>{"value"=>"searchvalue", "regex"=>"false"}}}
8
+ }
9
+
10
+ describe 'helper methods' do
11
+ describe 'order methods' do
12
+ let(:column) { datatable.datatable.columns.first }
13
+
14
+ it 'should be orderable' do
15
+ expect(column.orderable?).to eq(true)
16
+ end
17
+
18
+ it 'should be searchable' do
19
+ expect(column.searchable?).to eq(true)
20
+ end
21
+
22
+ it 'should have connected to id column' do
23
+ expect(column.data).to eq('username')
24
+ end
25
+
26
+ context '#search' do
27
+ it 'child class' do
28
+ expect(column.search).to be_a(AjaxDatatablesRails::Datatable::SimpleSearch)
29
+ end
30
+
31
+ it 'should have search value' do
32
+ expect(column.search.value).to eq('searchvalue')
33
+ end
34
+
35
+ it 'should not regex' do
36
+ expect(column.search.regexp?).to eq false
37
+ end
38
+ end
39
+
40
+ describe '#cond' do
41
+ it 'should be :like by default' do
42
+ expect(column.cond).to eq(:like)
43
+ end
44
+ end
45
+
46
+ describe '#source' do
47
+ it 'should be :like by default' do
48
+ expect(column.source).to eq('User.username')
49
+ end
50
+ end
51
+
52
+ describe '#search_query' do
53
+ it 'should buld search query' do
54
+ expect(column.search_query.to_sql).to include('%searchvalue%')
55
+ end
56
+ end
57
+
58
+ describe '#sort_query' do
59
+ it 'should build sort query' do
60
+ expect(column.sort_query).to eq('users.username')
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'AjaxDatatablesRails::Datatable::Datatable' do
4
+ let(:view) { double('view', params: sample_params) }
5
+ let(:datatable) { ComplexDatatable.new(view).datatable }
6
+ let(:order_option) { {"0"=>{"column"=>"0", "dir"=>"asc"}, "1"=>{"column"=>"1", "dir"=>"desc"}} }
7
+
8
+ before(:each) do
9
+ AjaxDatatablesRails.configure do |config|
10
+ config.db_adapter = :sqlite
11
+ config.orm = :active_record
12
+ end
13
+ end
14
+
15
+ describe 'helper methods' do
16
+ describe 'order methods' do
17
+ it 'should be orderable' do
18
+ expect(datatable.orderable?).to eq(true)
19
+ end
20
+
21
+ it 'should not be orderable' do
22
+ datatable.options[:order] = nil
23
+ expect(datatable.orderable?).to eq(false)
24
+ end
25
+
26
+ it 'should have 2 orderable columns' do
27
+ datatable.options[:order] = order_option
28
+ expect(datatable.orders.count).to eq(2)
29
+ end
30
+
31
+ it 'first column ordered by ASC' do
32
+ datatable.options[:order] = order_option
33
+ expect(datatable.orders.first.send :dir).to eq('ASC')
34
+ end
35
+
36
+ it 'first column ordered by DESC' do
37
+ datatable.options[:order] = order_option
38
+ expect(datatable.orders.last.send :dir).to eq('DESC')
39
+ end
40
+
41
+ it 'child class' do
42
+ expect(datatable.orders.first).to be_a(AjaxDatatablesRails::Datatable::SimpleOrder)
43
+ end
44
+ end
45
+
46
+ describe 'search methods' do
47
+ it 'should be searchable' do
48
+ datatable.options[:search][:value] = 'atom'
49
+ expect(datatable.searchable?).to eq(true)
50
+ end
51
+
52
+ it 'should not be searchable' do
53
+ datatable.options[:search][:value] = nil
54
+ expect(datatable.searchable?).to eq(false)
55
+ end
56
+
57
+ it 'child class' do
58
+ expect(datatable.search).to be_a(AjaxDatatablesRails::Datatable::SimpleSearch)
59
+ end
60
+
61
+ end
62
+
63
+ describe 'columns methods' do
64
+ it 'should have 4 columns' do
65
+ expect(datatable.columns.count).to eq(4)
66
+ end
67
+
68
+ it 'child class' do
69
+ expect(datatable.columns.first).to be_a(AjaxDatatablesRails::Datatable::Column)
70
+ end
71
+
72
+ end
73
+
74
+ describe 'option methods' do
75
+ before :each do
76
+ datatable.options[:start] = '50'
77
+ datatable.options[:length] = '15'
78
+ end
79
+
80
+ it 'paginate?' do
81
+ expect(datatable.paginate?).to be(true)
82
+ end
83
+
84
+ it 'offset' do
85
+ expect(datatable.offset).to eq(45)
86
+ end
87
+
88
+ it 'page' do
89
+ expect(datatable.page).to eq(4)
90
+ end
91
+
92
+ it 'per_page' do
93
+ expect(datatable.per_page).to eq(15)
94
+ end
95
+ end
96
+ end
97
+ end