tabulatr 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|