datatable 0.1.1alpha4 → 0.2pre1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ vendor/ruby
5
5
  example_app/config/database.yml
6
6
  */**/.DS_Store
7
7
  .DS_Store
8
+ .*.swp
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'rake/clean'
2
2
  require 'rdoc/task'
3
3
 
4
+ $:.push File.expand_path("../lib", __FILE__)
5
+ require "datatable/version"
6
+
4
7
  CLOBBER.include('*.gem')
5
8
 
6
9
  task :default do
@@ -4,3 +4,4 @@ log/*.log
4
4
  tmp/
5
5
  vendor/ruby
6
6
  .DS_Store
7
+ .*.swp
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- datatable (0.1.0alpha2)
4
+ datatable (0.2pre1)
5
5
  rails (>= 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,19 @@
1
1
  class OrdersController < ApplicationController
2
2
 
3
3
  def index
4
- @datatable = OrdersIndex
4
+ end
5
+
6
+ def example1
7
+ @datatable = Example1
8
+ respond_to do |format|
9
+ format.html
10
+ format.js { render :json => @datatable.query(params).to_json }
11
+ end
12
+ end
13
+
14
+ def example2
15
+ @datatable = Example2
16
+ @datatable.relation = Order.select([:order_number, :memo]).where(["memo like ?", 'red'])
5
17
  respond_to do |format|
6
18
  format.html
7
19
  format.js { render :json => @datatable.query(params).to_json }
@@ -1,4 +1,4 @@
1
- class OrdersIndex < Datatable::Base
1
+ class Example1 < Datatable::Base
2
2
 
3
3
  sql <<-SQL
4
4
  SELECT
@@ -0,0 +1,13 @@
1
+ class Example2 < Datatable::Base
2
+
3
+ set_model Order
4
+
5
+ column :id, :type => :integer, :sTitle => "Id"
6
+ column :memo
7
+
8
+ option('individual_column_searching', true)
9
+ option('sDom', '<"clear"><"H"Trf>t<"F"i>')
10
+ option('bScrollInfinite', true)
11
+ option('bScrollCollapse', true)
12
+ option('sScrollY', '200px')
13
+ end
@@ -0,0 +1,11 @@
1
+ <h1>Example #1</h1>
2
+
3
+ <%#= stylesheet_link_tag '/datatable/css/demo_table.css' %>
4
+
5
+ <%= stylesheet_link_tag '/datatable/css/smoothness/jquery-ui-1.8.14.custom.css' %>
6
+ <%= stylesheet_link_tag '/datatable/css/demo_table_jui.css' %>
7
+
8
+ <%= datatable %>
9
+
10
+
11
+ <%= javascript_include_datatable %>
@@ -0,0 +1,10 @@
1
+ <h1>Example #2</h1>
2
+
3
+ <%#= stylesheet_link_tag '/datatable/css/demo_table.css' %>
4
+
5
+ <%= stylesheet_link_tag '/datatable/css/smoothness/jquery-ui-1.8.14.custom.css' %>
6
+ <%= stylesheet_link_tag '/datatable/css/demo_table_jui.css' %>
7
+
8
+ <%= datatable %>
9
+
10
+ <%= javascript_include_datatable %>
@@ -1,14 +1,5 @@
1
-
2
- <h1>
3
- Orders
4
- </h1>
5
-
6
- <%#= stylesheet_link_tag '/datatable/css/demo_table.css' %>
7
-
8
- <%= stylesheet_link_tag '/datatable/css/smoothness/jquery-ui-1.8.14.custom.css' %>
9
- <%= stylesheet_link_tag '/datatable/css/demo_table_jui.css' %>
10
-
11
- <%= datatable %>
12
-
13
-
14
- <%= javascript_include_datatable %>
1
+ <h1>Datatable Examples</h1>
2
+ <ul>
3
+ <li><%= link_to "example 1", example1_path %> - sql override</li>
4
+ <li><%= link_to "example 2", example2_path %> - active relation</li>
5
+ </ul>
@@ -1,6 +1,9 @@
1
1
  RailsApp::Application.routes.draw do
2
2
 
3
+ match "example1" => "orders#example1", :as => 'example1'
4
+ match "example2" => "orders#example2", :as => 'example2'
5
+
3
6
  resources :orders
4
- root :to => "orders#index"
5
7
 
8
+ root :to => "orders#index"
6
9
  end
@@ -2,14 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe 'Generating sql based on our DSL' do
4
4
 
5
- # it 'should work' do
6
- # Order.create!(:order_number => 32)
7
- # datatable = OrdersIndex.new
8
- # params = {}
9
- # json = datatable.query(params).json
10
- # json['aaRecords'][0][0].should == 32
11
- # end
12
-
13
5
  it 'should select two fields' do
14
6
  class OrdersSimple < Datatable::Base
15
7
  set_model Order
@@ -37,6 +29,7 @@ describe 'Generating sql based on our DSL' do
37
29
  OrdersSimple.relation.should == Order.select(orders[:memo]).joins(:customer)
38
30
  end
39
31
 
32
+
40
33
  it 'should handle a join with an inner column' do
41
34
  class OrdersSimple < Datatable::Base
42
35
  set_model Order
@@ -46,6 +46,8 @@ describe 'SQL defined datatable supports global search' do
46
46
  end
47
47
 
48
48
  it 'integer columns' do
49
+ # make sure all of the order numbers are nil so they don't match
50
+ Order.update_all(:order_number => nil)
49
51
  order_id = Order.all[rand(Order.count)].id.to_s
50
52
  @params['sSearch'] = order_id
51
53
  T.query(@params).to_json['aaData'][0][0].should == order_id
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'variable substitution' do
3
+ describe 'variable substitution in' do
4
4
 
5
5
  before do
6
6
  Object.send(:remove_const, :T) rescue nil
@@ -8,97 +8,64 @@ describe 'variable substitution' do
8
8
  @params = { "iColumns" => 1 }
9
9
  end
10
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
11
+ it "sql clause handles strings" do
12
+ class T < Datatable::Base
13
+ count "SELECT count(orders.id) FROM orders"
14
+ sql "SELECT orders.id FROM {{table}}"
15
+ columns({'orders.id' => {:type => :integer}})
29
16
  end
17
+ T.query(@params, :table => "orders").to_json['aaData'].flatten.sort.should == Order.all.map(&:id).map(&:to_s).sort
18
+ end
30
19
 
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 }
20
+ it "count clause handles strings" do
21
+ class T < Datatable::Base
22
+ count "SELECT count(orders.id) FROM {{table}}"
23
+ sql "SELECT orders.id FROM orders"
24
+ columns({'orders.id' => {:type => :integer}})
25
+ end
26
+ T.query(@params, :table => "orders").to_json['aaData'].flatten.sort.should == Order.all.map(&:id).map(&:to_s).sort
27
+ end
28
+
29
+ it "where clause handles strings" do
30
+ class T < Datatable::Base
31
+ count "SELECT count(orders.id) FROM orders"
32
+ sql "SELECT orders.id FROM orders"
33
+ where "{{table}}.id IS NOT NULL"
34
+ columns({'orders.id' => {:type => :integer}})
47
35
  end
36
+ T.query(@params, :table => "orders").to_json['aaData'].flatten.sort.should == Order.all.map(&:id).map(&:to_s).sort
48
37
  end
49
38
 
50
- it 'in count clause' do
39
+ it "where clause handles arrays" do
51
40
  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
- )
41
+ count "SELECT count(orders.id) FROM orders"
42
+ sql "SELECT orders.id FROM orders"
43
+ where "orders.id in {{order_ids}}"
44
+ columns({'orders.id' => {:type => :integer}})
70
45
  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]]
46
+ T.query(@params, :order_ids => Order.all.map(&:id)).to_json['aaData'].flatten.sort.should == Order.all.map(&:id).map(&:to_s).sort
74
47
  end
75
48
 
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
49
+ it "where clause handles empty arrays" do
50
+ class T < Datatable::Base
51
+ count "SELECT count(orders.id) FROM orders"
52
+ sql "SELECT orders.id FROM orders"
53
+ where "orders.id in {{order_ids}}"
54
+ columns({'orders.id' => {:type => :integer}})
99
55
  end
56
+ T.query(@params, :order_ids => []).to_json['aaData'].flatten.should == []
100
57
  end
101
58
 
59
+ it "where clause handles multiple calls" do
60
+ class T < Datatable::Base
61
+ count "SELECT count(orders.id) FROM orders"
62
+ sql "SELECT orders.id FROM orders"
63
+ where "orders.id = {{order_ids}}"
64
+ columns({'orders.id' => {:type => :integer}})
65
+ end
66
+ T.query(@params, :order_ids => Order.order(:id).first.id ).to_json['aaData'].flatten.sort.should == [Order.order(:id).first.id.to_s]
67
+ T.query(@params, :order_ids => Order.order(:id).last.id ).to_json['aaData'].flatten.sort.should == [Order.order(:id).last.id.to_s]
68
+ end
102
69
 
103
70
 
104
71
  end
@@ -10,6 +10,10 @@ module Datatable
10
10
  @relation
11
11
  end
12
12
 
13
+ def relation=(arg)
14
+ @relation = arg
15
+ end
16
+
13
17
  def set_model(model)
14
18
  @model = model
15
19
  @relation = model
@@ -25,9 +29,10 @@ module Datatable
25
29
 
26
30
  @columns ||= ActiveSupport::OrderedHash.new
27
31
 
28
- column_hash = {}
29
- column_hash[:type] = current_model.columns.detect{ |col| col.name == c.to_s}.type
30
- column_hash[:link_to] = options[:link_to]
32
+ column_hash = options
33
+ unless column_hash[:type]
34
+ column_hash[:type] = current_model.columns.detect{ |col| col.name == c.to_s}.type
35
+ end
31
36
 
32
37
  @columns["#{current_model.table_name}.#{c}"] = column_hash
33
38
 
@@ -36,7 +41,6 @@ module Datatable
36
41
 
37
42
  # TODO: Change to joins to match arel
38
43
  def join(association, &block)
39
-
40
44
  @inner_model = current_model.reflect_on_association(association).klass
41
45
  @relation = @relation.joins(association)
42
46
  instance_eval(&block) if block_given?
@@ -1,4 +1,4 @@
1
1
  module Datatable
2
2
  # http://semver.org
3
- VERSION = "0.1.1alpha4"
3
+ VERSION = "0.2pre1"
4
4
  end
data/lib/datatable.rb CHANGED
@@ -58,14 +58,16 @@ module Datatable
58
58
  attr_accessor :records
59
59
 
60
60
  def self.sql(*args)
61
- return @sql_string if args.empty?
62
-
63
- @sql_string = args.first
61
+ if args.empty?
62
+ @sql_string
63
+ else
64
+ @sql_string = args.first
65
+ end
64
66
  end
65
-
67
+
66
68
  def self.count(*args)
67
69
  if args.empty?
68
- return @count_sql
70
+ @count_sql
69
71
  else
70
72
  @count_sql = args.first
71
73
  end
@@ -73,14 +75,14 @@ module Datatable
73
75
 
74
76
  def self.where(*args)
75
77
  if args.empty?
76
- return @where_sql
78
+ @where_sql
77
79
  else
78
80
  @where_sql = args.first
79
81
  end
80
82
  end
81
83
 
82
- def self.sql_string
83
- @sql_string
84
+ def self.template_text
85
+ (where || "") + (count || "") + (sql || "")
84
86
  end
85
87
 
86
88
  def self.columns(*args)
@@ -126,28 +128,20 @@ module Datatable
126
128
  skparams[key] = (value ? true : false) if key =~ /^b/
127
129
  end
128
130
 
129
- if @sql_string && !@already_substituted
130
- substitute_variables(variables)
131
+ # scan the template text looking for the variables so
132
+ # we can give a sensible error if it's missing
133
+ variables.each do |key, value|
134
+ unless template_text =~ /#{key}/m
135
+ fail "Substitution key: '#{key}' not in found in SQL text"
136
+ end
131
137
  end
132
- @already_substituted = true
133
-
138
+
134
139
  datatable = new(skparams)
135
- datatable.count
136
- datatable.instance_query
140
+ datatable.count(variables)
141
+ datatable.instance_query(variables)
137
142
  datatable
138
143
  end
139
144
 
140
- def self.substitute_variables(substitutions)
141
- substitutions.stringify_keys.each do |key, value|
142
- unless "#{@where_sql}#{@count_sql}#{@sql_string}" =~ /#{key}/m
143
- fail "Substitution key: '#{key}' not in found in SQL text"
144
- end
145
- new_text = value.kind_of?(Array) ? "(#{value.join(', ')})" : value.to_s
146
- @where_sql.try(:gsub!,"{{#{key}}}", new_text )
147
- @sql_string.try(:gsub!, "{{#{key}}}", new_text)
148
- @count_sql.try(:gsub!,"{{#{key}}}", new_text)
149
- end
150
- end
151
145
 
152
146
  # only used in testing
153
147
  def self.to_sql
@@ -174,13 +168,13 @@ module Datatable
174
168
  @records = []
175
169
  end
176
170
 
177
- def instance_query
178
- @records = self.class.sql_string ? sql_instance_query : active_record_instance_query
171
+ def instance_query(variables={})
172
+ @records = self.class.sql ? sql_instance_query(variables) : active_record_instance_query
179
173
  self
180
174
  end
181
175
 
182
- def count
183
- @count = self.class.sql_string ? sql_count : self.class.relation.count
176
+ def count(variables={})
177
+ @count = self.class.sql ? sql_count(variables) : self.class.relation.count
184
178
  end
185
179
 
186
180
 
@@ -195,27 +189,78 @@ module Datatable
195
189
 
196
190
  private
197
191
 
198
- def sql_count
199
- if self.class.count
200
- count_sql = self.class.count.dup
201
- if self.class.where && !@already_counted
202
- count_sql << " WHERE " + self.class.where
203
- end
204
- @already_counted = true
192
+ # def sql_count
193
+ # if self.class.count
194
+ # count_sql = self.class.count.dup
195
+ # if self.class.where && !@already_counted
196
+ # count_sql << " WHERE " + self.class.where
197
+ # end
198
+ # @already_counted = true
199
+ # else
200
+ # count_sql = query_sql.sub(/^\s*SELECT(.*?)FROM/mi, 'SELECT count(*) FROM')
201
+ # # we don't tak the where on because it's already been done inside query_sql
202
+ # end
203
+ # ActiveRecord::Base.connection.select_value(count_sql).to_i
204
+ # end
205
+ #
206
+ def sql_string
207
+ self.class.sql ? self.class.sql.dup : nil
208
+ end
209
+
210
+ def where_string
211
+ self.class.where ? self.class.where.dup : nil
212
+ end
213
+
214
+ def count_string
215
+ self.class.count ? self.class.count.dup : nil
216
+ end
217
+
218
+ def sql_count(variables)
219
+ if count_string.blank?
220
+ query = query_sql.sub(/^\s*SELECT(.*?)FROM/mi, 'SELECT count(*) FROM')
205
221
  else
206
- count_sql = query_sql.sub(/^\s*SELECT(.*?)FROM/mi, 'SELECT count(*) FROM')
207
- # we don't tak the where on because it's already been done inside query_sql
222
+ if where_string.blank?
223
+ query = count_string
224
+ else
225
+ query = count_string + " WHERE " + where_string
226
+ end
208
227
  end
209
- ActiveRecord::Base.connection.select_value(count_sql).to_i
228
+ query = substitute_variables(query.dup, variables)
229
+ ActiveRecord::Base.connection.select_value(query).to_i
210
230
  end
211
231
 
212
232
  def column_attributes
213
233
  self.class.columns
214
234
  end
215
235
 
216
- def sql_instance_query
236
+ def evaluate_variable(value)
237
+ if value.kind_of?(Array)
238
+ if value.empty?
239
+ return "(NULL)"
240
+ else
241
+ return "(#{value.join(',')})"
242
+ end
243
+ end
244
+ value.to_s
245
+ end
246
+
247
+ def substitute_variables(template, substitutions)
248
+ result = template.dup
249
+ substitutions.stringify_keys.each do |key, value|
250
+ if template =~ /#{key}/m
251
+ result.gsub!("{{#{key}}}", evaluate_variable(value))
252
+ else
253
+ #fail "Substitution key: '#{key}' not in found in SQL text\n#{template}"
254
+ end
255
+ end
256
+ result
257
+ end
258
+
259
+ def sql_instance_query(variables)
260
+ query = query_sql + order_by_sql_fragment + limit_offset_sql_fragment
261
+ query = substitute_variables(query.dup, variables)
217
262
  connection = self.class.model ? self.class.model.connection : ActiveRecord::Base.connection
218
- connection.select_rows(query_sql + order_by_sql_fragment + limit_offset_sql_fragment)
263
+ connection.select_rows(query)
219
264
  end
220
265
 
221
266
  def active_record_instance_query
@@ -319,7 +364,7 @@ module Datatable
319
364
  end
320
365
 
321
366
  def query_sql
322
- result = self.class.sql_string.dup
367
+ result = self.class.sql.dup
323
368
  if self.class.where
324
369
  result << " WHERE " + self.class.where
325
370
  if search_string
metadata CHANGED
@@ -1,50 +1,35 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: datatable
3
- version: !ruby/object:Gem::Version
4
- hash: -3702664372
5
- prerelease: 5
6
- segments:
7
- - 0
8
- - 1
9
- - 1
10
- - alpha
11
- - 4
12
- version: 0.1.1alpha4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2pre1
5
+ prerelease: 3
13
6
  platform: ruby
14
- authors:
7
+ authors:
15
8
  - Michael Greenly
16
9
  - Mischa Fierer
17
10
  autorequire:
18
11
  bindir: bin
19
12
  cert_chain: []
20
-
21
- date: 2011-07-18 00:00:00 Z
22
- dependencies:
23
- - !ruby/object:Gem::Dependency
13
+ date: 2011-08-07 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
24
16
  name: rails
25
- version_requirements: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &12836780 !ruby/object:Gem::Requirement
26
18
  none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 7
31
- segments:
32
- - 3
33
- - 0
34
- version: "3.0"
35
- prerelease: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '3.0'
36
23
  type: :runtime
37
- requirement: *id001
24
+ prerelease: false
25
+ version_requirements: *12836780
38
26
  description: A Rails plugin for the jquery.datatables library
39
- email:
27
+ email:
40
28
  - michaelgreenly@logic-refinery.com
41
29
  executables: []
42
-
43
30
  extensions: []
44
-
45
31
  extra_rdoc_files: []
46
-
47
- files:
32
+ files:
48
33
  - .bundle/config
49
34
  - .gitignore
50
35
  - .rspec
@@ -63,7 +48,8 @@ files:
63
48
  - example_app/Rakefile
64
49
  - example_app/app/controllers/application_controller.rb
65
50
  - example_app/app/controllers/orders_controller.rb
66
- - example_app/app/datatables/orders_index.rb
51
+ - example_app/app/datatables/example1.rb
52
+ - example_app/app/datatables/example2.rb
67
53
  - example_app/app/helpers/application_helper.rb
68
54
  - example_app/app/models/customer.rb
69
55
  - example_app/app/models/item.rb
@@ -71,6 +57,8 @@ files:
71
57
  - example_app/app/models/order_item.rb
72
58
  - example_app/app/models/sales_rep.rb
73
59
  - example_app/app/views/layouts/application.html.erb
60
+ - example_app/app/views/orders/example1.html.erb
61
+ - example_app/app/views/orders/example2.html.erb
74
62
  - example_app/app/views/orders/index.html.erb
75
63
  - example_app/config.ru
76
64
  - example_app/config/application.rb
@@ -233,38 +221,26 @@ files:
233
221
  - vendor/datatable/media/js/jquery.dataTables.min.js
234
222
  homepage: https://github.com/logic-refinery/datatable
235
223
  licenses: []
236
-
237
224
  post_install_message:
238
225
  rdoc_options: []
239
-
240
- require_paths:
226
+ require_paths:
241
227
  - lib
242
- required_ruby_version: !ruby/object:Gem::Requirement
228
+ required_ruby_version: !ruby/object:Gem::Requirement
243
229
  none: false
244
- requirements:
245
- - - ">="
246
- - !ruby/object:Gem::Version
247
- hash: 3
248
- segments:
249
- - 0
250
- version: "0"
251
- required_rubygems_version: !ruby/object:Gem::Requirement
230
+ requirements:
231
+ - - ! '>='
232
+ - !ruby/object:Gem::Version
233
+ version: '0'
234
+ required_rubygems_version: !ruby/object:Gem::Requirement
252
235
  none: false
253
- requirements:
254
- - - ">"
255
- - !ruby/object:Gem::Version
256
- hash: 25
257
- segments:
258
- - 1
259
- - 3
260
- - 1
236
+ requirements:
237
+ - - ! '>'
238
+ - !ruby/object:Gem::Version
261
239
  version: 1.3.1
262
240
  requirements: []
263
-
264
241
  rubyforge_project:
265
242
  rubygems_version: 1.8.5
266
243
  signing_key:
267
244
  specification_version: 3
268
245
  summary: A Rails plugin for the jquery.datatables library
269
246
  test_files: []
270
-