datatable 0.1.0alpha2

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 (187) hide show
  1. data/.bundle/config +3 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +83 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +135 -0
  8. data/Rakefile +27 -0
  9. data/TODO +71 -0
  10. data/datatable.gemspec +20 -0
  11. data/example_app/.DS_Store +0 -0
  12. data/example_app/.gitignore +6 -0
  13. data/example_app/.rspec +1 -0
  14. data/example_app/Gemfile +35 -0
  15. data/example_app/Gemfile.lock +126 -0
  16. data/example_app/Rakefile +7 -0
  17. data/example_app/app/controllers/application_controller.rb +3 -0
  18. data/example_app/app/controllers/orders_controller.rb +13 -0
  19. data/example_app/app/datatables/orders_index.rb +31 -0
  20. data/example_app/app/helpers/application_helper.rb +2 -0
  21. data/example_app/app/models/customer.rb +4 -0
  22. data/example_app/app/models/item.rb +4 -0
  23. data/example_app/app/models/order.rb +5 -0
  24. data/example_app/app/models/order_item.rb +4 -0
  25. data/example_app/app/models/sales_rep.rb +3 -0
  26. data/example_app/app/views/layouts/application.html.erb +12 -0
  27. data/example_app/app/views/orders/index.html.erb +14 -0
  28. data/example_app/config/application.rb +41 -0
  29. data/example_app/config/boot.rb +6 -0
  30. data/example_app/config/database.yml.mysql +20 -0
  31. data/example_app/config/database.yml.pg +20 -0
  32. data/example_app/config/environment.rb +5 -0
  33. data/example_app/config/environments/development.rb +28 -0
  34. data/example_app/config/environments/production.rb +49 -0
  35. data/example_app/config/environments/test.rb +35 -0
  36. data/example_app/config/initializers/backtrace_silencers.rb +7 -0
  37. data/example_app/config/initializers/datatable.rb +6 -0
  38. data/example_app/config/initializers/inflections.rb +10 -0
  39. data/example_app/config/initializers/mime_types.rb +5 -0
  40. data/example_app/config/initializers/secret_token.rb +9 -0
  41. data/example_app/config/initializers/session_store.rb +8 -0
  42. data/example_app/config/locales/en.yml +5 -0
  43. data/example_app/config/routes.rb +6 -0
  44. data/example_app/config.ru +4 -0
  45. data/example_app/db/migrate/20110429185712_create_customers.rb +15 -0
  46. data/example_app/db/migrate/20110429185742_create_sales_reps.rb +14 -0
  47. data/example_app/db/migrate/20110429185807_create_items.rb +15 -0
  48. data/example_app/db/migrate/20110429185913_create_orders.rb +15 -0
  49. data/example_app/db/migrate/20110429190005_create_order_items.rb +14 -0
  50. data/example_app/db/schema.rb +53 -0
  51. data/example_app/db/seeds.rb +49 -0
  52. data/example_app/lib/tasks/.gitkeep +0 -0
  53. data/example_app/lib/tasks/setup.rake +12 -0
  54. data/example_app/public/404.html +26 -0
  55. data/example_app/public/422.html +26 -0
  56. data/example_app/public/500.html +26 -0
  57. data/example_app/public/datatable/css/demo_page.css +99 -0
  58. data/example_app/public/datatable/css/demo_table.css +539 -0
  59. data/example_app/public/datatable/css/demo_table_jui.css +521 -0
  60. data/example_app/public/datatable/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  61. data/example_app/public/datatable/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  62. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  63. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  64. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  65. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  66. data/example_app/public/datatable/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  67. data/example_app/public/datatable/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  68. data/example_app/public/datatable/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  69. data/example_app/public/datatable/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  70. data/example_app/public/datatable/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  71. data/example_app/public/datatable/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  72. data/example_app/public/datatable/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  73. data/example_app/public/datatable/css/smoothness/jquery-ui-1.8.14.custom.css +568 -0
  74. data/example_app/public/datatable/images/back_disabled.jpg +0 -0
  75. data/example_app/public/datatable/images/back_enabled.jpg +0 -0
  76. data/example_app/public/datatable/images/favicon.ico +0 -0
  77. data/example_app/public/datatable/images/forward_disabled.jpg +0 -0
  78. data/example_app/public/datatable/images/forward_enabled.jpg +0 -0
  79. data/example_app/public/datatable/images/sort_asc.png +0 -0
  80. data/example_app/public/datatable/images/sort_asc_disabled.png +0 -0
  81. data/example_app/public/datatable/images/sort_both.png +0 -0
  82. data/example_app/public/datatable/images/sort_desc.png +0 -0
  83. data/example_app/public/datatable/images/sort_desc_disabled.png +0 -0
  84. data/example_app/public/datatable/js/jquery-ui-1.8.14.custom.min.js +789 -0
  85. data/example_app/public/datatable/js/jquery.dataTables.js +7347 -0
  86. data/example_app/public/datatable/js/jquery.dataTables.min.js +151 -0
  87. data/example_app/public/favicon.ico +0 -0
  88. data/example_app/public/flash/copy_cvs_xls.swf +0 -0
  89. data/example_app/public/flash/copy_cvs_xls_pdf.swf +0 -0
  90. data/example_app/public/images/rails.png +0 -0
  91. data/example_app/public/javascripts/application.js +2 -0
  92. data/example_app/public/javascripts/jquery.js +8936 -0
  93. data/example_app/public/javascripts/jquery.min.js +18 -0
  94. data/example_app/public/javascripts/jquery_ujs.js +316 -0
  95. data/example_app/public/robots.txt +5 -0
  96. data/example_app/public/stylesheets/.gitkeep +0 -0
  97. data/example_app/script/rails +6 -0
  98. data/example_app/spec/datatables/active_record_dsl_spec.rb +59 -0
  99. data/example_app/spec/datatables/active_record_link_to_spec.rb +22 -0
  100. data/example_app/spec/datatables/active_record_pagination_spec.rb +94 -0
  101. data/example_app/spec/datatables/active_record_table_operations_spec.rb +180 -0
  102. data/example_app/spec/datatables/config_spec.rb +10 -0
  103. data/example_app/spec/datatables/query_params_spec.rb +73 -0
  104. data/example_app/spec/datatables/sql_default_spec.rb +22 -0
  105. data/example_app/spec/datatables/sql_pagination_spec.rb +177 -0
  106. data/example_app/spec/datatables/sql_search_cast_spec.rb +6 -0
  107. data/example_app/spec/datatables/sql_search_global_spec.rb +107 -0
  108. data/example_app/spec/datatables/sql_search_individual_spec.rb +113 -0
  109. data/example_app/spec/datatables/sql_search_where_spec.rb +87 -0
  110. data/example_app/spec/datatables/sql_sorting_spec.rb +80 -0
  111. data/example_app/spec/datatables/sql_variables_spec.rb +104 -0
  112. data/example_app/spec/factories/customer_factory.rb +4 -0
  113. data/example_app/spec/factories/item_factory.rb +2 -0
  114. data/example_app/spec/factories/order_factory.rb +7 -0
  115. data/example_app/spec/factories/order_item_factory.rb +2 -0
  116. data/example_app/spec/factories/sales_rep_factory.rb +4 -0
  117. data/example_app/spec/helpers/aocolumn_spec.rb +239 -0
  118. data/example_app/spec/helpers/data_table_helper_spec.rb +148 -0
  119. data/example_app/spec/helpers/headings_spec.rb +71 -0
  120. data/example_app/spec/spec_helper.rb +29 -0
  121. data/generators.txt +6 -0
  122. data/images/datatable_screenshot.png +0 -0
  123. data/lib/datatable/active_record_dsl.rb +49 -0
  124. data/lib/datatable/errors.rb +5 -0
  125. data/lib/datatable/helper.rb +199 -0
  126. data/lib/datatable/railtie.rb +17 -0
  127. data/lib/datatable/version.rb +4 -0
  128. data/lib/datatable.rb +341 -0
  129. data/lib/generators/datatable/install_generator.rb +58 -0
  130. data/lib/generators/datatable/new_generator.rb +46 -0
  131. data/lib/generators/templates/datatable.rb +33 -0
  132. data/lib/generators/templates/datatable_initializer.rb +6 -0
  133. data/vendor/datatable/Readme.txt +11 -0
  134. data/vendor/datatable/extras/TableTools/media/css/TableTools.css +264 -0
  135. data/vendor/datatable/extras/TableTools/media/css/TableTools_JUI.css +182 -0
  136. data/vendor/datatable/extras/TableTools/media/images/background.png +0 -0
  137. data/vendor/datatable/extras/TableTools/media/images/collection.png +0 -0
  138. data/vendor/datatable/extras/TableTools/media/images/collection_hover.png +0 -0
  139. data/vendor/datatable/extras/TableTools/media/images/copy.png +0 -0
  140. data/vendor/datatable/extras/TableTools/media/images/copy_hover.png +0 -0
  141. data/vendor/datatable/extras/TableTools/media/images/csv.png +0 -0
  142. data/vendor/datatable/extras/TableTools/media/images/csv_hover.png +0 -0
  143. data/vendor/datatable/extras/TableTools/media/images/pdf.png +0 -0
  144. data/vendor/datatable/extras/TableTools/media/images/pdf_hover.png +0 -0
  145. data/vendor/datatable/extras/TableTools/media/images/print.png +0 -0
  146. data/vendor/datatable/extras/TableTools/media/images/print_hover.png +0 -0
  147. data/vendor/datatable/extras/TableTools/media/images/xls.png +0 -0
  148. data/vendor/datatable/extras/TableTools/media/images/xls_hover.png +0 -0
  149. data/vendor/datatable/extras/TableTools/media/js/TableTools.js +2410 -0
  150. data/vendor/datatable/extras/TableTools/media/js/TableTools.min.js +78 -0
  151. data/vendor/datatable/extras/TableTools/media/js/TableTools.min.js.gz +0 -0
  152. data/vendor/datatable/extras/TableTools/media/js/ZeroClipboard.js +365 -0
  153. data/vendor/datatable/extras/TableTools/media/swf/copy_cvs_xls.swf +0 -0
  154. data/vendor/datatable/extras/TableTools/media/swf/copy_cvs_xls_pdf.swf +0 -0
  155. data/vendor/datatable/license-bsd.txt +10 -0
  156. data/vendor/datatable/license-gpl2.txt +339 -0
  157. data/vendor/datatable/media/css/demo_page.css +99 -0
  158. data/vendor/datatable/media/css/demo_table.css +539 -0
  159. data/vendor/datatable/media/css/demo_table_jui.css +521 -0
  160. data/vendor/datatable/media/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  161. data/vendor/datatable/media/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  162. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  163. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  164. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  165. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  166. data/vendor/datatable/media/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  167. data/vendor/datatable/media/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  168. data/vendor/datatable/media/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  169. data/vendor/datatable/media/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  170. data/vendor/datatable/media/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  171. data/vendor/datatable/media/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  172. data/vendor/datatable/media/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  173. data/vendor/datatable/media/css/smoothness/jquery-ui-1.8.14.custom.css +568 -0
  174. data/vendor/datatable/media/images/back_disabled.jpg +0 -0
  175. data/vendor/datatable/media/images/back_enabled.jpg +0 -0
  176. data/vendor/datatable/media/images/favicon.ico +0 -0
  177. data/vendor/datatable/media/images/forward_disabled.jpg +0 -0
  178. data/vendor/datatable/media/images/forward_enabled.jpg +0 -0
  179. data/vendor/datatable/media/images/sort_asc.png +0 -0
  180. data/vendor/datatable/media/images/sort_asc_disabled.png +0 -0
  181. data/vendor/datatable/media/images/sort_both.png +0 -0
  182. data/vendor/datatable/media/images/sort_desc.png +0 -0
  183. data/vendor/datatable/media/images/sort_desc_disabled.png +0 -0
  184. data/vendor/datatable/media/js/jquery-ui-1.8.14.custom.min.js +789 -0
  185. data/vendor/datatable/media/js/jquery.dataTables.js +7347 -0
  186. data/vendor/datatable/media/js/jquery.dataTables.min.js +151 -0
  187. metadata +270 -0
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SQL defined datatable supports global search' do
4
+ before do
5
+ Object.send(:remove_const, :T) rescue nil
6
+ class T < Datatable::Base
7
+ sql <<-SQL
8
+ SELECT
9
+ id,
10
+ order_number,
11
+ memo
12
+ FROM
13
+ orders
14
+ SQL
15
+ columns(
16
+ {'orders.id' => {:type => :integer}},
17
+ {'orders.order_number' => {:type => :integer}},
18
+ {'orders.memo' => {:type => :string }}
19
+ )
20
+ end
21
+
22
+ @params = {
23
+ "iColumns" => 4,
24
+ "bSearchable_0" => true,
25
+ "bSearchable_1" => true,
26
+ "bSearchable_2" => true,
27
+ "bSortable_0" => true,
28
+ "bSortable_1" => true,
29
+ "bSortable_2" => true,
30
+ "sSearch_0" => nil,
31
+ "sSearch_1" => nil,
32
+ "sSearch_2" => nil,
33
+ "sSearch" => nil }
34
+
35
+ Order.delete_all
36
+ @orders = [*0..20].map do
37
+ Factory(:order, :order_number => (42 + rand(2)), :memo => rand(2).even? ? 'hello' : 'goodbye')
38
+ end
39
+ end
40
+
41
+ it 'string columns' do
42
+ @params['sSearch'] = 'ello'
43
+ expected = Order.where("memo like '%ello%'").map{|row| row.id.to_s }.sort
44
+ actual = T.query(@params).to_json['aaData'].map{|row| row[0]}.sort
45
+ actual.should == expected
46
+ end
47
+
48
+ it 'integer columns' do
49
+ order_id = Order.all[rand(Order.count)].id.to_s
50
+ @params['sSearch'] = order_id
51
+ T.query(@params).to_json['aaData'][0][0].should == order_id
52
+ T.query(@params).to_json['aaData'].length.should == 1
53
+ end
54
+
55
+ it 'integer columns do not return results unless a number appears in the search string' do
56
+ order = Order.first
57
+ order.order_number = 0
58
+ order.save
59
+ @params['sSearch'] = "0"
60
+ T.query(@params).to_json['aaData'][0][0].should == order.id.to_s
61
+ @params['sSearch'] = "a value without the integer zero"
62
+ T.query(@params).to_json['aaData'].should == []
63
+ end
64
+
65
+ it 'should only search columns that have the bSearchable_int not equal to false' do
66
+ # Order number is set as a non searchable column with the
67
+ # bSearchable flag below. It should be ignored during
68
+ # the search. To prove that we copy the first orders id
69
+ # value into the last orders order_number attribute. Then
70
+ # we do the search. Since order_numbers are unsearchable
71
+ # and ids are unique we should still only get a single
72
+ # value returned
73
+ order1 = Order.order(:id).first
74
+ order2 = Order.order(:id).last
75
+ order2.update_attribute(:order_number, order1.id)
76
+ @params['bSearchable_1'] = false
77
+ @params['sSearch'] = order1.id.to_s
78
+ T.query(@params).to_json['aaData'].should == [[order1.id.to_s,order1.order_number.to_s, order1.memo.to_s]]
79
+ end
80
+
81
+ it "don't fail when no columns is searchable" do
82
+ @params['bSearchable_0'] = false
83
+ @params['bSearchable_1'] = false
84
+ @params['bSearchable_2'] = false
85
+ @params['sSearch'] = "foo"
86
+ T.query(@params)
87
+ end
88
+
89
+ it "should ignore columns that are flagged bSearchable=false" do
90
+ T.columns(
91
+ {'orders.id' => {:type => :integer, :bSearchable => false}},
92
+ {'orders.order_number' => {:type => :integer }},
93
+ {'orders.memo' => {:type => :string }}
94
+ )
95
+ order = Order.last
96
+ @params['sSearch'] = order.id.to_s
97
+ T.query(@params).to_json['aaData'].should == []
98
+ end
99
+
100
+ it "should strip whitespace off of search parameters" do
101
+ @params['sSearch'] = ' hello '
102
+ expected = Order.where("memo like '%hello%'").all.map{|o| o.id.to_s }
103
+ actual = T.query(@params).to_json['aaData'].map{|r| r[0] }
104
+ expected.should == actual
105
+ end
106
+
107
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SQL defined datatable supports individual column search' do
4
+ before do
5
+ Object.send(:remove_const, :T) rescue nil
6
+ class T < Datatable::Base
7
+ sql <<-SQL
8
+ SELECT
9
+ id,
10
+ order_number,
11
+ memo
12
+ FROM
13
+ orders
14
+ SQL
15
+ columns(
16
+ {'orders.id' => {:type => :integer}},
17
+ {'orders.order_number' => {:type => :integer}},
18
+ {'orders.memo' => {:type => :string }}
19
+ )
20
+ end
21
+
22
+ @params = {
23
+ "iColumns" => 3,
24
+ "bSearchable_0" => true,
25
+ "bSearchable_1" => true,
26
+ "bSearchable_2" => true,
27
+ "bSortable_0" => true,
28
+ "bSortable_1" => true,
29
+ "bSortable_2" => true,
30
+ "sSearch_0" => nil,
31
+ "sSearch_1" => nil,
32
+ "sSearch_2" => nil,
33
+ "sSearch" => nil }
34
+
35
+ Order.delete_all
36
+ @orders = [*0..20].map do
37
+ Factory(:order, :order_number => (42 + rand(2)), :memo => rand(2).even? ? 'hello' : 'goodbye')
38
+ end
39
+ end
40
+
41
+ it 'should search by one string column' do
42
+ @params['bSearchable_2'] = true # col2 = memo
43
+ @params['sSearch_2'] = "hello"
44
+ T.query(@params).to_json['aaData'].length.should == Order.where('memo LIKE ?', '%hello%').count
45
+ T.query(@params).to_json['aaData'].map { |r| r[2] }.uniq.should == ['hello']
46
+ end
47
+
48
+ it 'should search order number column for integer value' do
49
+ @params['bSearchable_1'] = true
50
+ @params['sSearch_1'] = "42"
51
+ expected = Order.where(:order_number => 42 ).map{|row| row.id.to_s }.sort
52
+ actual = T.query(@params).to_json['aaData'].map{|row| row[0]}.sort
53
+ actual.should == expected
54
+ end
55
+
56
+ it 'integer columns do not return results unless a number appears in the search string' do
57
+ order = Order.first
58
+ order.order_number = 0
59
+ order.save
60
+ @params['bSearchable_1'] = true
61
+ @params['sSearch_1'] = "0"
62
+ T.query(@params).to_json['aaData'][0][0].should == order.id.to_s
63
+ @params['sSearch_1'] = "a value without the integer zero"
64
+ T.query(@params).to_json['aaData'].should == []
65
+ end
66
+
67
+
68
+ it 'should search by multiple columns' do
69
+ @params['bSearchable_1'] = true
70
+ @params['sSearch_1'] = "42"
71
+ @params['bSearchable_2'] = true
72
+ @params['sSearch_2'] = "hello"
73
+ expected = Order.where('memo LIKE ?', '%hello%').where(:order_number => 42).map{|row| row.id.to_s }.sort
74
+ actual = T.query(@params).to_json['aaData'].map{|row| row[0] }.sort
75
+ actual.should == expected
76
+ end
77
+
78
+ it "should ignore columns that are flagged bSearchable=false" do
79
+ T.columns(
80
+ {'orders.id' => {:type => :integer, :bSearchable => false}},
81
+ {'orders.order_number' => {:type => :integer}},
82
+ {'orders.memo' => {:type => :string }}
83
+ )
84
+ @params['bSearchable_0'] = true
85
+ @params['sSearch_0'] = Order.last.id
86
+ lambda { T.query(@params) }.should raise_error
87
+ end
88
+
89
+ it "should strip whitespace off of search parameters" do
90
+ @params['bSearchable_2'] = true
91
+ @params['sSearch_2'] = ' hello '
92
+ expected = Order.where("memo like '%hello%'").all.map{|o| o.id.to_s }
93
+ actual = T.query(@params).to_json['aaData'].map{|r| r[0] }
94
+ expected.should == actual
95
+ end
96
+
97
+ it 'should account for non searchable columns' do
98
+ # T.columns(
99
+ # {'orders.id' => {:type => :integer, :bSearchable => false}},
100
+ # {'orders.order_number' => {:type => :integer}},
101
+ # {'orders.memo' => {:type => :string }} )
102
+ #
103
+ # # order_number is column zero since the first column is unsearchable
104
+ # order = Order.first
105
+ # @params['bSearchable_0'] = true
106
+ # @params['sSearch_0'] = order.order_number.to_s
107
+ # expected = Order.where(:order_number => order.order_number).all.map{|o| o.id.to_s }
108
+ # actual = T.query(@params).to_json['aaData'].map{|a| a[0] }
109
+ # actual.should == expected
110
+ pending
111
+ end
112
+
113
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SQL defined datatable supports searching when WHERE clause exists' do
4
+ before do
5
+ Object.send(:remove_const, :T) rescue nil
6
+ class T < Datatable::Base
7
+ sql <<-SQL
8
+ SELECT
9
+ id,
10
+ order_number,
11
+ memo
12
+ FROM
13
+ orders
14
+ SQL
15
+ columns(
16
+ {'orders.id' => {:type => :integer}},
17
+ {'orders.order_number' => {:type => :integer}},
18
+ {'orders.memo' => {:type => :string }}
19
+ )
20
+ end
21
+
22
+ @params = {
23
+ "iColumns" => 4,
24
+ "bSearchable_0" => true,
25
+ "bSearchable_1" => true,
26
+ "bSearchable_2" => true,
27
+ "bSortable_0" => true,
28
+ "bSortable_1" => true,
29
+ "bSortable_2" => true,
30
+ "sSearch_0" => nil,
31
+ "sSearch_1" => nil,
32
+ "sSearch_2" => nil,
33
+ "sSearch" => nil }
34
+
35
+ Order.delete_all
36
+ @orders = [*0..20].map do
37
+ Factory(:order, :order_number => (42 + rand(2)), :memo => rand(2).even? ? 'hello' : 'goodbye')
38
+ end
39
+ end
40
+
41
+
42
+ it "demonstrate that you can't include a where in the base sql fragment" do
43
+ T.sql <<-SQL
44
+ SELECT
45
+ id,
46
+ order_number,
47
+ memo
48
+ FROM
49
+ orders
50
+ WHERE
51
+ memo LIKE '%ello%'
52
+ SQL
53
+ @params['sSearch'] = Order.order(:id).first.id.to_s
54
+ lambda { T.query(@params) }.should raise_error(ActiveRecord::StatementInvalid)
55
+ end
56
+
57
+ it "handles where in separate call" do
58
+ T.where <<-SQL
59
+ memo LIKE 'foo bar baz'
60
+ SQL
61
+ T.sql <<-SQL
62
+ SELECT
63
+ id,
64
+ order_number,
65
+ memo
66
+ FROM
67
+ orders
68
+ SQL
69
+ # create search parameters that use both global and individual
70
+ # column search to find an order known to exist
71
+ order = Order.order('order_number DESC').first
72
+ @params['sSearch'] = order.id.to_s
73
+ @params['bSearchable_1'] = true
74
+ @params['sSearch_1'] = order.order_number.to_s
75
+
76
+ # test to make sure it's not present in result because where clause excluded it
77
+ T.query(@params).to_json['aaData'].should be_empty
78
+
79
+ # modify this order so it will satisfy the query
80
+ order.memo = "foo bar baz"
81
+ order.save
82
+
83
+ # test to make sure it is present in result because where clause excluded it
84
+ T.query(@params).to_json['aaData'][0][0].should == order.id.to_s
85
+ end
86
+
87
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'query responds to sort parameters on sql defined datatable' do
4
+ before do
5
+ Object.send(:remove_const, :T) rescue nil
6
+ class T < Datatable::Base
7
+ sql <<-SQL
8
+ SELECT
9
+ id,
10
+ order_number,
11
+ memo
12
+ FROM
13
+ orders
14
+ SQL
15
+ columns(
16
+ {'orders.id' => {:type => :integer}},
17
+ {'orders.order_number' => {:type => :integer}},
18
+ {'orders.memo' => {:type => :string }}
19
+ )
20
+ end
21
+
22
+ @params = {
23
+ "iColumns" => 4,
24
+ "bSearchable_0" => true,
25
+ "bSearchable_1" => true,
26
+ "bSearchable_2" => true,
27
+ "bSortable_0" => true,
28
+ "bSortable_1" => true,
29
+ "bSortable_2" => true,
30
+ "sSearch_0" => nil,
31
+ "sSearch_1" => nil,
32
+ "sSearch_2" => nil,
33
+ "sSearch" => nil }
34
+
35
+ Order.delete_all
36
+ @orders = [*0..20].map do
37
+ Factory(:order, :order_number => (42 + rand(2)), :memo => rand(2).even? ? 'hello' : 'goodbye')
38
+ end
39
+ end
40
+
41
+ it 'sorts single column' do
42
+ @params['iSortCol_0'] = 0
43
+ @params['sSortDir_0'] = 'desc' # Assume first col is ID
44
+ @params['iSortingCols'] = 1
45
+ T.query(@params).to_json['aaData'][0][0].should == Order.order("id desc").first.id.to_s
46
+ end
47
+
48
+ it 'sorts multiple columns' do
49
+ @params['iSortCol_0'] = 2 # Memo
50
+ @params['sSortDir_0'] = 'asc'
51
+
52
+ @params['iSortCol_1'] = 0 # ID
53
+ @params['sSortDir_1'] = 'desc'
54
+
55
+ @params['iSortingCols'] = 2
56
+
57
+
58
+ T.query(@params).to_json['aaData'][0][0].should == Order.order('memo asc, id desc')[0].id.to_s
59
+ T.query(@params).to_json['aaData'][-1][0].should == Order.order('memo asc, id desc')[-1].id.to_s
60
+ end
61
+
62
+ it 'sorts ascending and descending' do
63
+ @params['iSortCol_0'] = 2 # Memo
64
+ @params['sSortDir_0'] = 'desc'
65
+
66
+ @params['iSortCol_1'] = 0 # ID
67
+ @params['sSortDir_1'] = 'asc'
68
+
69
+ @params['iSortingCols'] = 2
70
+
71
+
72
+ T.query(@params).to_json['aaData'][0][0].should == Order.order('memo desc, id asc')[0].id.to_s
73
+ T.query(@params).to_json['aaData'][-1][0].should == Order.order('memo desc, id asc')[-1].id.to_s
74
+ end
75
+
76
+ it "it does not sort columns where bSortable is false"
77
+
78
+
79
+
80
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'variable substitution' do
4
+
5
+ before do
6
+ Object.send(:remove_const, :T) rescue nil
7
+ 3.times { Factory(:order) }
8
+ @params = { "iColumns" => 1 }
9
+ end
10
+
11
+ describe "in sql clause" do
12
+ it 'of simple variables' do
13
+ class T < Datatable::Base
14
+ sql <<-SQL
15
+ SELECT
16
+ orders.id
17
+ FROM
18
+ orders
19
+ WHERE
20
+ orders.id = {{order_id}}
21
+ SQL
22
+ columns(
23
+ {'orders.id' => {:type => :integer}}
24
+ )
25
+ end
26
+ order_id = Order.last.id
27
+ T.query(@params, :order_id => order_id).to_json['aaData'].length.should == 1
28
+ T.query(@params, :order_id => order_id).to_json['aaData'].flatten.first.should == order_id.to_s
29
+ end
30
+
31
+ it 'of arrays' do
32
+ class T < Datatable::Base
33
+ sql <<-SQL
34
+ SELECT
35
+ orders.id
36
+ FROM
37
+ orders
38
+ WHERE
39
+ orders.id IN {{order_ids}}
40
+ SQL
41
+ columns(
42
+ {'orders.id' => {:type => :integer}}
43
+ )
44
+ end
45
+ order_ids = Order.all.map{|order| order.id }.sort
46
+ T.query(@params, :order_ids => order_ids).to_json['aaData'].flatten.sort.should == Order.order(:id).all.map {|o| o.id.to_s }
47
+ end
48
+ end
49
+
50
+ it 'in count clause' do
51
+ class T < Datatable::Base
52
+ count <<-SQL
53
+ SELECT
54
+ count(orders.id)
55
+ FROM
56
+ orders
57
+ SQL
58
+ sql <<-SQL
59
+ SELECT
60
+ orders.id
61
+ FROM
62
+ orders
63
+ SQL
64
+ where <<-SQL
65
+ orders.id = {{order_id}}
66
+ SQL
67
+ columns(
68
+ {'orders.id' => {:type => :integer}}
69
+ )
70
+ end
71
+ order_id = Order.last.id
72
+ T.query(@params, :order_id => order_id).to_json['aaData'].length.should == 1
73
+ T.query(@params, :order_id => order_id).to_json['aaData'].should == [[order_id.to_s]]
74
+ end
75
+
76
+ describe "in where and count clause" do
77
+ it "should do something" do
78
+ class T < Datatable::Base
79
+ count <<-SQL
80
+ SELECT
81
+ count(orders.id)
82
+ FROM
83
+ orders
84
+ SQL
85
+ sql <<-SQL
86
+ SELECT
87
+ orders.id
88
+ FROM
89
+ orders
90
+ SQL
91
+ where <<-SQL
92
+ orders.id = {{order_id}}
93
+ SQL
94
+ columns(
95
+ {'orders.id' => {:type => :integer}}
96
+ )
97
+ end
98
+ order_id = Order.last.id
99
+ end
100
+ end
101
+
102
+
103
+
104
+ end
@@ -0,0 +1,4 @@
1
+ Factory.define(:customer) do |f|
2
+ f.first_name "Fred"
3
+ f.last_name "Johnson"
4
+ end
@@ -0,0 +1,2 @@
1
+ Factory.define(:item) do |f|
2
+ end
@@ -0,0 +1,7 @@
1
+ memo_words = %W[ black blue brown green purple red white yellow ]
2
+
3
+ Factory.define(:order) do |f|
4
+ f.order_number rand(239832981)
5
+ f.memo memo_words[rand(memo_words.length - 1)]
6
+ f.association :customer, :factory => :customer
7
+ end
@@ -0,0 +1,2 @@
1
+ Factory.define(:order_item) do |f|
2
+ end
@@ -0,0 +1,4 @@
1
+ Factory.define(:sales_rep) do |f|
2
+ f.first_name "Robert"
3
+ f.last_name "Johnson"
4
+ end