datatable 0.1.1alpha4 → 0.2pre1

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