active-list 4.2.4 → 5.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.
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
+