active-list 4.2.4 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/VERSION +1 -1
  3. data/{lib → app}/assets/images/active-list.png +0 -0
  4. data/app/assets/images/active-list.svg +415 -0
  5. data/{lib/assets/javascripts/active-list.jquery.js → app/assets/javascripts/active_list.jquery.js} +2 -2
  6. data/app/assets/stylesheets/active_list.css.scss +7 -0
  7. data/{lib/active-list/compass/stylesheets/active-list/_background.scss → app/assets/stylesheets/active_list/background.scss} +10 -8
  8. data/{lib/active-list/compass/stylesheets/active-list/_minimal.scss → app/assets/stylesheets/active_list/minimal.scss} +16 -16
  9. data/{lib/active-list/compass/stylesheets/active-list/_theme.scss → app/assets/stylesheets/active_list/theme.scss} +37 -37
  10. data/lib/active-list.rb +1 -37
  11. data/lib/active_list.rb +43 -0
  12. data/lib/active_list/action_pack.rb +46 -0
  13. data/lib/active_list/definition.rb +17 -0
  14. data/lib/active_list/definition/abstract_column.rb +54 -0
  15. data/lib/active_list/definition/action_column.rb +76 -0
  16. data/lib/active_list/definition/association_column.rb +80 -0
  17. data/lib/active_list/definition/attribute_column.rb +58 -0
  18. data/lib/active_list/definition/check_box_column.rb +17 -0
  19. data/lib/active_list/definition/data_column.rb +88 -0
  20. data/lib/active_list/definition/empty_column.rb +10 -0
  21. data/lib/active_list/definition/field_column.rb +20 -0
  22. data/lib/active_list/definition/status_column.rb +10 -0
  23. data/lib/active_list/definition/table.rb +159 -0
  24. data/lib/active_list/definition/text_field_column.rb +10 -0
  25. data/lib/active_list/exporters.rb +28 -0
  26. data/lib/active_list/exporters/abstract_exporter.rb +55 -0
  27. data/lib/active_list/exporters/csv_exporter.rb +32 -0
  28. data/lib/active_list/exporters/excel_csv_exporter.rb +38 -0
  29. data/lib/active_list/exporters/open_document_spreadsheet_exporter.rb +82 -0
  30. data/lib/active_list/generator.rb +122 -0
  31. data/lib/active_list/generator/finder.rb +150 -0
  32. data/lib/active_list/helpers.rb +33 -0
  33. data/lib/{active-list → active_list}/rails/engine.rb +3 -2
  34. data/lib/active_list/renderers.rb +25 -0
  35. data/lib/active_list/renderers/abstract_renderer.rb +29 -0
  36. data/lib/active_list/renderers/simple_renderer.rb +356 -0
  37. metadata +74 -55
  38. data/lib/active-list/action_pack.rb +0 -48
  39. data/lib/active-list/columns/action_column.rb +0 -83
  40. data/lib/active-list/columns/data_column.rb +0 -151
  41. data/lib/active-list/columns/field_column.rb +0 -29
  42. data/lib/active-list/compass/stylesheets/_active-list.scss +0 -7
  43. data/lib/active-list/definition.rb +0 -103
  44. data/lib/active-list/exporters.rb +0 -71
  45. data/lib/active-list/exporters/csv_exporter.rb +0 -30
  46. data/lib/active-list/exporters/excel_csv_exporter.rb +0 -36
  47. data/lib/active-list/exporters/open_document_spreadsheet_exporter.rb +0 -81
  48. data/lib/active-list/finder.rb +0 -134
  49. data/lib/active-list/generator.rb +0 -88
  50. data/lib/active-list/renderers.rb +0 -28
  51. data/lib/active-list/renderers/simple_renderer.rb +0 -335
  52. data/lib/assets/stylesheets/active-list.css.scss +0 -7
@@ -0,0 +1,10 @@
1
+ module ActiveList
2
+
3
+ module Definition
4
+
5
+ class TextFieldColumn < FieldColumn
6
+ end
7
+
8
+ end
9
+
10
+ end
@@ -0,0 +1,28 @@
1
+ # require 'active_support/core_ext/module/attribute_accessors'
2
+ module ActiveList
3
+
4
+ module Exporters
5
+
6
+ def self.hash
7
+ ActiveList.exporters
8
+ end
9
+
10
+ autoload :AbstractExporter, 'active_list/exporters/abstract_exporter'
11
+ autoload :OpenDocumentSpreadsheetExporter, 'active_list/exporters/open_document_spreadsheet_exporter'
12
+ autoload :CsvExporter, 'active_list/exporters/csv_exporter'
13
+ autoload :ExcelCsvExporter, 'active_list/exporters/excel_csv_exporter'
14
+ end
15
+
16
+ mattr_reader :exporters
17
+ @@exporters = {}
18
+
19
+ def self.register_exporter(name, exporter)
20
+ raise ArgumentError.new("ActiveList::Exporters::AbstractExporter expected (got #{exporter.name}/#{exporter.ancestors.inspect})") unless exporter < ActiveList::Exporters::AbstractExporter
21
+ @@exporters[name] = exporter
22
+ end
23
+
24
+ end
25
+
26
+ ActiveList.register_exporter(:ods, ActiveList::Exporters::OpenDocumentSpreadsheetExporter)
27
+ ActiveList.register_exporter(:csv, ActiveList::Exporters::CsvExporter)
28
+ ActiveList.register_exporter(:xcsv, ActiveList::Exporters::ExcelCsvExporter)
@@ -0,0 +1,55 @@
1
+ module ActiveList
2
+
3
+ module Exporters
4
+
5
+ class AbstractExporter
6
+
7
+ attr_reader :table, :generator
8
+
9
+ def initialize(generator)
10
+ @generator = generator
11
+ @table = generator.table
12
+ end
13
+
14
+ def file_extension
15
+ "txt"
16
+ end
17
+
18
+ def mime_type
19
+ Mime::TEXT
20
+ end
21
+
22
+ def send_data_code
23
+ raise NotImplementedError, "#{self.class.name}#format_data_code is not implemented."
24
+ end
25
+
26
+ def columns_headers(options={})
27
+ headers, columns = [], table.exportable_columns
28
+ for column in columns
29
+ datum = column.header_code
30
+ headers << (options[:encoding] ? datum+".to_s.encode('#{options[:encoding]}')" : datum)
31
+ end
32
+ return headers
33
+ end
34
+
35
+ def columns_to_array(nature, options={})
36
+ columns = table.exportable_columns
37
+
38
+ array = []
39
+ record = options[:record] || 'record_of_the_death'
40
+ for column in columns
41
+ if column.is_a?(ActiveList::Definition::AbstractColumn)
42
+ if nature == :header
43
+ datum = column.header_code
44
+ else
45
+ datum = column.exporting_datum_code(record)
46
+ end
47
+ array << (options[:encoding] ? datum+".to_s.encode('#{options[:encoding]}')" : datum)
48
+ end
49
+ end
50
+ return array
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,32 @@
1
+ module ActiveList
2
+
3
+ module Exporters
4
+
5
+ class CsvExporter < AbstractExporter
6
+
7
+ def file_extension
8
+ "csv"
9
+ end
10
+
11
+ def mime_type
12
+ Mime::CSV
13
+ end
14
+
15
+ def send_data_code
16
+ record = "r"
17
+ code = generator.select_data_code(paginate: false)
18
+ code << "data = ActiveList::CSV.generate do |csv|\n"
19
+ code << " csv << [#{columns_to_array(:header).join(', ')}]\n"
20
+ code << " for #{record} in #{generator.records_variable_name}\n"
21
+ code << " csv << [#{columns_to_array(:body, record: record).join(', ')}]\n"
22
+ code << " end\n"
23
+ code << "end\n"
24
+ code << "send_data(data, type: #{self.mime_type.to_s.inspect}, disposition: 'inline', filename: #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i,'_') + '.#{self.file_extension}')\n"
25
+ return code.c
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+
3
+ # Register XCSV format unless is already set
4
+ Mime::Type.register("text/csv", :xcsv) unless defined? Mime::XCSV
5
+
6
+ module ActiveList
7
+
8
+ module Exporters
9
+
10
+ class ExcelCsvExporter < CsvExporter
11
+
12
+ def file_extension
13
+ "csv"
14
+ end
15
+
16
+ def mime_type
17
+ Mime::XCSV
18
+ end
19
+
20
+ def send_data_code
21
+ record = "r"
22
+ code = generator.select_data_code(paginate: false)
23
+ encoding = "CP1252"
24
+ code << "data = ActiveList::CSV.generate(:col_sep => ';') do |csv|\n"
25
+ code << " csv << [#{columns_to_array(:header, encoding: encoding).join(', ')}]\n"
26
+ code << " for #{record} in #{generator.records_variable_name}\n"
27
+ code << " csv << [#{columns_to_array(:body, record: record, encoding: encoding).join(', ')}]\n"
28
+ code << " end\n"
29
+ code << "end\n"
30
+ code << "send_data(data, type: #{self.mime_type.to_s.inspect}, disposition: 'inline', filename: #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i,'_')+'.#{self.file_extension}')\n"
31
+ return code.c
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+ require 'zip'
3
+
4
+ # Register ODS format unless is already set
5
+ Mime::Type.register("application/vnd.oasis.opendocument.spreadsheet", :ods) unless defined? Mime::ODS
6
+
7
+ module ActiveList
8
+
9
+ module Exporters
10
+
11
+ class OpenDocumentSpreadsheetExporter < AbstractExporter
12
+
13
+ DATE_ELEMENTS = {
14
+ "m" => "<number:month number:style=\"long\"/>",
15
+ "d" => "<number:day number:style=\"long\"/>",
16
+ "Y" => "<number:year/>"
17
+ }
18
+
19
+ def file_extension
20
+ "ods"
21
+ end
22
+
23
+ def mime_type
24
+ Mime::ODS
25
+ end
26
+
27
+ def send_data_code
28
+ xml_escape = "to_s.gsub('&', '&amp;').gsub('\\'', '&apos;').gsub('<', '&lt;').gsub('>', '&gt;')"
29
+ xml_escape << ".force_encoding('US-ASCII')" if xml_escape.respond_to?(:force_encoding)
30
+ record = "r"
31
+ code = generator.select_data_code(paginate: false)
32
+ code << "name = #{table.model.name}.model_name.human.gsub(/[^a-z0-9]/i, '_')\n"
33
+ code << "file = ::Rails.root.join('tmp', 'export', 'active_list', name + rand.to_s+'.#{self.file_extension}')\n"
34
+ code << "FileUtils.mkdir_p(file.dirname)\n"
35
+ code << "Zip::OutputStream.open(file) do |zile|\n"
36
+ # MimeType in first place
37
+ code << " zile.put_next_entry('mimetype', nil, nil, Zip::Entry::STORED)\n"
38
+ code << " zile << '#{self.mime_type}'\n"
39
+
40
+ # Manifest
41
+ code << " zile.put_next_entry('META-INF/manifest.xml')\n"
42
+ code << " zile << ('<?xml version=\"1.0\" encoding=\"UTF-8\"?><manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\"><manifest:file-entry manifest:media-type=\"#{self.mime_type}\" manifest:full-path=\"/\"/><manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"content.xml\"/></manifest:manifest>')\n"
43
+ code << " zile.put_next_entry('content.xml')\n"
44
+
45
+ code << " zile << ('<?xml version=\"1.0\" encoding=\"UTF-8\"?><office:document-content xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\" xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\" xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\" xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\" xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\" xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\" xmlns:presentation=\"urn:oasis:names:tc:opendocument:xmlns:presentation:1.0\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\" xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\" xmlns:math=\"http://www.w3.org/1998/Math/MathML\" xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\" xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\" xmlns:ooo=\"http://openoffice.org/2004/office\" xmlns:ooow=\"http://openoffice.org/2004/writer\" xmlns:oooc=\"http://openoffice.org/2004/calc\" xmlns:dom=\"http://www.w3.org/2001/xml-events\" xmlns:xforms=\"http://www.w3.org/2002/xforms\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:field=\"urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:field:1.0\" office:version=\"1.1\"><office:scripts/>')\n"
46
+ # Styles
47
+ code << " zile << ('<office:automatic-styles>"+
48
+ "<style:style style:name=\"co1\" style:family=\"table-column\"><style:table-column-properties fo:break-before=\"auto\" style:use-optimal-column-width=\"true\"/></style:style>"+
49
+ "<style:style style:name=\"header\" style:family=\"table-cell\"><style:text-properties fo:font-weight=\"bold\" style:font-weight-asian=\"bold\" style:font-weight-complex=\"bold\"/></style:style>"+
50
+ "<number:date-style style:name=\"K4D\" number:automatic-order=\"true\"><number:text>"+::I18n.translate("date.formats.default").gsub(/\%./){|x| "</number:text>"+DATE_ELEMENTS[x[1..1]]+"<number:text>"} +"</number:text></number:date-style><style:style style:name=\"ce1\" style:family=\"table-cell\" style:data-style-name=\"K4D\"/>"+
51
+ "</office:automatic-styles>')\n"
52
+
53
+ # Tables
54
+ code << " zile << ('<office:body><office:spreadsheet><table:table table:name=\"'+#{table.model.name}.model_name.human.#{xml_escape}+'\">')\n"
55
+ code << " zile << ('<table:table-column table:number-columns-repeated=\"#{table.exportable_columns.size}\"/>')\n"
56
+ code << " zile << ('<table:table-header-rows><table:table-row>"+columns_headers.collect{|h| "<table:table-cell table:style-name=\"header\" office:value-type=\"string\"><text:p>'+(#{h}).#{xml_escape}+'</text:p></table:table-cell>"}.join+"</table:table-row></table:table-header-rows>')\n"
57
+ code << " for #{record} in #{generator.records_variable_name}\n"
58
+ code << " zile << ('<table:table-row>"+table.exportable_columns.collect do |column|
59
+ "<table:table-cell"+(if column.numeric? or column.datatype==:decimal
60
+ " office:value-type=\"float\" office:value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
61
+ elsif column.datatype==:boolean
62
+ " office:value-type=\"boolean\" office:boolean-value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
63
+ elsif column.datatype==:date
64
+ " office:value-type=\"date\" table:style-name=\"ce1\" office:date-value=\"'+(#{column.datum_code(record)}).#{xml_escape}+'\""
65
+ else
66
+ " office:value-type=\"string\""
67
+ end)+"><text:p>'+("+column.exporting_datum_code(record, true)+").#{xml_escape}+'</text:p></table:table-cell>"
68
+ end.join+"</table:table-row>')\n"
69
+ code << " end\n"
70
+ code << " zile << ('</table:table></office:spreadsheet></office:body></office:document-content>')\n"
71
+ code << "end\n"
72
+ code << "send_file(file, stream: false, type: #{self.mime_type.to_s.inspect}, disposition: 'inline', filename: name+'.#{self.file_extension}')\n"
73
+ code << "File.delete(file)\n" # Removes tmp files before they explode the disk
74
+ # raise code
75
+ return code
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: UTF-8
2
+ module ActiveList
3
+
4
+ class Generator
5
+
6
+ attr_accessor :table, :controller, :controller_method_name, :view_method_name, :records_variable_name
7
+
8
+ def initialize(*args, &block)
9
+ options = args.extract_options!
10
+ @controller = options[:controller]
11
+ name = args.shift || @controller.controller_name.to_sym
12
+ model = (options[:model]||name).to_s.classify.constantize
13
+ @collection = !!(model.name == @controller.controller_name.to_s.classify)
14
+ @controller_method_name = "list#{'_'+name.to_s if name != @controller.controller_name.to_sym}"
15
+ @view_method_name = "_#{@controller.controller_name}_list_#{name}_tag"
16
+ @records_variable_name = "@#{name}"
17
+ @table = ActiveList::Definition::Table.new(name, model, options)
18
+ if block_given?
19
+ yield @table
20
+ else
21
+ @table.load_default_columns
22
+ end
23
+ @parameters = {:sort => :to_s, :dir => :to_s}
24
+ @parameters.merge!(:page => :to_i, :per_page => :to_i) if @table.paginate?
25
+ end
26
+
27
+ def collection?
28
+ @collection
29
+ end
30
+
31
+ def var_name(name)
32
+ "_#{name}"
33
+ end
34
+
35
+ def renderer
36
+ ActiveList::Renderers[@table.options[:renderer]].new(self)
37
+ end
38
+
39
+ def controller_method_code
40
+ code = "# encoding: utf-8\n"
41
+ code << "def #{self.controller_method_name}\n"
42
+ code << self.session_initialization_code.dig
43
+ code << " respond_to do |format|\n"
44
+ code << " format.html do\n"
45
+ code << " if request.xhr?\n"
46
+ code << self.renderer.remote_update_code.dig(4)
47
+ code << " else\n"
48
+ code << " render(inline: '<%=#{self.view_method_name}-%>')\n" # , layout: action_has_layout?
49
+ code << " end\n"
50
+ code << " end\n"
51
+ for format, exporter in ActiveList::Exporters.hash
52
+ code << " format.#{format} do\n"
53
+ code << exporter.new(self).send_data_code.dig(3)
54
+ code << " end\n"
55
+ end
56
+ code << " end\n"
57
+ # Save preferences of user
58
+ if defined? User and User.instance_methods.include? :pref
59
+ code << " p = current_user.pref('list.#{self.view_method_name}', YAML::dump({}))\n"
60
+ code << " p.set! YAML::dump(#{var_name(:params)}.stringify_keys)\n"
61
+ end
62
+ code << "end\n"
63
+ # code.split("\n").each_with_index{|l, x| puts((x+1).to_s.rjust(4)+": "+l)}
64
+ unless ::Rails.env.production?
65
+ file = ::Rails.root.join("tmp", "code", "active_list", "controllers", self.controller.controller_path, self.controller_method_name + ".rb")
66
+ FileUtils.mkdir_p(file.dirname)
67
+ File.write(file, code)
68
+ end
69
+ return code
70
+ end
71
+
72
+ def view_method_code
73
+ code = "# encoding: utf-8\n"
74
+ code << "def #{self.view_method_name}(options={}, &block)\n"
75
+ code << self.session_initialization_code.dig
76
+ code << self.renderer.build_table_code.dig
77
+ code << "end\n"
78
+ # code.split("\n").each_with_index{|l, x| puts((x+1).to_s.rjust(4)+": "+l)}
79
+ unless ::Rails.env.production?
80
+ file = ::Rails.root.join("tmp", "code", "active_list", "views", self.controller.controller_path, self.view_method_name + ".rb")
81
+ FileUtils.mkdir_p(file.dirname)
82
+ File.write(file, code)
83
+ end
84
+ return code
85
+ end
86
+
87
+ def session_initialization_code
88
+ code = "options = {} unless options.is_a? Hash\n"
89
+ code << "options.update(params)\n"
90
+ if defined? User and User.instance_methods.include? :pref
91
+ code << "#{var_name(:params)} = YAML::load(current_user.pref('list.#{self.view_method_name}', YAML::dump({})).value).symbolize_keys\n"
92
+ code << "#{var_name(:params)} = {} unless #{var_name(:params)}.is_a?(Hash)\n"
93
+ else
94
+ code << "#{var_name(:params)} = {}\n"
95
+ end
96
+ code << "#{var_name(:params)}.update(options.symbolize_keys)\n"
97
+ code << "unless #{var_name(:params)}[:hidden_columns].is_a? Array\n"
98
+ code << " #{var_name(:params)}[:hidden_columns] = #{@table.hidden_columns.map(&:name).map(&:to_sym).inspect}\n"
99
+ code << "end\n"
100
+ for parameter, convertor in @parameters.sort{|a,b| a[0].to_s <=> b[0].to_s}
101
+ # expr = "options.delete('#{@table.name}_#{parameter}') || options.delete('#{parameter}') || #{var_name(:params)}[:#{parameter}]"
102
+ # expr += " || #{@table.options[parameter]}" unless @table.options[parameter].blank?
103
+ # code << "#{var_name(:params)}[:#{parameter}] = (#{expr}).#{convertor}\n"
104
+ expr = "#{var_name(:params)}[:#{parameter}]"
105
+ expr = "(#{expr} || #{@table.options[parameter]})" unless @table.options[parameter].blank?
106
+ code << "#{var_name(:params)}[:#{parameter}] = #{expr}.#{convertor}\n"
107
+ end
108
+ # Order
109
+ code << "#{var_name(:order)} = #{@table.options[:order] ? @table.options[:order].inspect : 'nil'}\n"
110
+ code << "if #{var_name(:col)} = {" + @table.sortable_columns.collect{|c| "'#{c.sort_id}' => '#{c.sort_expression}'"}.join(', ') + "}[#{var_name(:params)}[:sort]]\n"
111
+ code << " #{var_name(:params)}[:dir] = 'asc' unless #{var_name(:params)}[:dir] == 'asc' or #{var_name(:params)}[:dir] == 'desc'\n"
112
+ code << " #{var_name(:order)} = #{var_name(:col)} + ' ' + #{var_name(:params)}[:dir]\n"
113
+ code << "end\n"
114
+
115
+ return code
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ require "active_list/generator/finder"
@@ -0,0 +1,150 @@
1
+ module ActiveList
2
+
3
+ # Manage data query
4
+ class Generator
5
+
6
+ # Generate select code for the table taking all parameters in account
7
+ def select_data_code(options = {})
8
+ paginate = (options.has_key?(:paginate) ? options[:paginate] : @table.paginate?)
9
+ # Check order
10
+ unless @table.options.keys.include?(:order)
11
+ columns = @table.table_columns
12
+ @table.options[:order] = (columns.size > 0 ? columns.first.name.to_sym : {id: :desc}) # "#{@table.model.table_name}.id DESC"
13
+ end
14
+
15
+ class_name = @table.model.name
16
+ class_name = "(controller_name != '#{class_name.tableize}' ? controller_name.to_s.classify.constantize : #{class_name})" if self.collection?
17
+
18
+ # Find data
19
+ query_code = "#{class_name}"
20
+ query_code << self.scope_code if self.scope_code
21
+ query_code << ".select(#{self.select_code})" if self.select_code
22
+ query_code << ".where(#{self.conditions_code})" unless @table.options[:conditions].blank?
23
+ query_code << ".joins(#{@table.options[:joins].inspect})" unless @table.options[:joins].blank?
24
+ unless self.includes_reflections.empty?
25
+ expr = self.includes_reflections.inspect[1..-2]
26
+ query_code << ".includes(#{expr})"
27
+ query_code << ".references(#{expr})"
28
+ end
29
+
30
+ code = ""
31
+ code << "#{var_name(:count)} = #{query_code}.count\n"
32
+ if paginate
33
+ code << "#{var_name(:limit)} = (#{var_name(:params)}[:per_page] || 25).to_i\n"
34
+ code << "#{var_name(:page)} = (#{var_name(:params)}[:page] || 1).to_i\n"
35
+ code << "#{var_name(:page)} = 1 if #{var_name(:page)} < 1\n"
36
+ code << "#{var_name(:offset)} = (#{var_name(:page)} - 1) * #{var_name(:limit)}\n"
37
+ code << "#{var_name(:last)} = (#{var_name(:count)}.to_f / #{var_name(:limit)}).ceil.to_i\n"
38
+ code << "#{var_name(:last)} = 1 if #{var_name(:last)} < 1\n"
39
+ code << "return #{self.view_method_name}(options.merge(page: 1)) if 1 > #{var_name(:page)}\n"
40
+ code << "return #{self.view_method_name}(options.merge(page: #{var_name(:last)})) if #{var_name(:page)} > #{var_name(:last)}\n"
41
+ end
42
+ code << "#{self.records_variable_name} = #{query_code}"
43
+ code << ".reorder(#{var_name(:order)})"
44
+ if paginate
45
+ code << ".offset(#{var_name(:offset)})"
46
+ code << ".limit(#{var_name(:limit)})"
47
+ end
48
+ code << " || {}\n"
49
+ return code
50
+ end
51
+
52
+ protected
53
+
54
+ # Compute includes Hash
55
+ def includes_reflections
56
+ hash = []
57
+ for column in @table.columns
58
+ if column.respond_to?(:reflection)
59
+ hash << column.reflection.name
60
+ end
61
+ end
62
+ return hash
63
+ end
64
+
65
+
66
+ def scope_code
67
+ return nil unless scopes = @table.options[:scope]
68
+ scopes = [scopes].flatten
69
+ code = ""
70
+ for scope in scopes
71
+ code << ".#{scope}"
72
+ end
73
+ return code
74
+ end
75
+
76
+
77
+ # Generate the code from a conditions option
78
+ def conditions_code
79
+ conditions = @table.options[:conditions]
80
+ code = ''
81
+ case conditions
82
+ when Array
83
+ case conditions[0]
84
+ when String # SQL
85
+ code << '[' + conditions.first.inspect
86
+ code << conditions[1..-1].collect{|p| ", " + sanitize_condition(p)}.join if conditions.size > 1
87
+ code << ']'
88
+ when Symbol # Method
89
+ raise "What?"
90
+ code << conditions.first.to_s + '('
91
+ code << conditions[1..-1].collect{|p| sanitize_condition(p)}.join(', ') if conditions.size > 1
92
+ code << ')'
93
+ else
94
+ raise ArgumentError.new("First element of an Array can only be String or Symbol.")
95
+ end
96
+ when Hash # SQL
97
+ code << '{' + conditions.collect{|key, value| key.to_s + ': ' + sanitize_condition(value)}.join(',') + '}'
98
+ when Symbol # Method
99
+ code << conditions.to_s + "(options)"
100
+ when Code
101
+ code << "(" + conditions.gsub(/\s*\n\s*/, ';') + ")"
102
+ when String
103
+ code << conditions.inspect
104
+ else
105
+ raise ArgumentError.new("Unsupported type for conditions: #{conditions.inspect}")
106
+ end
107
+ return code
108
+ end
109
+
110
+ def select_code
111
+ return nil unless @table.options[:distinct] or @table.options[:select]
112
+ code = ""
113
+ code << "DISTINCT " if @table.options[:distinct]
114
+ code << "#{@table.model.table_name}.*"
115
+ if @table.options[:select]
116
+ code << @table.options[:select].collect{|k, v| ", #{k[0].to_s+'.'+k[1].to_s} AS #{v}" }.join
117
+ end
118
+ return ("'" + code + "'").c
119
+ end
120
+
121
+
122
+ def sanitize_condition(value)
123
+ # if value.is_a? Array
124
+ # # if value.size==1 and value[0].is_a? String
125
+ # # value[0].to_s
126
+ # # else
127
+ # value.inspect
128
+ # # end
129
+ # elsif value.is_a? Code
130
+ # value.inspect
131
+ # elsif value.is_a? String
132
+ # '"' + value.gsub('"', '\"') + '"'
133
+ # els
134
+ if [Date, DateTime].include? value.class
135
+ '"' + value.to_formatted_s(:db) + '"'
136
+ elsif value.is_a? NilClass
137
+ 'nil'
138
+ else
139
+ value.inspect
140
+ end
141
+ end
142
+
143
+
144
+ end
145
+
146
+
147
+ end
148
+
149
+
150
+