rails-tables 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/tables/column.rb +53 -0
- data/app/tables/datatable.rb +68 -118
- data/app/tables/search.rb +68 -0
- data/lib/rails-tables/model_additions.rb +13 -0
- data/lib/rails-tables/version.rb +1 -1
- data/lib/rails-tables.rb +1 -0
- metadata +6 -3
@@ -0,0 +1,53 @@
|
|
1
|
+
class Column
|
2
|
+
|
3
|
+
attr_accessor :name, :column_name, :referring_column_name, :render_with, :sortable, :blank_value
|
4
|
+
def initialize(name, *args)
|
5
|
+
self.name = name
|
6
|
+
|
7
|
+
attributes = args.pop || {}
|
8
|
+
self.column_name = attributes.fetch(:column_name, name)
|
9
|
+
self.referring_column_name = attributes.fetch(:referring_column_name, nil)
|
10
|
+
self.render_with = attributes.fetch(:render_with, :default_render)
|
11
|
+
self.sortable = attributes.fetch(:sortable, true)
|
12
|
+
self.blank_value = attributes.fetch(:blank_value, '–')
|
13
|
+
|
14
|
+
define_singleton_method :render do |view, object|
|
15
|
+
if self.render_with.kind_of? Symbol
|
16
|
+
content = self.send(self.render_with, view, object)
|
17
|
+
else
|
18
|
+
content = self.render_with.call(view, object)
|
19
|
+
end
|
20
|
+
content.present? ? content.to_s.html_safe : self.blank_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_render(view, object)
|
25
|
+
property = object.send(self.column_name)
|
26
|
+
property if not property.nil?
|
27
|
+
end
|
28
|
+
def self_referential_link(view, object)
|
29
|
+
property = object.send(self.column_name)
|
30
|
+
view.link_to property, object if not property.nil?
|
31
|
+
end
|
32
|
+
def related_link(view, object)
|
33
|
+
property = object.send(self.column_name)
|
34
|
+
view.link_to self.name, property if not property.nil?
|
35
|
+
end
|
36
|
+
def related_link_list(view, object)
|
37
|
+
property = object.send(self.referring_column_name)
|
38
|
+
property.collect { |related_object| self_referential_link(view, related_object) }.join(', ') if not property.nil?
|
39
|
+
end
|
40
|
+
def time(view, object)
|
41
|
+
property = object.send(self.column_name)
|
42
|
+
property.strftime("%I:%M%p") if not property.nil?
|
43
|
+
end
|
44
|
+
def date(view, object)
|
45
|
+
property = object.send(self.column_name)
|
46
|
+
property.strftime("%m/%d/%Y") if not property.nil?
|
47
|
+
end
|
48
|
+
def datetime(view, object)
|
49
|
+
property = object.send(self.column_name)
|
50
|
+
property.strftime("%m/%d/%Y at %I:%M%p") if not property.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/app/tables/datatable.rb
CHANGED
@@ -1,131 +1,81 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
1
|
+
class Datatable
|
2
|
+
delegate :params, to: 'self.view'
|
3
|
+
|
4
|
+
attr_accessor :view, :filters
|
5
|
+
def initialize(view, filters={})
|
6
|
+
self.view = view
|
7
|
+
self.filters = filters
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
def as_json(options = {})
|
11
|
+
{
|
12
|
+
sEcho: params[:sEcho].to_i,
|
13
|
+
iTotalRecords: objects.size,
|
14
|
+
iTotalDisplayRecords: objects.total_entries,
|
15
|
+
aaData: data
|
16
|
+
}
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
def self.included(base)
|
29
|
-
base.extend ClassMethods
|
19
|
+
class << self
|
20
|
+
attr_accessor :columns, :searches
|
21
|
+
def column(name, *args)
|
22
|
+
arguments = args.pop || {}
|
23
|
+
self.columns = [] if self.columns.nil?
|
24
|
+
self.columns << Column.new(name, arguments)
|
30
25
|
end
|
26
|
+
# def search_by(name, *args)
|
27
|
+
# arguments = args.pop || {}
|
28
|
+
# self.searches = [] if self.searches.nil?
|
29
|
+
# self.searches << Search.new(name, self.table, arguments)
|
30
|
+
# end
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
+
private
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
@filters.each do |method, arguments|
|
41
|
-
objects = objects.send(method, arguments)
|
42
|
-
end
|
43
|
-
if params[:sSearch].present?
|
44
|
-
terms = params[:sSearch].split.map{|s| s+="%"}
|
45
|
-
columns = self.searches.keys.map(&:to_s)
|
46
|
-
objects = objects.full_text_search(columns, terms)
|
47
|
-
#objects = objects.where("name like :search or category like :search", search: "%#{params[:sSearch]}%")
|
48
|
-
end
|
49
|
-
objects = objects.paginate(page: page, per_page: per_page)
|
50
|
-
objects
|
35
|
+
def objects
|
36
|
+
if sortable
|
37
|
+
objects = self.class.model.reorder("#{sort_column} #{sort_direction}")
|
38
|
+
else
|
39
|
+
objects = self.class.model
|
51
40
|
end
|
52
|
-
|
53
|
-
|
54
|
-
params[:iDisplayStart].to_i/per_page + 1
|
55
|
-
end
|
56
|
-
def per_page
|
57
|
-
params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
|
58
|
-
end
|
59
|
-
|
60
|
-
def sortable
|
61
|
-
self.class.columns.map{ |column| column.sortable }[params[:iSortCol_0].to_i]
|
62
|
-
end
|
63
|
-
def sort_column
|
64
|
-
self.class.columns.map(&:column_name)[params[:iSortCol_0].to_i]
|
65
|
-
end
|
66
|
-
def sort_direction
|
67
|
-
params[:sSortDir_0] == "desc" ? "desc" : "asc"
|
41
|
+
@filters.each do |method, arguments|
|
42
|
+
objects = objects.send(method, arguments)
|
68
43
|
end
|
44
|
+
# if params[:sSearch].present?
|
45
|
+
# objects = self.model(:datatable_search, search(objects, params[:sSearch]))
|
46
|
+
# #objects = objects.where("name like :search or category like :search", search: "%#{params[:sSearch]}%")
|
47
|
+
# end
|
48
|
+
objects = objects.paginate(page: page, per_page: per_page)
|
49
|
+
objects
|
50
|
+
end
|
69
51
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
52
|
+
def search(objects, terms)
|
53
|
+
self.class.searches.each do |search|
|
54
|
+
objects = search.search(objects, terms)
|
74
55
|
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def page
|
59
|
+
params[:iDisplayStart].to_i/per_page + 1
|
60
|
+
end
|
61
|
+
def per_page
|
62
|
+
params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
|
63
|
+
end
|
64
|
+
|
65
|
+
def sortable
|
66
|
+
self.class.columns.map{ |column| column.sortable }[params[:iSortCol_0].to_i]
|
67
|
+
end
|
68
|
+
def sort_column
|
69
|
+
self.class.columns.map(&:column_name)[params[:iSortCol_0].to_i]
|
70
|
+
end
|
71
|
+
def sort_direction
|
72
|
+
params[:sSortDir_0] == "desc" ? "desc" : "asc"
|
73
|
+
end
|
75
74
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def initialize(name, *args)
|
80
|
-
self.name = name
|
81
|
-
|
82
|
-
attributes = args.pop || {}
|
83
|
-
self.column_name = attributes.fetch(:column_name, name)
|
84
|
-
self.referring_column_name = attributes.fetch(:referring_column_name, nil)
|
85
|
-
self.render_with = attributes.fetch(:render_with, :default_render)
|
86
|
-
self.sortable = attributes.fetch(:sortable, true)
|
87
|
-
self.default = attributes.fetch(:default, '–')
|
88
|
-
|
89
|
-
define_singleton_method :render do |view, object|
|
90
|
-
if self.render_with.kind_of? Symbol
|
91
|
-
content = self.send(self.render_with, view, object)
|
92
|
-
else
|
93
|
-
content = self.render_with.call(view, object)
|
94
|
-
end
|
95
|
-
content.present? ? content.to_s.html_safe : self.default
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def default_render(view, object)
|
100
|
-
property = object.send(self.column_name)
|
101
|
-
property if not property.nil?
|
102
|
-
end
|
103
|
-
def self_referential_link(view, object)
|
104
|
-
property = object.send(self.column_name)
|
105
|
-
view.link_to property, object if not property.nil?
|
106
|
-
end
|
107
|
-
def related_link(view, object)
|
108
|
-
property = object.send(self.column_name)
|
109
|
-
view.link_to self.name, property if not property.nil?
|
110
|
-
end
|
111
|
-
def related_link_list(view, object)
|
112
|
-
property = object.send(self.referring_column_name)
|
113
|
-
property.collect { |related_object| self_referential_link(view, related_object) }.join(', ') if not property.nil?
|
114
|
-
end
|
115
|
-
def time(view, object)
|
116
|
-
property = object.send(self.column_name)
|
117
|
-
property.strftime("%I:%M%p") if not property.nil?
|
118
|
-
end
|
119
|
-
def date(view, object)
|
120
|
-
property = object.send(self.column_name)
|
121
|
-
property.strftime("%m/%d/%Y") if not property.nil?
|
122
|
-
end
|
123
|
-
def datetime(view, object)
|
124
|
-
property = object.send(self.column_name)
|
125
|
-
property.strftime("%m/%d/%Y at %I:%M%p") if not property.nil?
|
126
|
-
end
|
127
|
-
|
75
|
+
def data
|
76
|
+
objects.map do |object|
|
77
|
+
self.class.columns.map{ |column| column.render(self.view, object) }
|
128
78
|
end
|
129
|
-
|
130
79
|
end
|
80
|
+
|
131
81
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Search
|
2
|
+
|
3
|
+
attr_accessor :name, :table, :column_name, :search_with
|
4
|
+
def initialize(name, table, *args)
|
5
|
+
self.name = name
|
6
|
+
self.table = table
|
7
|
+
|
8
|
+
attributes = args.pop || {}
|
9
|
+
self.column_name = attributes.fetch(:column_name, name)
|
10
|
+
self.search_with = attributes.fetch(:strategy, :default_strategy)
|
11
|
+
|
12
|
+
|
13
|
+
define_singleton_method :search do |objects, terms|
|
14
|
+
if self.search_with.kind_of? Symbol
|
15
|
+
self.send(self.search_with, self.column_name, objects, terms)
|
16
|
+
else
|
17
|
+
self.search_with.call(self.column_name, objects, terms)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_strategy(field, objects, terms)
|
23
|
+
self.starts_with_strategy(field, objects, terms)
|
24
|
+
end
|
25
|
+
def starts_with_strategy(field, objects, terms)
|
26
|
+
terms.split.map{|s| s+="%"}.map do |term|
|
27
|
+
Squeel::Nodes::Predicate.new(Squeel::Nodes::Stub.new(field), :matches, term)
|
28
|
+
end.inject do |t, expr|
|
29
|
+
t | expr
|
30
|
+
end.tap do |block|
|
31
|
+
return objects.where{block}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def contains_strategy(field, objects, terms)
|
35
|
+
terms.split.map{|s| s="%#{s}%"}.map do |term|
|
36
|
+
Squeel::Nodes::Predicate.new(Squeel::Nodes::Stub.new(field), :matches, term)
|
37
|
+
end.inject do |t, expr|
|
38
|
+
t | expr
|
39
|
+
end.tap do |block|
|
40
|
+
return objects.where{block}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
# def self_referential_link(view, object)
|
44
|
+
# property = object.send(self.column_name)
|
45
|
+
# view.link_to property, object if not property.nil?
|
46
|
+
# end
|
47
|
+
# def related_link(view, object)
|
48
|
+
# property = object.send(self.column_name)
|
49
|
+
# view.link_to self.name, property if not property.nil?
|
50
|
+
# end
|
51
|
+
# def related_link_list(view, object)
|
52
|
+
# property = object.send(self.referring_column_name)
|
53
|
+
# property.collect { |related_object| self_referential_link(view, related_object) }.join(', ') if not property.nil?
|
54
|
+
# end
|
55
|
+
# def time(view, object)
|
56
|
+
# property = object.send(self.column_name)
|
57
|
+
# property.strftime("%I:%M%p") if not property.nil?
|
58
|
+
# end
|
59
|
+
# def date(view, object)
|
60
|
+
# property = object.send(self.column_name)
|
61
|
+
# property.strftime("%m/%d/%Y") if not property.nil?
|
62
|
+
# end
|
63
|
+
# def datetime(view, object)
|
64
|
+
# property = object.send(self.column_name)
|
65
|
+
# property.strftime("%m/%d/%Y at %I:%M%p") if not property.nil?
|
66
|
+
# end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
def has_datatable(*args)
|
2
|
+
arguments = args.pop || {}
|
3
|
+
name = arguments.fetch(:name, 'datatable')
|
4
|
+
klass = arguments.fetch(:klass, "#{self.name.pluralize}Table")
|
5
|
+
require File.join(Rails.root, 'app', 'tables', "#{klass.underscore}.rb")
|
6
|
+
model = self
|
7
|
+
klass.constantize.class.send(:define_method, 'model') do
|
8
|
+
model
|
9
|
+
end
|
10
|
+
self.class.send(:define_method, name) do
|
11
|
+
klass.constantize
|
12
|
+
end
|
13
|
+
end
|
data/lib/rails-tables/version.rb
CHANGED
data/lib/rails-tables.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-tables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
-
description: A clean jQuery datatables
|
46
|
+
description: A clean jQuery datatables DSL that follows the structure of Ryan Bate's
|
47
47
|
jQuery datatables railscast.
|
48
48
|
email:
|
49
49
|
- dev@chriskeele.com
|
@@ -51,9 +51,12 @@ executables: []
|
|
51
51
|
extensions: []
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
|
+
- app/tables/column.rb
|
54
55
|
- app/tables/datatable.rb
|
56
|
+
- app/tables/search.rb
|
55
57
|
- config/routes.rb
|
56
58
|
- lib/rails-tables/engine.rb
|
59
|
+
- lib/rails-tables/model_additions.rb
|
57
60
|
- lib/rails-tables/version.rb
|
58
61
|
- lib/rails-tables.rb
|
59
62
|
- lib/tasks/rails-tables_tasks.rake
|
@@ -114,7 +117,7 @@ rubyforge_project:
|
|
114
117
|
rubygems_version: 1.8.23
|
115
118
|
signing_key:
|
116
119
|
specification_version: 3
|
117
|
-
summary: A clean jQuery datatables
|
120
|
+
summary: A clean jQuery datatables DSL.
|
118
121
|
test_files:
|
119
122
|
- test/dummy/app/assets/javascripts/application.js
|
120
123
|
- test/dummy/app/assets/stylesheets/application.css
|