usefull_table 1.0.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/CHANGELOG.md +12 -0
- data/Gemfile +27 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +234 -0
- data/Rakefile +31 -0
- data/app/controllers/usefull_table/table_controller.rb +34 -0
- data/app/helpers/usefull_table_helper.rb +323 -0
- data/app/views/usefull_table/table/create.xlsx.maker +17 -0
- data/config/routes.rb +8 -0
- data/lib/generators/usefull_table/install/install_generator.rb +47 -0
- data/lib/generators/usefull_table/install/templates/config/locales/usefull_table.it.yml +42 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_destroy.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_download.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_edit.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_false.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_show.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/images/usefull_table_true.png +0 -0
- data/lib/generators/usefull_table/install/templates/public/stylesheets/usefull_table.css +101 -0
- data/lib/generators/usefull_table/scaffold/scaffold_generator.rb +12 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/index.html.erb +15 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/show.html.erb +12 -0
- data/lib/generators/usefull_table/scaffold/templates/lib/templates/rails/scaffold_controller/controller.rb +84 -0
- data/lib/usefull_table/engine.rb +17 -0
- data/lib/usefull_table/exceptions.rb +17 -0
- data/lib/usefull_table/table_builder.rb +522 -0
- data/lib/usefull_table/version.rb +3 -0
- data/lib/usefull_table.rb +13 -0
- metadata +123 -0
@@ -0,0 +1,522 @@
|
|
1
|
+
require "active_resource/formats"
|
2
|
+
|
3
|
+
module UsefullTable
|
4
|
+
#Builder as the name suggest builds rows and columns
|
5
|
+
#
|
6
|
+
#
|
7
|
+
#==@data
|
8
|
+
#@data array contains columns data in the form:
|
9
|
+
#[ {column1}, {column2} ...]
|
10
|
+
#where {column} is an hash with the following options:
|
11
|
+
#* {
|
12
|
+
#* :nome => column name (ActiveRecord) int the form :column or "collection.column"
|
13
|
+
#* :type => :column | :link
|
14
|
+
#* :label => "wath you want" | column name if not specified
|
15
|
+
#* :header_type => :sort | :plain | :human | :nil
|
16
|
+
#* :body_type => :value (column value) | :plain (wathever you write as column name)
|
17
|
+
class TableBuilder
|
18
|
+
DATE = [:date, :datetime]
|
19
|
+
LINK = [:show, :edit, :destroy, :download, :link]
|
20
|
+
|
21
|
+
attr_reader :options
|
22
|
+
|
23
|
+
#Initialize Builder with the following parameters:
|
24
|
+
# @data = [ {column}, .. ] see #col description
|
25
|
+
# @object => ActiveRecod instance (paginated)
|
26
|
+
# @search => MetaSearch instance
|
27
|
+
# @template => View Contest
|
28
|
+
# @options => options
|
29
|
+
# :params => Tabel.builder.new.to_param[:params]
|
30
|
+
#def initialize(object, search, options, template, data = nil, &block)
|
31
|
+
def initialize(object, search, opt, template, *args, &block)
|
32
|
+
options = args.extract_options!
|
33
|
+
|
34
|
+
raise MissingBlock if block.nil? && options[:params].blank?
|
35
|
+
|
36
|
+
@object = object
|
37
|
+
@search = search
|
38
|
+
@template = template
|
39
|
+
|
40
|
+
if options[:params]
|
41
|
+
#debugger
|
42
|
+
@data = _decode_hash(options[:params][:data]).map{|e| e.with_indifferent_access } if options[:params][:data].present?
|
43
|
+
opt = _decode_hash(options[:params][:options]).with_indifferent_access
|
44
|
+
else
|
45
|
+
@data ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
_manage_options(opt)
|
49
|
+
|
50
|
+
@excel = []
|
51
|
+
yield(self) if block
|
52
|
+
|
53
|
+
#Rendering order is importanto so body and header are pre-rendered by initilizer and returned at will.
|
54
|
+
@rendered_header = _render_header
|
55
|
+
@rendered_body = _render_body
|
56
|
+
end
|
57
|
+
|
58
|
+
#Render table as Array,
|
59
|
+
#Columns Name in the first row
|
60
|
+
#Bodies follows
|
61
|
+
#Note: be sure to call after render_header and render_body
|
62
|
+
def to_a
|
63
|
+
@excel
|
64
|
+
end
|
65
|
+
|
66
|
+
#~ #Return path if temporary file where excel il saved
|
67
|
+
#~ #Note: the file vanisch with the instance, so if you have more than one table per page, only the last one persist
|
68
|
+
#~ #Note2: then excel is created on object so exports only the page (is affected by will_paginate)
|
69
|
+
#~ def excel_path
|
70
|
+
#~ to_a.to_xls(:file => true).path
|
71
|
+
#~ end
|
72
|
+
|
73
|
+
#Header is pre_rendered because we need the renderengi order is followed
|
74
|
+
def render_header
|
75
|
+
@rendered_header
|
76
|
+
end
|
77
|
+
|
78
|
+
#Body is pre_rendered because we need the renderengi order is followed
|
79
|
+
def render_body
|
80
|
+
@rendered_body
|
81
|
+
end
|
82
|
+
|
83
|
+
#~ def render_excel
|
84
|
+
#~ @rendered_excel
|
85
|
+
#~ end
|
86
|
+
|
87
|
+
#=col
|
88
|
+
#Render column value
|
89
|
+
#
|
90
|
+
#==Usage #col
|
91
|
+
# <% t.col :name %> #render column :name ( t.col "name" is ok)
|
92
|
+
# <% t.col "user.name" %> #render column name of the user collection in item (item.user.name)
|
93
|
+
#
|
94
|
+
#==Options
|
95
|
+
# :header_type =>
|
96
|
+
# *:sort* #Header is MetaSearch#sort_link of columns_name
|
97
|
+
# :human #Header is plain text humanized with ActiveRecord column name
|
98
|
+
# :nil #No header
|
99
|
+
#
|
100
|
+
# :label =>
|
101
|
+
# "Custom Name" #plain text without localization in header
|
102
|
+
# :custom_name #localized text in lazy context (.) in header
|
103
|
+
#
|
104
|
+
# :data_type => #default get class name from object to render
|
105
|
+
# :Date | :Time | :DateTime | :Currency
|
106
|
+
#
|
107
|
+
# :url => "static_path" or Proc #Proc expose the object instance of the current row
|
108
|
+
#
|
109
|
+
# :inline => true (default false) enable inline edit
|
110
|
+
#
|
111
|
+
def col(attribute, *args)
|
112
|
+
options = args.extract_options!
|
113
|
+
options[:method_name] = :col
|
114
|
+
options[:name] = attribute
|
115
|
+
options[:type] = :column
|
116
|
+
options[:header_type] ||= options[:label].nil? ? :sort : :plain
|
117
|
+
options[:body_type] ||= options[:url].blank? ? :value : :link
|
118
|
+
options[:label] ||= attribute
|
119
|
+
@data << options
|
120
|
+
end
|
121
|
+
|
122
|
+
#=bool
|
123
|
+
#
|
124
|
+
# <% t.bool :name %> #render column :name ( t.bool "name" is ok) as a green/red point
|
125
|
+
# <% t.bool "user.name" %> #render column name of the user collection in item (item.user.name) as a green/red point
|
126
|
+
#
|
127
|
+
#==Options
|
128
|
+
# :header_type =>
|
129
|
+
# *:sort* #Header is MetaSearch#sort_link of columns_name
|
130
|
+
# :human #Header is plain text humanized with ActiveRecord column name
|
131
|
+
# :nil #No header
|
132
|
+
#
|
133
|
+
# :label =>
|
134
|
+
# "Custom Name" #plain text without localization in header
|
135
|
+
# :custom_name #localized text in lazy context (.) in header
|
136
|
+
#
|
137
|
+
# :url => "static_path" or Proc #Proc expose the object instance of the current row
|
138
|
+
#
|
139
|
+
# :reverse => true #transofrm true => false
|
140
|
+
#
|
141
|
+
def bool(attribute, *args)
|
142
|
+
options = args.extract_options!
|
143
|
+
options[:method_name] = :bool
|
144
|
+
options[:name] = attribute
|
145
|
+
options[:type] = :bool
|
146
|
+
options[:header_type] ||= options[:label].nil? ? :sort : :plain
|
147
|
+
options[:body_type] ||= options[:url].blank? ? :value : :link
|
148
|
+
options[:data_type] = options[:reverse] == true ? :Bool_reverse : :Bool
|
149
|
+
options[:label] ||= attribute
|
150
|
+
@data << options
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
#=label
|
155
|
+
#Render static label
|
156
|
+
#
|
157
|
+
#==Usage
|
158
|
+
# <% t.label object %> #render object.inspect
|
159
|
+
# <% t.label Proc.new {|item| item.name.capitalize} %> #Evaluate proc with item instance of the corresponding row
|
160
|
+
def label(body, *args)
|
161
|
+
options = args.extract_options!
|
162
|
+
options[:method_name] = :label
|
163
|
+
options[:name] = :label
|
164
|
+
options[:type] = :column
|
165
|
+
options[:header_type] ||= options[:label].nil? ? :nil : :plain
|
166
|
+
options[:body_type] = :plain
|
167
|
+
options[:body] = body
|
168
|
+
@data << options
|
169
|
+
end
|
170
|
+
|
171
|
+
#Deprecated
|
172
|
+
def status(*args)
|
173
|
+
Rails::logger.info("TableBuilder#status is deprecated, please use monitor.")
|
174
|
+
monitor(*args)
|
175
|
+
end
|
176
|
+
|
177
|
+
#=monitor
|
178
|
+
#Render a tri-state icon to monitor model status
|
179
|
+
#* Red : Error
|
180
|
+
#* Yellow: Warning
|
181
|
+
#* Green: Status ok
|
182
|
+
#
|
183
|
+
#==Usage
|
184
|
+
# <% t.monitor %>
|
185
|
+
#
|
186
|
+
#Clicking the icon you get the comlete problem description pushed by Ajaxs script (no page reload)
|
187
|
+
def monitor(*args)
|
188
|
+
options = args.extract_options!
|
189
|
+
options[:method_name] = :monitor
|
190
|
+
options[:name] = :status_flag
|
191
|
+
options[:type] = :column
|
192
|
+
options[:header_type] = :nil
|
193
|
+
options[:body_type] = :flag
|
194
|
+
options[:label] ||= I18n.t(:status_flag, :scope => "activerecord.attributes")
|
195
|
+
@data << options if @options[:monitor][:visible] == true
|
196
|
+
end
|
197
|
+
|
198
|
+
#=link
|
199
|
+
#Create a link to something, using Icons or CustomText
|
200
|
+
#==Usage
|
201
|
+
# <% t.show :url => Proc.new {|object| home_path(object) }"%>
|
202
|
+
# <% t.destroy :url => Proc.new {|object| home_path(object) }"%>
|
203
|
+
# <% t.link :name => "Custom Link", :url => Proc.new {|object| my_link_home_path(object) }"%> #text link (Custom Link) to url
|
204
|
+
# <% t.link :name => "Custom Link", :body_typ => :icon, :url => Proc.new {|object| my_link_home_path(object) }"%> #icon link with icon name = usefull_table_cusom_link.png or localization in usefull_table.icons.custom_link
|
205
|
+
#
|
206
|
+
#==Options
|
207
|
+
# :url => Proc or string
|
208
|
+
# :label => :show_doc localized in lazy contest (.)
|
209
|
+
# "Show Doc" printed without localization
|
210
|
+
# :link_options => *nil* | {:method => delete, :confirm => "sicuro?"} if name == :destroy
|
211
|
+
# :name => :symbol or "string" #if method_name == :link the name is used as link_text (localized if symbol), ignored elsewhere
|
212
|
+
LINK.each do |method_name|
|
213
|
+
define_method method_name do |*args|
|
214
|
+
options = args.extract_options!
|
215
|
+
options[:method_name] = :link
|
216
|
+
options[:type] = :link
|
217
|
+
options[:header_type] ||= :nil
|
218
|
+
options[:header_type] = :plain unless options[:label].nil?
|
219
|
+
options[:body_type] ||= method_name == :link ? :link : :icon
|
220
|
+
options[:label] ||= method_name
|
221
|
+
options[:name] = method_name unless method_name == :link && !options[:name].nil?
|
222
|
+
options[:link_options] ||= {:method => :delete, :confirm => I18n.t(:confirm, :scope => "usefull_table", :default => "Are you sure?")} if options[:name] == :destroy
|
223
|
+
raise CustomErrors::TableBuilders::UrlMissing unless options[:url]
|
224
|
+
@data << options
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def to_param
|
229
|
+
@params = {}
|
230
|
+
@params[:data] = _encode_hash(_sanitize_data(@data))
|
231
|
+
@params[:options] = _encode_hash(@options)
|
232
|
+
|
233
|
+
@params
|
234
|
+
end
|
235
|
+
|
236
|
+
|
237
|
+
private
|
238
|
+
|
239
|
+
#remove columns with link and procs
|
240
|
+
#* Links are not rendered so sending them is a waste
|
241
|
+
#* Proc cannot be serialized so are not sendable.
|
242
|
+
def _sanitize_data(d)
|
243
|
+
data = d.dup
|
244
|
+
#Rails::logger.info("TableBuilder#_sanitize_data data=#{data.inspect}")
|
245
|
+
num = 1
|
246
|
+
data.delete_if { |element| element[:method_name] == :link || element[:body].kind_of?(Proc)}
|
247
|
+
data.each do |element|
|
248
|
+
element[:url] = "/" if element[:url].present?
|
249
|
+
end if data.present?
|
250
|
+
#Rails::logger.info("TableBuilder#_sanitize_data(fine) data=#{data.inspect}")
|
251
|
+
data
|
252
|
+
end
|
253
|
+
|
254
|
+
def _encode_hash(a)
|
255
|
+
a.to_xml
|
256
|
+
end
|
257
|
+
|
258
|
+
def _decode_hash(a)
|
259
|
+
ActiveResource::Formats::XmlFormat.decode(a)
|
260
|
+
end
|
261
|
+
|
262
|
+
#set default values for options
|
263
|
+
def _manage_options(options)
|
264
|
+
@options = HashWithIndifferentAccess.new(options)
|
265
|
+
#Paginator
|
266
|
+
@options[:paginator] ||= {}
|
267
|
+
@options[:paginator][:visible] = true if @options[:paginator][:visible].nil?
|
268
|
+
@options[:paginator][:visible] = false if !@object.respond_to? :total_pages
|
269
|
+
@options[:paginator][:class] = "usefull_table_paginator"
|
270
|
+
|
271
|
+
#Container
|
272
|
+
@options[:html] ||= {:class => "usefull_table_container"}
|
273
|
+
|
274
|
+
#Excel
|
275
|
+
@options[:export] ||= {}
|
276
|
+
@options[:export][:visible] = true if @options[:export][:visible].nil?
|
277
|
+
@options[:export][:visible] = false unless defined?(ActsAsXls)
|
278
|
+
@options[:export][:filter] ||= false if @search.nil?
|
279
|
+
@options[:export][:human] = true if @options[:export][:human].nil?
|
280
|
+
@options[:export][:worksheet] ||= @object.first.class.name.gsub(/::/,"#")
|
281
|
+
#remove search options if custom url is passed
|
282
|
+
@options[:export][:search] = @options[:export][:url] ? false : true
|
283
|
+
@options[:export][:url] ||= @template.url_for(:action => "create", :controller => "usefull_table/table") + ".xlsx"
|
284
|
+
@options[:export][:class] = "usefull_table_export"
|
285
|
+
|
286
|
+
#Table
|
287
|
+
@options[:table] ||= {}
|
288
|
+
@options[:table][:div_html] ||= {:class => "usefull_table"}
|
289
|
+
@options[:table][:header_html] ||= {:class => "first_row"}
|
290
|
+
#Ususally column_type is :sort, but is search is not present I cannot render a sort_link...
|
291
|
+
@options[:table][:header_type] = :human if @search.nil?
|
292
|
+
|
293
|
+
#Monitor
|
294
|
+
@options[:monitor] ||= {}
|
295
|
+
@options[:monitor][:visible] = @object.first.respond_to?(:status_flag) ? true : false
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
#Render table Header
|
300
|
+
def _render_header
|
301
|
+
out = []
|
302
|
+
@template.content_tag(:tr, @options[:table][:header_html]) do
|
303
|
+
@data.each do |element|
|
304
|
+
element[:header_type] = :human if @options[:table][:header_type] == :human && element[:header_type] == :sort
|
305
|
+
head = header(element)
|
306
|
+
out << head[:plain]
|
307
|
+
@template.concat @template.content_tag(:th, head[:html])
|
308
|
+
#out_html = @template.content_tag(:th, head[:html])
|
309
|
+
end
|
310
|
+
@excel << out.compact
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
#Render table row
|
315
|
+
def _render_body
|
316
|
+
out_html = ""
|
317
|
+
@object.each do |obj|
|
318
|
+
row = []
|
319
|
+
out_html <<@template.content_tag(:tr, :class => @template.cycle("even","odd")) do
|
320
|
+
@data.each do |element|
|
321
|
+
b = body(obj,element)
|
322
|
+
row << b[:plain]
|
323
|
+
@template.concat @template.content_tag(:td, b[:html])
|
324
|
+
end
|
325
|
+
end
|
326
|
+
@excel << row.compact
|
327
|
+
end
|
328
|
+
out_html.html_safe
|
329
|
+
end
|
330
|
+
|
331
|
+
#Render column Header
|
332
|
+
def header(attribute)
|
333
|
+
out = ""
|
334
|
+
out_html = ""
|
335
|
+
case attribute[:header_type]
|
336
|
+
when :sort then
|
337
|
+
value = nestize(attribute)
|
338
|
+
out_html = @template.sort_link(@search, value)
|
339
|
+
out = value
|
340
|
+
when :plain then
|
341
|
+
out_html = out = attribute[:label] = localize(attribute[:label])
|
342
|
+
when :human then
|
343
|
+
#UserSession.log("TableHelper#h: object.first.class.human_attribute_name(#{attribute[:label]})")
|
344
|
+
out_html = out = @object.first.class.human_attribute_name(attribute[:label].to_s.gsub(/\./,"_"))
|
345
|
+
when :nil then
|
346
|
+
out_html = out = ""
|
347
|
+
else
|
348
|
+
out_html = out = I18n.t(:Header_error, :scope => :usefull_table, :default => "Header Error")
|
349
|
+
end
|
350
|
+
out = nil if attribute[:type] == :link
|
351
|
+
out = I18n.t(:title, :scope => "usefull_table.monitor", :default => "Status") if attribute[:method_name] == :monitor
|
352
|
+
{:html => out_html.html_safe, :plain => out}
|
353
|
+
end
|
354
|
+
|
355
|
+
#Render column body
|
356
|
+
#return :plain and :html value
|
357
|
+
def body(obj, attribute)
|
358
|
+
#Rails::logger.info("TableBuilder#body")
|
359
|
+
out = ""
|
360
|
+
out_html = ""
|
361
|
+
case attribute[:type]
|
362
|
+
when :link then
|
363
|
+
out_html = attribute_link(obj, attribute)
|
364
|
+
out = nil
|
365
|
+
when :bool
|
366
|
+
out = typeize(obj, attribute)
|
367
|
+
out_html = attribute_bool(out)
|
368
|
+
out = out ? 1 : 0
|
369
|
+
when :column then
|
370
|
+
out = a = typeize(obj, attribute) unless attribute[:body_type] == :plain
|
371
|
+
#Rails::logger.info("TableBuilder#body a=#{a.inspect}, attribute=#{attribute.inspect}")
|
372
|
+
case attribute[:body_type]
|
373
|
+
when :value
|
374
|
+
out_html = a
|
375
|
+
out_html = attribute_inline(obj,attribute,a) if attribute[:inline] == true
|
376
|
+
when :link
|
377
|
+
#url = attribute[:url].kind_of?(Proc) ? attribute[:url].call(obj) : attribute[:url]
|
378
|
+
out_html = a.blank? ? a : @template.link_to(a, attribute[:url].kind_of?(Proc) ? attribute[:url].call(obj) : attribute[:url] )
|
379
|
+
#out_html = @template.link_to(a, url)
|
380
|
+
when :flag
|
381
|
+
out_html = @template.monitor_tag obj
|
382
|
+
out = I18n.t(a , :scope => "usefull_table.monitor", :default => a)
|
383
|
+
when :plain
|
384
|
+
#Rails::logger.info("TableBuilder#body#plain obj=#{obj.inspect}")
|
385
|
+
if attribute[:body].kind_of?(Proc)
|
386
|
+
out_html = out = attribute[:body].call(obj)
|
387
|
+
else
|
388
|
+
out_html = out = attribute[:body].kind_of?(String) ? attribute[:body] : attribute[:body].inspect
|
389
|
+
end
|
390
|
+
end
|
391
|
+
else
|
392
|
+
out_html = out = I18n.t(:body_error, :scope => :usefull_table, :default => "Body Error")
|
393
|
+
end
|
394
|
+
{:html => out_html.to_s.html_safe, :plain => out}
|
395
|
+
end
|
396
|
+
|
397
|
+
|
398
|
+
#Localize if Symbol, print if String
|
399
|
+
def localize(value)
|
400
|
+
value.kind_of?(String) ? value : @template.t(".#{value.to_s}")
|
401
|
+
end
|
402
|
+
|
403
|
+
#Check if the attribute_name is a reference to a collection (user.name)
|
404
|
+
def nested?(attribute) #:doc:
|
405
|
+
attribute[:name].to_s.match(/\./) ? true : false
|
406
|
+
end
|
407
|
+
|
408
|
+
#Convert labels from user.name to user_name to be used by meta_search for sorting columns
|
409
|
+
def nestize(attribute) #:doc:
|
410
|
+
nested?(attribute) ? attribute[:name].to_s.gsub(/\./,"_") : attribute[:name]
|
411
|
+
end
|
412
|
+
|
413
|
+
#format value using data_type
|
414
|
+
def typeize(obj, attribute) #:doc:
|
415
|
+
#Rails::logger.info("TableBuilder#typeize")
|
416
|
+
type = attribute[:data_type] || attribute_type(obj, attribute[:name])
|
417
|
+
true_values = [1, true, "vero", "true", "yes", "si", "s"]
|
418
|
+
case type
|
419
|
+
when :Date then
|
420
|
+
@template.l(attribute_value(obj,attribute[:name]), :format => :usefull_table_date)
|
421
|
+
when :Time then
|
422
|
+
@template.l(attribute_value(obj,attribute[:name]), :format => :usefull_table_time )
|
423
|
+
when :DateTime then
|
424
|
+
@template.l(attribute_value(obj,attribute[:name]), :format => :usefull_table_datetime)
|
425
|
+
when :Currency then
|
426
|
+
@template.number_to_currency(attribute_value(obj,attribute[:name]))
|
427
|
+
when :Bool then
|
428
|
+
true_values.include?(attribute_value(obj,attribute[:name])) ? true : false
|
429
|
+
when :Bool_reverse then
|
430
|
+
true_values.include?(attribute_value(obj,attribute[:name])) ? false : true
|
431
|
+
else
|
432
|
+
attribute_value(obj,attribute[:name])
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
#Return attribute value if defined blank otherwise
|
437
|
+
def attribute_value(obj, attribute_name)
|
438
|
+
#Rails::logger.info("TableBuilder#attribute_value obj=#{obj.inspect}, attribute=#{attribute_name.inspect}")
|
439
|
+
if safe?(obj, attribute_name)
|
440
|
+
obj.instance_eval("self." + attribute_name.to_s) if safe?(obj, attribute_name)
|
441
|
+
else
|
442
|
+
""
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
#Render in_place_editor
|
447
|
+
#
|
448
|
+
#get Class and method name and send them to helper for rendering.
|
449
|
+
#
|
450
|
+
#ToDo: Add check to multi level columns
|
451
|
+
def attribute_inline(obj, attribute, value)
|
452
|
+
Rails::logger.info("TableBuilder#attribute_inline obj=#{obj.inspect}, attribute=#{attribute.inspect}, value=#{value.inspect}")
|
453
|
+
if safe?(obj, attribute[:name])
|
454
|
+
attributes = attribute[:name].to_s.split(".")
|
455
|
+
base = obj.class
|
456
|
+
method = attributes.pop
|
457
|
+
Rails::logger.info("TableBuilder#attribute_inline(1) attributes=#{attributes.inspect}")
|
458
|
+
id = obj.id
|
459
|
+
Rails::logger.info("TableBuilder#attribute_inline(2) method=#{method}, base=#{base.name}, attributes=#{attributes.inspect}")
|
460
|
+
unless attributes.blank?
|
461
|
+
id_relation = eval("obj.#{attributes.join(".")}.id")
|
462
|
+
attributes.each do |association|
|
463
|
+
reflection = base.reflect_on_association(association.to_sym)
|
464
|
+
base = reflection.blank? ? nil : reflection.klass
|
465
|
+
end
|
466
|
+
end
|
467
|
+
@template.inline_field(base, id, method, value, id_relation)
|
468
|
+
else
|
469
|
+
value
|
470
|
+
end
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
#Render a red/green label
|
475
|
+
def attribute_bool(value)
|
476
|
+
name = value ? :ok : :ko
|
477
|
+
@template.content_tag(:span, @template.image_tag(I18n.t(name, :scope => "usefull_table.icons", :defualt => "usefull_table_#{name.to_s}.png")), :align => :center )
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
#Return link to url with Icon
|
482
|
+
#==Attributes
|
483
|
+
# :url => Proc.new { |object| ...} #eval with row_instance as contest
|
484
|
+
# "static_url"
|
485
|
+
# :name => :show | :edit | :destroy | :download used to loaclize icons_name
|
486
|
+
# /config/locales/usefull_table.it.yml
|
487
|
+
# it:
|
488
|
+
# usefull_table:
|
489
|
+
# icons:
|
490
|
+
# nane:
|
491
|
+
def attribute_link(obj, attribute)
|
492
|
+
#Rails::logger.info("TableBuilder#attribute_link obj=#{obj.inspect}, attribute=#{attribute.inspect}")
|
493
|
+
url = attribute[:url].kind_of?(Proc) ? attribute[:url].call(obj) : attribute[:url]
|
494
|
+
attribute_name = attribute[:name]
|
495
|
+
icon_name = attribute[:body_type] == :icon ? @template.image_tag(I18n.t(attribute_name.to_s.underscore, :scope => "usefull_table.icons", :defualt => "usefull_table_#{attribute_name.to_s.underscore}.png") ): localize(attribute_name)
|
496
|
+
@template.link_to(icon_name, url, attribute[:link_options])
|
497
|
+
end
|
498
|
+
|
499
|
+
#Return attribute Type
|
500
|
+
#works evenif the attribute is nested : document.activity.data_prevista => :Date
|
501
|
+
#Time object in Rails is a DateTime object, so it is renamed
|
502
|
+
def attribute_type(obj, attribute_name)
|
503
|
+
#Added self. because of uppercase fileds like Art are misinterprede as Constants...
|
504
|
+
out = obj.instance_eval("self." + attribute_name.to_s + ".class.name.to_sym") if safe?(obj, attribute_name)
|
505
|
+
#Rails::logger.info("TableBuilder#attribute_type attribute=#{attribute_name.inspect}, out=#{out.inspect}")
|
506
|
+
out == :Time ? :DateTime : out
|
507
|
+
end
|
508
|
+
|
509
|
+
#Check if attribute_name return something...
|
510
|
+
# Documentbody.first.safe?("document.activity.customer.nome") => true
|
511
|
+
def safe?(obj, attribute_name)
|
512
|
+
#Rails::logger.info("TableHelper#safe? attribute_name=#{attribute_name.inspect}, obj=#{obj.inspect}")
|
513
|
+
raise RuntimeError if obj.instance_eval("self." + attribute_name.to_s).nil?
|
514
|
+
true
|
515
|
+
rescue NoMethodError, RuntimeError
|
516
|
+
false
|
517
|
+
end
|
518
|
+
|
519
|
+
end
|
520
|
+
|
521
|
+
|
522
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: usefull_table
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Andrea Bignozzi
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-07-02 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - "="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 21
|
28
|
+
segments:
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
- 9
|
32
|
+
version: 3.0.9
|
33
|
+
type: :runtime
|
34
|
+
name: rails
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
name: acts_as_xls
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: *id002
|
51
|
+
description: Table Helper with Excel export, inline editing and monitoring funxtions
|
52
|
+
email:
|
53
|
+
- skylord73@gmail.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- app/views/usefull_table/table/create.xlsx.maker
|
62
|
+
- app/helpers/usefull_table_helper.rb
|
63
|
+
- app/controllers/usefull_table/table_controller.rb
|
64
|
+
- lib/usefull_table.rb
|
65
|
+
- lib/generators/usefull_table/install/install_generator.rb
|
66
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_show.png
|
67
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_destroy.png
|
68
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_edit.png
|
69
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_true.png
|
70
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_false.png
|
71
|
+
- lib/generators/usefull_table/install/templates/public/images/usefull_table_download.png
|
72
|
+
- lib/generators/usefull_table/install/templates/public/stylesheets/usefull_table.css
|
73
|
+
- lib/generators/usefull_table/install/templates/config/locales/usefull_table.it.yml
|
74
|
+
- lib/generators/usefull_table/scaffold/templates/lib/templates/rails/scaffold_controller/controller.rb
|
75
|
+
- lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/show.html.erb
|
76
|
+
- lib/generators/usefull_table/scaffold/templates/lib/templates/erb/scaffold/index.html.erb
|
77
|
+
- lib/generators/usefull_table/scaffold/scaffold_generator.rb
|
78
|
+
- lib/usefull_table/engine.rb
|
79
|
+
- lib/usefull_table/table_builder.rb
|
80
|
+
- lib/usefull_table/exceptions.rb
|
81
|
+
- lib/usefull_table/version.rb
|
82
|
+
- config/routes.rb
|
83
|
+
- MIT-LICENSE
|
84
|
+
- Rakefile
|
85
|
+
- Gemfile
|
86
|
+
- README.rdoc
|
87
|
+
- CHANGELOG.md
|
88
|
+
has_rdoc: true
|
89
|
+
homepage:
|
90
|
+
licenses: []
|
91
|
+
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.3.7
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Table Helper with Excel export, inline editing and monitoring funxtions
|
122
|
+
test_files: []
|
123
|
+
|