rails-tables 0.0.1 → 0.1.0
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/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
|