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