tabulatr 0.1.3 → 0.2.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/.gitignore +1 -0
- data/Changelog.textile +7 -0
- data/Gemfile +1 -0
- data/README.textile +11 -5
- data/lib/initializers/active_record.rb +1 -1
- data/lib/initializers/mongoid.rb +6 -5
- data/lib/tabulatr/tabulatr/data_cell.rb +10 -6
- data/lib/tabulatr/tabulatr/finder/{find_for_active_record_table.rb → find_for_table.rb} +44 -34
- data/lib/tabulatr/tabulatr/finder.rb +45 -11
- data/lib/tabulatr/tabulatr/paginator.rb +1 -1
- data/lib/tabulatr/tabulatr/settings.rb +1 -18
- data/lib/tabulatr/tabulatr.rb +9 -8
- data/lib/tabulatr/version.rb +1 -1
- data/spec/dummy_app/app/models/product.rb +22 -5
- data/spec/dummy_app/app/models/tag.rb +13 -3
- data/spec/dummy_app/app/models/vendor.rb +16 -4
- data/spec/dummy_app/app/views/products/index_simple.html.erb +1 -0
- data/spec/dummy_app/config/application.rb +3 -0
- data/spec/dummy_app/config/mongoid.yml +17 -0
- data/spec/requests/tabulatrs_spec.rb +29 -7
- data/tabulatr.gemspec +2 -2
- metadata +28 -8
- data/lib/tabulatr/tabulatr/finder/find_for_mongoid_table.rb +0 -116
data/.gitignore
CHANGED
data/Changelog.textile
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
h1. Changelog for tabulatr
|
2
2
|
|
3
|
+
h2. 0.2.0
|
4
|
+
|
5
|
+
* Mongoid can also be used in place of ActiveRecord
|
6
|
+
* fixed handling of the primary_key column and name
|
7
|
+
* Added dom_id to tables tr. Thanks to <a href="https://github.com/sterrym">sterrym (Tim Glen)</a>!
|
8
|
+
* Added note on "Request-URI Too Large error" to README
|
9
|
+
|
3
10
|
h2. 0.1.3
|
4
11
|
|
5
12
|
* nicer table headers. Thanks to <a href="https://github.com/troya2" target="_blank">troya2 (Troy Anderson)</a>!
|
data/Gemfile
CHANGED
data/README.textile
CHANGED
@@ -4,7 +4,7 @@ h1. Tabulatr - Index Tables made easy, finally
|
|
4
4
|
|
5
5
|
h2. Mission Objective
|
6
6
|
|
7
|
-
Tabulatr aims at making the ever-recurring task of creating listings of ActiveRecord models simple and uniform.
|
7
|
+
Tabulatr aims at making the ever-recurring task of creating listings of ActiveRecord or Mongoid models simple and uniform.
|
8
8
|
|
9
9
|
We found ourselves reinventing the wheel in every project we made, by using
|
10
10
|
|
@@ -313,16 +313,22 @@ To override these, you should, in an initializer, call
|
|
313
313
|
h2. Dependencies
|
314
314
|
|
315
315
|
We use
|
316
|
-
* <a href="http://github.com/provideal/whiny_hash">
|
317
|
-
* <a href="http://github.com/provideal/id_stuffer">
|
316
|
+
* <a href="http://github.com/provideal/whiny_hash">whiny_hash</a> to handle the options in a fail-early-manner,
|
317
|
+
* <a href="http://github.com/provideal/id_stuffer">id_stuffer</a> to compress the _remembered_ ids.
|
318
318
|
* And... eh... It's an extension for Rails 3, so it might be handy to have a version of Rails 3 and Ruby 1.8.? or 1.9.?.
|
319
319
|
|
320
320
|
h2. Bugs
|
321
321
|
|
322
|
-
|
322
|
+
h3. Request-URI Too Large error
|
323
|
+
|
324
|
+
Since everyhing about the state of the table is intentionally encoded in the URI, the URI may become somewhat bloated if fancy selecting is used. By using <a href="http://github.com/provideal/id_stuffer">id_stuffer</a>, we drastically reduced the size of the URI (that's the reason we actually made it), but it may still become rather large. This is a problem particulary when using WEBrick, because WEBricks URIs must not exceed 2048 characters. And this limit is hard-coded IIRC. So – If you run into this limitation – please consider using another server. (Thanks to <a href="https://github.com/stepheneb">stepheneb</a> for calling my attention back to this.)
|
325
|
+
|
326
|
+
h3. Other, new bugs
|
327
|
+
|
328
|
+
There are roughly another 997 bugs in Tabulatr, although we do some testing (see <tt>spec/</tt>). So if you hunt them, please let me know using the <a href="https://github.com/provideal/tabulatr/issues">GitHub Bugtracker</a>.
|
323
329
|
|
324
330
|
h2. Contributing to tabulatr
|
325
|
-
|
331
|
+
|
326
332
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
327
333
|
* Check out the <a href="https://github.com/provideal/tabulatr/issues">issue tracker</a> to make sure someone already hasn't requested it and/or contributed it
|
328
334
|
* Fork the project
|
@@ -26,7 +26,7 @@
|
|
26
26
|
if Object.const_defined? "ActiveRecord"
|
27
27
|
class ActiveRecord::Base
|
28
28
|
def self.find_for_table(params, opts={}, &block)
|
29
|
-
Tabulatr::Finder.
|
29
|
+
Tabulatr::Finder.find_for_table(self, params, opts, &block)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
data/lib/initializers/mongoid.rb
CHANGED
@@ -21,13 +21,14 @@
|
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
#++
|
23
23
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
# This is somewhat ugly, for it creates the Mongoid module, no matter
|
25
|
+
# whether it's about to be used. So you will find an empty Mongoid
|
26
|
+
# module in every Tabulatr project.
|
27
|
+
module Mongoid
|
28
|
+
module Document
|
28
29
|
module ClassMethods
|
29
30
|
def find_for_table(params, opts={}, &block)
|
30
|
-
Tabulatr.
|
31
|
+
Tabulatr::Finder.find_for_table(self, params, opts, &block)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
@@ -80,8 +80,12 @@ class Tabulatr
|
|
80
80
|
assoc = @record.class.reflect_on_association(relation)
|
81
81
|
make_tag(:td, opts[:td_html]) do
|
82
82
|
format = opts[:format]
|
83
|
-
|
84
|
-
|
83
|
+
ass = @record.send(relation.to_sym)
|
84
|
+
if opts[:sort_by]
|
85
|
+
# TODO: SORTING specified by opts[:sort_by]
|
86
|
+
end
|
87
|
+
concat(if (ass.is_a?(Array) or assoc.collection?) and opts[:map]
|
88
|
+
ass.map do |r|
|
85
89
|
val = h(r.send(opts[:method] || name))
|
86
90
|
if format.is_a?(Proc) then format.call(val)
|
87
91
|
elsif format.is_a?(String) then h(format % val)
|
@@ -90,8 +94,8 @@ class Tabulatr
|
|
90
94
|
end
|
91
95
|
end.join(opts[:join_symbol])
|
92
96
|
else
|
93
|
-
ass = @record.send(relation.to_sym)
|
94
97
|
return '' unless ass
|
98
|
+
#puts ass.to_s
|
95
99
|
val = h(ass.send(opts[:method] || name))
|
96
100
|
val = if format.is_a?(Proc) then format.call(val)
|
97
101
|
elsif format.is_a?(String) then h(format % val)
|
@@ -106,10 +110,10 @@ class Tabulatr
|
|
106
110
|
raise "Whatever that's for!" if block_given?
|
107
111
|
iname = "#{@classname}#{@table_form_options[:checked_postfix]}[current_page][]"
|
108
112
|
make_tag(:td, opts[:td_html]) do
|
109
|
-
checked = @checked[:selected].member?(@record.id
|
113
|
+
checked = @checked[:selected].member?(@record.send(@id)) ? :checked : nil
|
110
114
|
make_tag(:input, :type => 'checkbox', :name => iname,
|
111
|
-
:id => "#{@classname}#{@table_form_options[:checked_postfix]}_#{@record.id.to_s}",
|
112
|
-
:value => @record.id, :checked => checked)
|
115
|
+
:id => "#{@classname}#{@table_form_options[:checked_postfix]}_#{@record.send(@id).to_s}",
|
116
|
+
:value => @record.send(@id), :checked => checked)
|
113
117
|
end
|
114
118
|
end
|
115
119
|
|
@@ -28,9 +28,15 @@ module Tabulatr::Finder
|
|
28
28
|
# -------------------------------------------------------------------
|
29
29
|
# Called if SomeActveRecordSubclass::find_for_table(params) is called
|
30
30
|
#
|
31
|
-
def self.
|
31
|
+
def self.find_for_table(klaz, params, o={}, &block)
|
32
|
+
rel = klaz
|
33
|
+
typ = if klaz.respond_to?(:descends_from_active_record?) and klaz.descends_from_active_record? then :ar
|
34
|
+
elsif klaz.include?(Mongoid::Document) then :mongoid
|
35
|
+
else raise("Don't know how to deal with class '#{klaz}'")
|
36
|
+
end
|
37
|
+
|
32
38
|
# on the first run, get the correct like db-operator, can still be ovrrridden
|
33
|
-
unless Tabulatr::SQL_OPTIONS[:like]
|
39
|
+
unless typ != :ar || Tabulatr::SQL_OPTIONS[:like]
|
34
40
|
case ActiveRecord::Base.connection.class.to_s
|
35
41
|
when "ActiveRecord::ConnectionAdapters::MysqlAdapter" then Tabulatr.sql_options(:like => 'LIKE')
|
36
42
|
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter" then Tabulatr.sql_options(:like => 'ILIKE')
|
@@ -56,8 +62,11 @@ module Tabulatr::Finder
|
|
56
62
|
# before we do anything else, we find whether there's something to do for batch actions
|
57
63
|
checked_param = ActiveSupport::HashWithIndifferentAccess.new({:checked_ids => '', :current_page => []}).
|
58
64
|
merge(params[check_name] || {})
|
65
|
+
id = (typ==:ar ? klaz.primary_key.to_sym : :id)
|
66
|
+
id_type = (typ==:ar ? klaz.columns_hash[id.to_s].type : :string)
|
59
67
|
checked_ids = uncompress_id_list(checked_param[:checked_ids])
|
60
68
|
new_ids = checked_param[:current_page]
|
69
|
+
new_ids.map!(&:to_i) if id_type==:integer
|
61
70
|
selected_ids = checked_ids + new_ids
|
62
71
|
batch_param = params[batch_name]
|
63
72
|
if batch_param.present? and block_given?
|
@@ -66,10 +75,10 @@ module Tabulatr::Finder
|
|
66
75
|
end
|
67
76
|
|
68
77
|
# then, we obey any "select" buttons if pushed
|
69
|
-
|
78
|
+
precon = rel
|
79
|
+
precon = precon.where(opts[:precondition]) if opts[:precondition].present?
|
70
80
|
if checked_param[:select_all]
|
71
|
-
|
72
|
-
selected_ids = all.map { |r| r.id.to_s }
|
81
|
+
selected_ids = (typ==:ar ? precon.select(:id) : precon.only(:id) ).to_a.map { |r| r.send(id) }
|
73
82
|
elsif checked_param[:select_none]
|
74
83
|
selected_ids = []
|
75
84
|
elsif checked_param[:select_visible]
|
@@ -118,33 +127,34 @@ module Tabulatr::Finder
|
|
118
127
|
|
119
128
|
# firstly, get the conditions from the filters
|
120
129
|
includes = []
|
121
|
-
|
122
|
-
conditions = filter_param.
|
130
|
+
rel = rel.where(opts[:precondition]) if opts[:precondition]
|
131
|
+
conditions = filter_param.each do |t|
|
123
132
|
n, v = t
|
133
|
+
next unless v.present?
|
124
134
|
# FIXME n = name_escaping(n)
|
125
135
|
if (n != form_options[:associations_filter])
|
126
|
-
|
136
|
+
table_name = (typ==:ar ? klaz.table_name : klaz.to_s.tableize.gsub('/','_'))
|
137
|
+
rel = condition_from(rel, typ, "#{table_name}.#{n}", v)
|
127
138
|
else
|
128
|
-
v.
|
139
|
+
v.each do |t|
|
129
140
|
n,v = t
|
130
141
|
assoc, att = n.split(".").map(&:to_sym)
|
131
142
|
r = klaz.reflect_on_association(assoc)
|
132
143
|
includes << assoc
|
133
|
-
|
134
|
-
nn = "#{
|
135
|
-
condition_from(nn,v
|
144
|
+
table_name = (typ==:ar ? klaz.table_name : klaz.to_s.tableize)
|
145
|
+
nn = "#{table_name}.#{att}"
|
146
|
+
rel = condition_from(rel, typ, nn, v)
|
136
147
|
end
|
137
148
|
end
|
138
149
|
end
|
139
|
-
conditions = [conditions.first] + conditions.last
|
140
150
|
|
141
151
|
# more button handling
|
142
152
|
if checked_param[:select_filtered]
|
143
|
-
all =
|
144
|
-
selected_ids = (selected_ids + all.map { |r| r.id.to_s }).sort.uniq
|
153
|
+
all = rel.all
|
154
|
+
selected_ids = (selected_ids + all.map { |r| i=r.send(id); i.is_a?(Fixnum) ? i : i.to_s }).sort.uniq
|
145
155
|
elsif checked_param[:unselect_filtered]
|
146
|
-
all =
|
147
|
-
selected_ids = (selected_ids - all.map { |r| r.id.to_s }).sort.uniq
|
156
|
+
all = rel.dup.all
|
157
|
+
selected_ids = (selected_ids - all.map { |r| i=r.send(id); i.is_a?(Fixnum) ? i : i.to_s }).sort.uniq
|
148
158
|
end
|
149
159
|
|
150
160
|
# secondly, find the order_by stuff
|
@@ -158,7 +168,6 @@ module Tabulatr::Finder
|
|
158
168
|
end
|
159
169
|
raise "SECURITY violation, sort field name is '#{n}'" unless /^[\w]+$/.match order_direction
|
160
170
|
raise "SECURITY violation, sort field name is '#{n}'" unless /^[\d\w]+$/.match order_by
|
161
|
-
order = "#{order_by} #{order_direction}"
|
162
171
|
else
|
163
172
|
if opts[:default_order]
|
164
173
|
l = opts[:default_order].split(" ")
|
@@ -166,11 +175,11 @@ module Tabulatr::Finder
|
|
166
175
|
if l.length == 0 or l.length > 2
|
167
176
|
order_by = l[0]
|
168
177
|
order_direction = l[1] || 'asc'
|
169
|
-
order = "#{order_by} #{order_direction}"
|
170
178
|
else
|
171
179
|
order = order_by = order_direction = nil
|
172
180
|
end
|
173
181
|
end
|
182
|
+
order = (typ==:ar ? "#{order_by} #{order_direction}" : [order_by.to_s, order_direction.to_s]) if order_by
|
174
183
|
|
175
184
|
# thirdly, get the pagination data
|
176
185
|
paginate_options = Tabulatr.paginate_options.merge(opts).merge(pops)
|
@@ -178,40 +187,41 @@ module Tabulatr::Finder
|
|
178
187
|
page = paginate_options[:page].to_i
|
179
188
|
page += 1 if paginate_options[:page_right]
|
180
189
|
page -= 1 if paginate_options[:page_left]
|
181
|
-
c =
|
190
|
+
c = rel.count
|
182
191
|
pages = (c/pagesize).ceil
|
183
192
|
page = [1, [page, pages].min].max
|
184
|
-
|
193
|
+
total = klaz
|
194
|
+
total = total.where(opts[:precondition]) if opts[:precondition]
|
195
|
+
total = total.count
|
196
|
+
|
185
197
|
# Now, actually find the stuff
|
186
|
-
found =
|
187
|
-
|
188
|
-
:order => order, :include => includes
|
198
|
+
found = rel.limit(pagesize.to_i).offset(((page-1)*pagesize).to_i)
|
199
|
+
.order(order).to_a #, :include => includes
|
189
200
|
|
190
201
|
# finally, inject methods to retrieve the current 'settings'
|
191
|
-
|
192
|
-
found.define_singleton_method(
|
193
|
-
found.define_singleton_method(
|
194
|
-
found.define_singleton_method(fio[:pagination]) do
|
202
|
+
found.define_singleton_method(:__filters) do filter_param end
|
203
|
+
found.define_singleton_method(:__classinfo) do [cname, id, id_type] end
|
204
|
+
found.define_singleton_method(:__pagination) do
|
195
205
|
{ :page => page, :pagesize => pagesize, :count => c, :pages => pages,
|
196
206
|
:pagesizes => paginate_options[:pagesizes],
|
197
|
-
:total =>
|
207
|
+
:total => total }
|
198
208
|
end
|
199
|
-
found.define_singleton_method(
|
209
|
+
found.define_singleton_method(:__sorting) do
|
200
210
|
order ? { :by => order_by, :direction => order_direction } : nil
|
201
211
|
end
|
202
|
-
visible_ids = (found.map { |r| r.id
|
212
|
+
visible_ids = (found.map { |r| r.send(id) })
|
203
213
|
checked_ids = compress_id_list(selected_ids - visible_ids)
|
204
214
|
visible_ids = compress_id_list(visible_ids)
|
205
|
-
found.define_singleton_method(
|
215
|
+
found.define_singleton_method(:__checked) do
|
206
216
|
{ :selected => selected_ids,
|
207
217
|
:checked_ids => checked_ids,
|
208
218
|
:visible => visible_ids
|
209
219
|
}
|
210
220
|
end
|
211
|
-
found.define_singleton_method(
|
221
|
+
found.define_singleton_method(:__stateful) do
|
212
222
|
(opts[:stateful] ? true : false)
|
213
223
|
end
|
214
|
-
found.define_singleton_method(
|
224
|
+
found.define_singleton_method(:__store_data) do
|
215
225
|
opts[:store_data] || {}
|
216
226
|
end
|
217
227
|
|
@@ -24,18 +24,32 @@
|
|
24
24
|
# These are extensions for use from ActionController instances
|
25
25
|
module Tabulatr::Finder
|
26
26
|
|
27
|
-
require File.join(File.dirname(__FILE__), 'finder', '
|
28
|
-
require File.join(File.dirname(__FILE__), 'finder', 'find_for_mongoid_table')
|
27
|
+
require File.join(File.dirname(__FILE__), 'finder', 'find_for_table')
|
29
28
|
|
30
29
|
# compress the list of ids as good as I could imagine ;)
|
31
30
|
# uses fancy base twisting
|
32
31
|
def self.compress_id_list(list)
|
33
|
-
|
32
|
+
if list.length == 0
|
33
|
+
""
|
34
|
+
elsif list.first.is_a?(Fixnum)
|
35
|
+
IdStuffer.stuff(list)
|
36
|
+
else
|
37
|
+
"GzB" + Base64.encode64s(
|
38
|
+
Zlib::Deflate.deflate(
|
39
|
+
list.join(Tabulatr.table_form_options[:checked_separator])))
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
# inverse of compress_id_list
|
37
44
|
def self.uncompress_id_list(str)
|
38
|
-
|
45
|
+
if !str.present?
|
46
|
+
[]
|
47
|
+
elsif str.starts_with?("GzB")
|
48
|
+
Zlib::Inflate.inflate(Base64.decode64(str[3..-1]))
|
49
|
+
.split(Tabulatr.table_form_options[:checked_separator])
|
50
|
+
else
|
51
|
+
IdStuffer.unstuff(str)
|
52
|
+
end
|
39
53
|
end
|
40
54
|
|
41
55
|
class Invoker
|
@@ -57,26 +71,46 @@ private
|
|
57
71
|
klaz.to_s.downcase.gsub("/","_")
|
58
72
|
end
|
59
73
|
|
60
|
-
def self.condition_from(n,v
|
74
|
+
def self.condition_from(rel, typ, n, v)
|
61
75
|
raise "SECURITY violation, field name is '#{n}'" unless /^[\d\w]+(\.[\d\w]+)?$/.match n
|
62
76
|
@like ||= Tabulatr.sql_options[:like]
|
63
|
-
nc = c
|
64
77
|
if v.is_a?(String)
|
65
78
|
if v.present?
|
66
|
-
|
79
|
+
if typ == :ar
|
80
|
+
rel = rel.where(n => v)
|
81
|
+
elsif typ == :mongoid
|
82
|
+
nn = n.split('.').last
|
83
|
+
rel = rel.where(nn => v)
|
84
|
+
else raise "Unknown db type '#{typ}'"
|
85
|
+
end
|
67
86
|
end
|
68
87
|
elsif v.is_a?(Hash)
|
69
88
|
if v[:like]
|
70
89
|
if v[:like].present?
|
71
|
-
|
90
|
+
if typ==:ar
|
91
|
+
rel = rel.where("#{n} #{@like} ?", "%#{v[:like]}%")
|
92
|
+
elsif typ==:mongoid
|
93
|
+
nn = n.split('.').last
|
94
|
+
rel = rel.where(nn => Regexp.new(v[:like]))
|
95
|
+
else
|
96
|
+
raise "Unknown db type '#{typ}'"
|
97
|
+
end
|
72
98
|
end
|
73
99
|
else
|
74
|
-
|
75
|
-
|
100
|
+
if typ==:ar
|
101
|
+
rel = rel.where("#{n} >= ?", "#{v[:from]}") if v[:from].present?
|
102
|
+
rel = rel.where("#{n} <= ?", "#{v[:to]}") if v[:to].present?
|
103
|
+
elsif typ==:mongoid
|
104
|
+
nn = n.split('.').last.to_sym
|
105
|
+
rel = rel.where(nn.gte => v[:from]) if v[:from].present?
|
106
|
+
rel = rel.where(nn.lte => v[:to]) if v[:to].present?
|
107
|
+
else
|
108
|
+
raise "Unknown db type '#{typ}'"
|
109
|
+
end
|
76
110
|
end
|
77
111
|
else
|
78
112
|
raise "Wrong filter type: #{v.class}"
|
79
113
|
end
|
80
|
-
|
114
|
+
rel
|
81
115
|
end
|
82
116
|
end
|
@@ -27,7 +27,7 @@ class Tabulatr
|
|
27
27
|
def render_paginator
|
28
28
|
# get the current pagination state
|
29
29
|
pagination_name = "#{@classname}#{TABLE_FORM_OPTIONS[:pagination_postfix]}"
|
30
|
-
pparams = @records.
|
30
|
+
pparams = @records.__pagination
|
31
31
|
page = pparams[:page].to_i
|
32
32
|
pages = pparams[:pages].to_i
|
33
33
|
pagesize = pparams[:pagesize].to_i
|
@@ -153,22 +153,10 @@ class Tabulatr
|
|
153
153
|
:link => false, # proc or symbol to make the content a link
|
154
154
|
:join_symbol => ', ', # symbol used to join the elements of 'many' associations
|
155
155
|
:map => true, # whether to map the call on individual records (true) or call on the list (false)
|
156
|
+
:sort_by => false, # sort the elements of an association
|
156
157
|
:sortable => true # if set, sorting-stuff is added to the header cell
|
157
158
|
})
|
158
159
|
|
159
|
-
# these settings are considered constant for the whole application, can not be overridden
|
160
|
-
# on a per-table basis.
|
161
|
-
# That's necessary to allow find_for_table to work properly
|
162
|
-
FINDER_INJECT_OPTIONS = WhinyHash.new({
|
163
|
-
:pagination => :__pagination,
|
164
|
-
:filters => :__filters,
|
165
|
-
:classname => :__classname,
|
166
|
-
:sorting => :__sorting,
|
167
|
-
:checked => :__checked,
|
168
|
-
:store_data => :__store_data,
|
169
|
-
:stateful => :__stateful
|
170
|
-
})
|
171
|
-
|
172
160
|
# defaults for the find_for_table
|
173
161
|
FINDER_OPTIONS = WhinyHash.new({
|
174
162
|
:default_order => false,
|
@@ -183,11 +171,6 @@ class Tabulatr
|
|
183
171
|
:like => nil
|
184
172
|
})
|
185
173
|
|
186
|
-
def self.finder_inject_options(n=nil)
|
187
|
-
FINDER_INJECT_OPTIONS.merge!(n) if n
|
188
|
-
FINDER_INJECT_OPTIONS
|
189
|
-
end
|
190
|
-
|
191
174
|
def self.finder_options(n=nil)
|
192
175
|
FINDER_OPTIONS.merge!(n) if n
|
193
176
|
FINDER_OPTIONS
|
data/lib/tabulatr/tabulatr.rb
CHANGED
@@ -41,6 +41,7 @@ class Tabulatr
|
|
41
41
|
include ActionView::Helpers::FormTagHelper
|
42
42
|
include ActionView::Helpers::FormOptionsHelper
|
43
43
|
include ActionView::Helpers::TranslationHelper
|
44
|
+
include ActionView::Helpers::RecordTagHelper
|
44
45
|
|
45
46
|
# Constructor of Tabulatr
|
46
47
|
#
|
@@ -56,13 +57,13 @@ class Tabulatr
|
|
56
57
|
@val = []
|
57
58
|
@record = nil
|
58
59
|
@row_mode = false
|
59
|
-
@classname = @records.
|
60
|
-
@pagination = @records.
|
61
|
-
@filters = @records.
|
62
|
-
@sorting = @records.
|
63
|
-
@checked = @records.
|
64
|
-
@store_data = @records.
|
65
|
-
@stateful = @records.
|
60
|
+
@classname, @id, @id_type = @records.__classinfo
|
61
|
+
@pagination = @records.__pagination
|
62
|
+
@filters = @records.__filters
|
63
|
+
@sorting = @records.__sorting
|
64
|
+
@checked = @records.__checked
|
65
|
+
@store_data = @records.__store_data
|
66
|
+
@stateful = @records.__stateful
|
66
67
|
@should_translate = @table_options[:translate]
|
67
68
|
end
|
68
69
|
|
@@ -214,7 +215,7 @@ private
|
|
214
215
|
else
|
215
216
|
rc = nil
|
216
217
|
end
|
217
|
-
make_tag(:tr, row_html.merge(:class => rc)) do
|
218
|
+
make_tag(:tr, row_html.merge(:class => rc, :id => dom_id(record))) do
|
218
219
|
yield(data_row_builder(record))
|
219
220
|
end # </tr>
|
220
221
|
end
|
data/lib/tabulatr/version.rb
CHANGED
@@ -1,6 +1,23 @@
|
|
1
|
-
|
1
|
+
if USE_MONGOID
|
2
|
+
class Product
|
3
|
+
include Mongoid::Document
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
has_and_belongs_to_many :tags
|
6
|
+
belongs_to :vendor
|
7
|
+
|
8
|
+
field :name, :type => String
|
9
|
+
field :url, :type => String
|
10
|
+
field :active, :type => Boolean
|
11
|
+
field :description, :type => String
|
12
|
+
field :price, :type => Fixnum
|
13
|
+
field :created_at, :type => Time
|
14
|
+
field :updated_at, :type => Time
|
15
|
+
end
|
16
|
+
else
|
17
|
+
class Product < ActiveRecord::Base
|
18
|
+
|
19
|
+
has_and_belongs_to_many :tags
|
20
|
+
belongs_to :vendor
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -1,3 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
if USE_MONGOID
|
2
|
+
class Tag
|
3
|
+
include Mongoid::Document
|
4
|
+
has_and_belongs_to_many :products
|
5
|
+
field :title, :type => String
|
6
|
+
field :created_at, :type => Time
|
7
|
+
field :updated_at, :type => Time
|
8
|
+
end
|
9
|
+
else
|
10
|
+
class Tag < ActiveRecord::Base
|
11
|
+
has_and_belongs_to_many :products
|
12
|
+
end
|
13
|
+
end
|
@@ -1,5 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
if USE_MONGOID
|
2
|
+
class Vendor
|
3
|
+
include Mongoid::Document
|
4
|
+
|
5
|
+
has_many :products
|
6
|
+
field :name, :type => String
|
7
|
+
field :url, :type => String
|
8
|
+
field :active, :type => Boolean
|
9
|
+
field :description, :type => String
|
10
|
+
field :created_at, :type => Time
|
11
|
+
field :updated_at, :type => Time
|
12
|
+
end
|
13
|
+
else
|
14
|
+
class Vendor < ActiveRecord::Base
|
15
|
+
has_many :products
|
16
|
+
end
|
5
17
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
host: localhost
|
3
|
+
# slaves:
|
4
|
+
# - host: slave1.local
|
5
|
+
# port: 27018
|
6
|
+
# - host: slave2.local
|
7
|
+
# port: 27019
|
8
|
+
persist_in_safe_mode: true
|
9
|
+
|
10
|
+
development:
|
11
|
+
<<: *defaults
|
12
|
+
database: tabulatr_development
|
13
|
+
|
14
|
+
test:
|
15
|
+
<<: *defaults
|
16
|
+
database: tabulatr_test
|
17
|
+
|
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Tabulatrs" do
|
4
|
+
|
5
|
+
Mongoid.master.collections.select do |collection|
|
6
|
+
collection.name !~ /system/
|
7
|
+
end.each(&:drop)
|
4
8
|
|
5
9
|
names = ["lorem", "ipsum", "dolor", "sit", "amet", "consectetur",
|
6
10
|
"adipisicing", "elit", "sed", "eiusmod", "tempor", "incididunt", "labore",
|
@@ -16,7 +20,7 @@ describe "Tabulatrs" do
|
|
16
20
|
# General stuf
|
17
21
|
WORKS_IN_GENERAL = CONTAINS_BUTTONS = CONTAINS_COLUMN_HEADERS = CONTAINS_OTHER_CONTROLS = tralse
|
18
22
|
# This fills in the data, so rather not cmment this out
|
19
|
-
CONTAINS_ACTUAL_DATA = CONTAINS_ASSOC_DATA = CONTAINS_ACTUAL_DATA_MULTIPLE = CONTAINS_DATA_ON_FURTHER_PAGES =
|
23
|
+
CONTAINS_ACTUAL_DATA = CONTAINS_ASSOC_DATA = CONTAINS_ACTUAL_DATA_MULTIPLE = CONTAINS_DATA_ON_FURTHER_PAGES = tralse
|
20
24
|
# Paginatione
|
21
25
|
PAGES_UP_AND_DOWN = JUMPS_TO_CORRECT_PAGE = CHANGES_PAGE_SIZE = tralse
|
22
26
|
# Filters
|
@@ -24,7 +28,7 @@ describe "Tabulatrs" do
|
|
24
28
|
# Sorting
|
25
29
|
KNOWS_HOW_TO_SORT = tralse
|
26
30
|
# Statful
|
27
|
-
SORTS_STATEFULLY = FILTERS_STATEFULLY = SELECTS_STATEFULLY =
|
31
|
+
SORTS_STATEFULLY = FILTERS_STATEFULLY = SELECTS_STATEFULLY = tralse
|
28
32
|
# selecting and batch actions
|
29
33
|
SELECT_BUTTONS_WORK = KNOWS_HOW_TO_SELECT_AND_APPLY_BATCH_ACTIONS = tralse
|
30
34
|
|
@@ -33,6 +37,7 @@ describe "Tabulatrs" do
|
|
33
37
|
tag1 = Tag.create!(:title => 'foo')
|
34
38
|
tag2 = Tag.create!(:title => 'bar')
|
35
39
|
tag3 = Tag.create!(:title => 'fubar')
|
40
|
+
ids = []
|
36
41
|
|
37
42
|
describe "General data" do
|
38
43
|
it "works in general" do
|
@@ -52,7 +57,7 @@ describe "Tabulatrs" do
|
|
52
57
|
|
53
58
|
it "contains column headers" do
|
54
59
|
visit index_simple_products_path
|
55
|
-
['Id','Title','Price','Active','Created At','Vendor Name','Tags Title','Tags Count'].each do |n|
|
60
|
+
['Id','Title','Price','Active','Created At','Vendor Created At','Vendor Name','Tags Title','Tags Count'].each do |n|
|
56
61
|
page.should have_content(n)
|
57
62
|
end
|
58
63
|
end if CONTAINS_COLUMN_HEADERS
|
@@ -69,9 +74,11 @@ describe "Tabulatrs" do
|
|
69
74
|
page.should have_content("true")
|
70
75
|
page.should have_content("10.0")
|
71
76
|
page.should have_content("--0--")
|
77
|
+
#save_and_open_page
|
72
78
|
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 1, 1, 0, 1))
|
73
79
|
product.vendor = vendor1
|
74
80
|
product.save!
|
81
|
+
ids << product.id
|
75
82
|
visit index_simple_products_path
|
76
83
|
page.should have_content("ven d'or")
|
77
84
|
end if CONTAINS_ACTUAL_DATA
|
@@ -90,6 +97,7 @@ describe "Tabulatrs" do
|
|
90
97
|
9.times do |i|
|
91
98
|
product = Product.create!(:title => names[i+1], :active => i.even?, :price => 11.0+i,
|
92
99
|
:description => "blah blah #{i}", :vendor => i.even? ? vendor1 : vendor2)
|
100
|
+
ids << product.id
|
93
101
|
visit index_simple_products_path
|
94
102
|
page.should have_content(names[i])
|
95
103
|
page.should have_content((11.0+i).to_s)
|
@@ -97,10 +105,18 @@ describe "Tabulatrs" do
|
|
97
105
|
end
|
98
106
|
end if CONTAINS_ACTUAL_DATA_MULTIPLE
|
99
107
|
|
108
|
+
it "contains row identifiers" do
|
109
|
+
visit index_simple_products_path
|
110
|
+
Product.all.each do |product|
|
111
|
+
page.should have_css("#product_#{product.id}")
|
112
|
+
end
|
113
|
+
end if CONTAINS_ACTUAL_DATA
|
114
|
+
|
100
115
|
it "contains the further data on the further pages" do
|
101
116
|
names[10..-1].each_with_index do |n,i|
|
102
117
|
product = Product.create!(:title => n, :active => i.even?, :price => 20.0+i,
|
103
118
|
:description => "blah blah #{i}", :vendor => i.even? ? vendor1 : vendor2)
|
119
|
+
ids << product.id
|
104
120
|
visit index_simple_products_path
|
105
121
|
page.should_not have_content(n)
|
106
122
|
page.should_not have_content((30.0+i).to_s)
|
@@ -207,6 +223,7 @@ describe "Tabulatrs" do
|
|
207
223
|
click_button("Apply")
|
208
224
|
page.should have_content(str)
|
209
225
|
tot = (names.select do |s| s.match Regexp.new(str) end).length
|
226
|
+
#save_and_open_page
|
210
227
|
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], [10,tot].min, names.length, 0, tot))
|
211
228
|
end
|
212
229
|
end if FILTERS_WITH_LIKE
|
@@ -239,6 +256,7 @@ describe "Tabulatrs" do
|
|
239
256
|
describe "Sorting" do
|
240
257
|
it "knows how to sort" do
|
241
258
|
visit index_sort_products_path
|
259
|
+
# save_and_open_page
|
242
260
|
(1..10).each do |i|
|
243
261
|
page.should have_content names[-i]
|
244
262
|
end
|
@@ -273,21 +291,25 @@ describe "Tabulatrs" do
|
|
273
291
|
end if SORTS_STATEFULLY
|
274
292
|
|
275
293
|
it "filters statefully" do
|
294
|
+
Capybara.reset_sessions!
|
276
295
|
visit index_stateful_products_path
|
277
296
|
fill_in("product_filter[title]", :with => "lorem")
|
278
297
|
click_button("Apply")
|
279
298
|
visit index_stateful_products_path
|
299
|
+
#save_and_open_page
|
280
300
|
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 1, names.length, 0, 1))
|
281
301
|
click_button("Reset")
|
282
302
|
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 10, names.length, 0, names.length))
|
283
303
|
end if FILTERS_STATEFULLY
|
284
|
-
|
304
|
+
|
285
305
|
it "selects statefully" do
|
286
306
|
visit index_stateful_products_path
|
307
|
+
fill_in("product_filter[title]", :with => "")
|
308
|
+
click_button("Apply")
|
287
309
|
n = names.length
|
288
310
|
(n/10).times do |i|
|
289
311
|
(1..3).each do |j|
|
290
|
-
check("product_checked_#{10*i+j}")
|
312
|
+
check("product_checked_#{ids[10*i+j]}")
|
291
313
|
end
|
292
314
|
click_button("Apply")
|
293
315
|
tot = 3*(i+1)
|
@@ -342,13 +364,13 @@ describe "Tabulatrs" do
|
|
342
364
|
click_button("Apply")
|
343
365
|
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 10, n, n-tot, n))
|
344
366
|
end if SELECT_BUTTONS_WORK
|
345
|
-
|
367
|
+
|
346
368
|
it "knows how to select and apply batch actions" do
|
347
369
|
visit index_select_products_path
|
348
370
|
n = names.length
|
349
371
|
(n/10).times do |i|
|
350
372
|
(1..3).each do |j|
|
351
|
-
check("product_checked_#{10*i+j}")
|
373
|
+
check("product_checked_#{ids[10*i+j]}")
|
352
374
|
end
|
353
375
|
click_button("Apply")
|
354
376
|
tot = 3*(i+1)
|
data/tabulatr.gemspec
CHANGED
@@ -6,10 +6,10 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "tabulatr"
|
7
7
|
s.version = Tabulatr::VERSION.dup
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.summary = "A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions."
|
9
|
+
s.summary = "A tight DSL to build tables of ActiveRecord or Mongoid models with sorting, pagination, finding/filtering, selecting and batch actions."
|
10
10
|
s.email = "info@provideal.net"
|
11
11
|
s.homepage = "http://github.com/provideal/tabulatr"
|
12
|
-
s.description = "A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions. " +
|
12
|
+
s.description = "A tight DSL to build tables of ActiveRecord or Mongoid models with sorting, pagination, finding/filtering, selecting and batch actions. " +
|
13
13
|
"Tries to do for tables what formtastic and simple_form did for forms."
|
14
14
|
s.authors = ['Peter Horn', 'René Sprotte']
|
15
15
|
|
metadata
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabulatr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
12
|
- Peter Horn
|
@@ -11,7 +15,7 @@ autorequire:
|
|
11
15
|
bindir: bin
|
12
16
|
cert_chain: []
|
13
17
|
|
14
|
-
date: 2011-
|
18
|
+
date: 2011-05-26 00:00:00 +02:00
|
15
19
|
default_executable:
|
16
20
|
dependencies:
|
17
21
|
- !ruby/object:Gem::Dependency
|
@@ -22,6 +26,9 @@ dependencies:
|
|
22
26
|
requirements:
|
23
27
|
- - ~>
|
24
28
|
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
- 0
|
25
32
|
version: "3.0"
|
26
33
|
type: :runtime
|
27
34
|
version_requirements: *id001
|
@@ -33,6 +40,10 @@ dependencies:
|
|
33
40
|
requirements:
|
34
41
|
- - ">="
|
35
42
|
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
- 2
|
36
47
|
version: 0.0.2
|
37
48
|
type: :runtime
|
38
49
|
version_requirements: *id002
|
@@ -44,10 +55,14 @@ dependencies:
|
|
44
55
|
requirements:
|
45
56
|
- - ">="
|
46
57
|
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
- 0
|
61
|
+
- 1
|
47
62
|
version: 0.0.1
|
48
63
|
type: :runtime
|
49
64
|
version_requirements: *id003
|
50
|
-
description: A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions. Tries to do for tables what formtastic and simple_form did for forms.
|
65
|
+
description: A tight DSL to build tables of ActiveRecord or Mongoid models with sorting, pagination, finding/filtering, selecting and batch actions. Tries to do for tables what formtastic and simple_form did for forms.
|
51
66
|
email: info@provideal.net
|
52
67
|
executables: []
|
53
68
|
|
@@ -88,8 +103,7 @@ files:
|
|
88
103
|
- lib/tabulatr/tabulatr/data_cell.rb
|
89
104
|
- lib/tabulatr/tabulatr/filter_cell.rb
|
90
105
|
- lib/tabulatr/tabulatr/finder.rb
|
91
|
-
- lib/tabulatr/tabulatr/finder/
|
92
|
-
- lib/tabulatr/tabulatr/finder/find_for_mongoid_table.rb
|
106
|
+
- lib/tabulatr/tabulatr/finder/find_for_table.rb
|
93
107
|
- lib/tabulatr/tabulatr/formattr.rb
|
94
108
|
- lib/tabulatr/tabulatr/header_cell.rb
|
95
109
|
- lib/tabulatr/tabulatr/paginator.rb
|
@@ -136,6 +150,7 @@ files:
|
|
136
150
|
- spec/dummy_app/config/initializers/session_store.rb
|
137
151
|
- spec/dummy_app/config/initializers/tabulatr_settings.rb
|
138
152
|
- spec/dummy_app/config/locales/en.yml
|
153
|
+
- spec/dummy_app/config/mongoid.yml
|
139
154
|
- spec/dummy_app/config/routes.rb
|
140
155
|
- spec/dummy_app/db/migrate/20110112151112_create_vendors.rb
|
141
156
|
- spec/dummy_app/db/migrate/20110112151200_create_products.rb
|
@@ -184,20 +199,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
199
|
requirements:
|
185
200
|
- - ">="
|
186
201
|
- !ruby/object:Gem::Version
|
202
|
+
segments:
|
203
|
+
- 0
|
187
204
|
version: "0"
|
188
205
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
206
|
none: false
|
190
207
|
requirements:
|
191
208
|
- - ">="
|
192
209
|
- !ruby/object:Gem::Version
|
210
|
+
segments:
|
211
|
+
- 0
|
193
212
|
version: "0"
|
194
213
|
requirements: []
|
195
214
|
|
196
215
|
rubyforge_project: tabulatr
|
197
|
-
rubygems_version: 1.
|
216
|
+
rubygems_version: 1.3.7
|
198
217
|
signing_key:
|
199
218
|
specification_version: 3
|
200
|
-
summary: A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions.
|
219
|
+
summary: A tight DSL to build tables of ActiveRecord or Mongoid models with sorting, pagination, finding/filtering, selecting and batch actions.
|
201
220
|
test_files:
|
202
221
|
- spec/dummy_app/.gitignore
|
203
222
|
- spec/dummy_app/app/controllers/application_controller.rb
|
@@ -239,6 +258,7 @@ test_files:
|
|
239
258
|
- spec/dummy_app/config/initializers/session_store.rb
|
240
259
|
- spec/dummy_app/config/initializers/tabulatr_settings.rb
|
241
260
|
- spec/dummy_app/config/locales/en.yml
|
261
|
+
- spec/dummy_app/config/mongoid.yml
|
242
262
|
- spec/dummy_app/config/routes.rb
|
243
263
|
- spec/dummy_app/db/migrate/20110112151112_create_vendors.rb
|
244
264
|
- spec/dummy_app/db/migrate/20110112151200_create_products.rb
|
@@ -1,116 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2010-2011 Peter Horn, Provideal GmbH
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
-
# a copy of this software and associated documentation files (the
|
6
|
-
# "Software"), to deal in the Software without restriction, including
|
7
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
-
# the following conditions:
|
11
|
-
#
|
12
|
-
# The above copyright notice and this permission notice shall be
|
13
|
-
# included in all copies or substantial portions of the Software.
|
14
|
-
#
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
#++
|
23
|
-
|
24
|
-
# These are extensions for use from ActionController instances
|
25
|
-
# In a seperate class call only for clearity
|
26
|
-
module Tabulatr::Finder
|
27
|
-
|
28
|
-
# ----------------------------------------------------------------
|
29
|
-
# Called if SomeMongoidDocument::find_for_table(params) is called
|
30
|
-
#
|
31
|
-
def self.find_for_mongoid_table(klaz, params, opts={})
|
32
|
-
# firstly, get the conditions from the filters
|
33
|
-
cname = class_to_param(klaz)
|
34
|
-
filter_param = (params["#{cname}#{TABLE_FORM_OPTIONS[:filter_postfix]}"] || {})
|
35
|
-
conditions = filter_param.inject({}) do |c, t|
|
36
|
-
n, v = t
|
37
|
-
nc = c
|
38
|
-
# FIXME n = name_escaping(n)
|
39
|
-
raise "SECURITY violation, field name is '#{n}'" unless /^[\d\w]+$/.match n
|
40
|
-
if v.class == String
|
41
|
-
if v.present?
|
42
|
-
nc[n.to_sym] = v
|
43
|
-
end
|
44
|
-
elsif v.is_a?(Hash)
|
45
|
-
if v[:like]
|
46
|
-
if v[:like].present?
|
47
|
-
nc[n.to_sym] = Regexp.new("#{v[:like]}")
|
48
|
-
end
|
49
|
-
else
|
50
|
-
nc[n.to_sym.gte] = "#{v[:from]}" if v[:from].present?
|
51
|
-
nc[n.to_sym.lte] = "#{v[:to]}" if v[:to].present?
|
52
|
-
end
|
53
|
-
else
|
54
|
-
raise "Wrong filter type: #{v.class}"
|
55
|
-
end
|
56
|
-
nc
|
57
|
-
end
|
58
|
-
|
59
|
-
# secondly, find the order_by stuff
|
60
|
-
# FIXME: Implement me! PLEEEZE!
|
61
|
-
sortparam = params["#{cname}#{TABLE_FORM_OPTIONS[:sort_postfix]}"]
|
62
|
-
if sortparam
|
63
|
-
if sortparam[:_resort]
|
64
|
-
order_by = sortparam[:_resort].first.first
|
65
|
-
order_direction = sortparam[:_resort].first.last.first.first
|
66
|
-
else
|
67
|
-
order_by = sortparam.first.first
|
68
|
-
order_direction = sortparam.first.last.first.first
|
69
|
-
end
|
70
|
-
raise "SECURITY violation, sort field name is '#{n}'" unless /^[\w]+$/.match order_direction
|
71
|
-
raise "SECURITY violation, sort field name is '#{n}'" unless /^[\d\w]+$/.match order_by
|
72
|
-
order = [order_by, order_direction]
|
73
|
-
else
|
74
|
-
order = nil
|
75
|
-
end
|
76
|
-
|
77
|
-
# thirdly, get the pagination data
|
78
|
-
paginate_options = PAGINATE_OPTIONS.merge(opts).
|
79
|
-
merge(params["#{cname}#{TABLE_FORM_OPTIONS[:pagination_postfix]}"] || {})
|
80
|
-
page = paginate_options[:page].to_i
|
81
|
-
page += 1 if paginate_options[:page_right]
|
82
|
-
page -= 1 if paginate_options[:page_left]
|
83
|
-
pagesize = paginate_options[:pagesize].to_f
|
84
|
-
c = klaz.count :conditions => conditions
|
85
|
-
pages = (c/pagesize).ceil
|
86
|
-
page = [1, [page, pages].min].max
|
87
|
-
|
88
|
-
# Now, actually find the stuff
|
89
|
-
found = klaz.find(:conditions => conditions)
|
90
|
-
found = found.order_by([order]) if order
|
91
|
-
found = found.paginate(:page => page, :per_page => pagesize)
|
92
|
-
|
93
|
-
# finally, inject methods to retrieve the current 'settings'
|
94
|
-
found.define_singleton_method(fio[:filters]) do filter_param end
|
95
|
-
found.define_singleton_method(fio[:classname]) do cname end
|
96
|
-
found.define_singleton_method(fio[:pagination]) do
|
97
|
-
{:page => page, :pagesize => pagesize, :count => c, :pages => pages,
|
98
|
-
:pagesizes => paginate_options[:pagesizes]}
|
99
|
-
end
|
100
|
-
found.define_singleton_method(fio[:sorting]) do
|
101
|
-
order ? { :by => order_by, :direction => order_direction } : nil
|
102
|
-
end
|
103
|
-
checked_param = params["#{cname}#{TABLE_FORM_OPTIONS[:checked_postfix]}"]
|
104
|
-
checked_ids = checked_param[:checked].split(TABLE_FORM_OPTIONS[:checked_separator])
|
105
|
-
new_ids = checked_param[:current_page] || []
|
106
|
-
selected_ids = checked_ids + new_ids
|
107
|
-
ids = found.map { |r| r.id.to_s }
|
108
|
-
checked_ids = selected_ids - ids
|
109
|
-
found.define_singleton_method(fio[:checked]) do
|
110
|
-
{ :selected => selected_ids,
|
111
|
-
:checked_ids => checked_ids.join(TABLE_FORM_OPTIONS[:checked_separator]) }
|
112
|
-
end
|
113
|
-
found
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|