class ActiveList::Generator
Manage data query
Attributes
controller[RW]
controller_method_name[RW]
export_class[RW]
records_variable_name[RW]
table[RW]
view_method_name[RW]
Public Class Methods
new(*args) { |table| ... }
click to toggle source
# File lib/active_list/generator.rb, line 5 def initialize(*args, &_block) options = args.extract_options! @controller = options[:controller] name = args.shift || @controller.controller_name.to_sym model = (options[:model] || name).to_s.classify.constantize @collection = options[:collection] || !!(model.name == @controller.controller_name.to_s.classify) @controller_method_name = "list#{'_' + name.to_s if name != @controller.controller_name.to_sym}" @view_method_name = "_#{@controller.controller_name}_list_#{name}_tag" @records_variable_name = "@#{name}" @table = ActiveList::Definition::Table.new(name, model, options) @export_class = options[:export_class] if block_given? yield @table else @table.load_default_columns end @parameters = { sort: :to_s, dir: :to_s } @parameters.merge!(page: :to_i, per_page: :to_i) if @table.paginate? end
Public Instance Methods
collection?()
click to toggle source
# File lib/active_list/generator.rb, line 25 def collection? @collection end
controller_method_code()
click to toggle source
# File lib/active_list/generator.rb, line 37 def controller_method_code code = "# encoding: utf-8\n" code << "def #{controller_method_name}\n" code << session_initialization_code.dig code << " respond_to do |format|\n" code << " format.html do\n" code << " if request.xhr?\n" code << renderer.remote_update_code.dig(4) code << " else\n" code << " render(inline: '<%=#{view_method_name}-%>')\n" # , layout: action_has_layout? code << " end\n" code << " end\n" for format, exporter in ActiveList::Exporters.hash code << " format.#{format} do\n" code << exporter.new(self).generate_file_code(format).dig(3) code << " end\n" end code << " end\n" # Save preferences of user if defined?(User) && User.instance_methods.include?(:preference) code << " p = current_user.preference('list.#{view_method_name}', YAML::dump({}))\n" code << " p.set! YAML::dump(#{var_name(:params)}.stringify_keys)\n" end code << "end\n" # code.split("\n").each_with_index{|l, x| puts((x+1).to_s.rjust(4)+": "+l)} unless ::Rails.env.production? file = ::Rails.root.join('tmp', 'code', 'active_list', 'controllers', controller.controller_path, controller_method_name + '.rb') FileUtils.mkdir_p(file.dirname) File.write(file, code) end code end
exportable_query_code(options = {})
click to toggle source
# File lib/active_list/generator/finder.rb, line 67 def exportable_query_code(options = {}) unless @table.options.keys.include?(:order) columns = @table.table_columns @table.options[:order] = (columns.any? ? columns.first.name.to_sym : { id: :desc }) end class_name = "options[\"constant_name\"]&.constantize || #{@table.model.name}" class_name = "(controller_name != '#{class_name.tableize}' && !options[\"constant_name\"] ? controller_name.to_s.classify.constantize : #{class_name})" if collection? code = '' code << "query = #{class_name}.to_s\n" code << "query << #{scope_code.inspect}\n" if scope_code if select_code code << "select = #{select_code}\n" code << "query << \".select(\"\n" code << "query << select.inspect\n" code << "query << \")\"\n" end if from_code code << "from = #{from_code}\n" code << "query << \".from(\"\n" code << "query << from.inspect\n" code << "query << \")\"\n" end unless @table.options[:conditions].blank? code << "condition = #{conditions_code}\n" code << "query << \".where(\"\n" code << "query << condition.inspect\n" code << "query << \")\"\n" end code << "query << \".joins(#{@table.options[:joins].inspect})\"\n" unless @table.options[:joins].blank? unless includes_reflections.empty? expr = includes_reflections.inspect[1..-2] code << "query << \".includes(#{expr})\"\n" code << "query << \".references(#{expr})\"\n" end unless @table.options[:group].blank? code << "group = #{@table.options[:group].inspect}\n" code << "query << \".group(\"\n" code << "query << group.inspect\n" code << "query << \")\"\n" end code << "order = #{var_name(:order)}\n" code << "query << \".reorder(\"\n" code << "query << order.inspect\n" code << "query << \")\"\n" code.c end
renderer()
click to toggle source
# File lib/active_list/generator.rb, line 33 def renderer ActiveList::Renderers[@table.options[:renderer]].new(self) end
select_data_code(options = {})
click to toggle source
Generate select code for the table taking all parameters in account
# File lib/active_list/generator/finder.rb, line 5 def select_data_code(options = {}) paginate = (options.key?(:paginate) ? options[:paginate] : @table.paginate?) # Check order unless @table.options.keys.include?(:order) columns = @table.table_columns @table.options[:order] = (columns.any? ? columns.first.name.to_sym : { id: :desc }) end class_name = "options[\"constant_name\"]&.constantize || #{@table.model.name}" class_name = "(controller_name != '#{class_name.tableize}' && !options[\"constant_name\"] ? controller_name.to_s.classify.constantize : #{class_name})" if collection? # Find data query_code = class_name.to_s query_code << scope_code if scope_code query_code << ".select(#{select_code})" if select_code query_code << ".from(#{from_code})" if from_code query_code << ".where(#{conditions_code})" unless @table.options[:conditions].blank? query_code << ".joins(#{@table.options[:joins].inspect})" unless @table.options[:joins].blank? unless includes_reflections.empty? expr = includes_reflections.inspect[1..-2] query_code << ".includes(#{expr})" query_code << ".references(#{expr})" end code = '' code << "#{query_code}\n" code << if @table.options[:count].present? "#{var_name(:count)} = #{query_code}.count(#{@table.options[:count].inspect})\n" else "#{var_name(:count)} = #{query_code}.count\n" end query_code << ".group(#{@table.options[:group].inspect})" unless @table.options[:group].blank? query_code << ".reorder(#{var_name(:order)})" if paginate code << "#{var_name(:limit)} = (#{var_name(:params)}[:per_page] || 25).to_i\n" code << "if params[:page]\n" code << " #{var_name(:page)} = (#{var_name(:params)}[:page] || 1).to_i\n" code << "elsif params['#{table.name}-id'] and #{var_name(:index)} = #{query_code}.pluck(:id).index(params['#{table.name}-id'].to_i)\n" # Find page of request element code << " #{var_name(:page)} = (#{var_name(:index)}.to_f / #{var_name(:limit)}).floor + 1\n" code << "else\n" code << " #{var_name(:page)} = 1\n" code << "end\n" code << "#{var_name(:page)} = 1 if #{var_name(:page)} < 1\n" code << "#{var_name(:offset)} = (#{var_name(:page)} - 1) * #{var_name(:limit)}\n" code << "#{var_name(:last)} = (#{var_name(:count)}.to_f / #{var_name(:limit)}).ceil.to_i\n" code << "#{var_name(:last)} = 1 if #{var_name(:last)} < 1\n" code << "return #{view_method_name}(options.merge(page: 1)) if 1 > #{var_name(:page)}\n" code << "return #{view_method_name}(options.merge(page: #{var_name(:last)})) if #{var_name(:page)} > #{var_name(:last)}\n" query_code << ".offset(#{var_name(:offset)})" query_code << ".limit(#{var_name(:limit)})" end code << "#{records_variable_name} = #{query_code} || {}\n" code end
session_initialization_code()
click to toggle source
# File lib/active_list/generator.rb, line 85 def session_initialization_code code = "options = {} unless options.is_a? Hash\n" # For Rails 5 code << "options.update(params.to_unsafe_h)\n" if defined?(User) && User.instance_methods.include?(:preference) code << "#{var_name(:params)} = YAML::load(current_user.preference('list.#{view_method_name}', YAML::dump({})).value).symbolize_keys\n" code << "#{var_name(:params)} = {} unless #{var_name(:params)}.is_a?(Hash)\n" else code << "#{var_name(:params)} = {}\n" end code << "#{var_name(:params)}.update(options.symbolize_keys)\n" code << "unless #{var_name(:params)}[:hidden_columns].is_a? Array\n" code << " #{var_name(:params)}[:hidden_columns] = #{@table.hidden_columns.map(&:name).map(&:to_sym).inspect}\n" code << "end\n" for parameter, convertor in @parameters.sort { |a, b| a[0].to_s <=> b[0].to_s } # expr = "options.delete('#{@table.name}_#{parameter}') || options.delete('#{parameter}') || #{var_name(:params)}[:#{parameter}]" # expr += " || #{@table.options[parameter]}" unless @table.options[parameter].blank? # code << "#{var_name(:params)}[:#{parameter}] = (#{expr}).#{convertor}\n" expr = "#{var_name(:params)}[:#{parameter}]" expr = "(#{expr} || #{@table.options[parameter]})" unless @table.options[parameter].blank? code << "#{var_name(:params)}[:#{parameter}] = #{expr}.#{convertor}\n" end code << "params[:redirect] ||= request.fullpath unless request.xhr?\n" # Order code << "#{var_name(:order)} = #{@table.options[:order] ? @table.options[:order].inspect : 'nil'}\n" code << "if #{var_name(:col)} = {" + @table.sortable_columns.collect { |c| "'#{c.sort_id}' => '#{c.sort_expression}'" }.join(', ') + "}[#{var_name(:params)}[:sort]]\n" code << " #{var_name(:params)}[:dir] = 'asc' unless #{var_name(:params)}[:dir] == 'asc' or #{var_name(:params)}[:dir] == 'desc'\n" code << " null_pos = 'first' if #{var_name(:params)}[:dir] == 'asc'\n" code << " null_pos = 'last' if #{var_name(:params)}[:dir] == 'desc'\n" code << " #{var_name(:order)} = #{var_name(:col)} + ' ' + #{var_name(:params)}[:dir] + ' NULLS ' + null_pos \n" code << "end\n" code end
var_name(name)
click to toggle source
# File lib/active_list/generator.rb, line 29 def var_name(name) "_#{name}" end
view_method_code()
click to toggle source
# File lib/active_list/generator.rb, line 70 def view_method_code code = "# encoding: utf-8\n" code << "def #{view_method_name}(options={}, &block)\n" code << session_initialization_code.dig code << "#{renderer.build_table_code}(options).dig\n" code << "end\n" # code.split("\n").each_with_index{|l, x| puts((x+1).to_s.rjust(4)+": "+l)} unless ::Rails.env.production? file = ::Rails.root.join('tmp', 'code', 'active_list', 'views', controller.controller_path, view_method_name + '.rb') FileUtils.mkdir_p(file.dirname) File.write(file, code) end code end
Protected Instance Methods
conditions_code()
click to toggle source
Generate the code from a conditions option
# File lib/active_list/generator/finder.rb, line 147 def conditions_code conditions = @table.options[:conditions] code = '' case conditions when Array case conditions[0] when String # SQL code << '[' + conditions.first.inspect code << conditions[1..-1].collect { |p| ', ' + sanitize_condition(p) }.join if conditions.size > 1 code << ']' when Symbol # Method raise 'What?' # Amazingly explicit. # code << conditions.first.to_s + '(' # code << conditions[1..-1].collect { |p| sanitize_condition(p) }.join(', ') if conditions.size > 1 # code << ')' else raise ArgumentError, 'First element of an Array can only be String or Symbol.' end when Hash # SQL code << '{' + conditions.collect { |key, value| key.to_s + ': ' + sanitize_condition(value) }.join(',') + '}' when Symbol # Method code << conditions.to_s + '(options)' when CodeString code << '(' + conditions.gsub(/\s*\n\s*/, ';') + ')' when String code << conditions.inspect else raise ArgumentError, "Unsupported type for conditions: #{conditions.inspect}" end code end
from_code()
click to toggle source
# File lib/active_list/generator/finder.rb, line 179 def from_code return nil unless @table.options[:from] from = @table.options[:from] code = '' code << '(' + from.gsub(/\s*\n\s*/, ';') + ')' code end
includes_reflections()
click to toggle source
Compute includes Hash
# File lib/active_list/generator/finder.rb, line 128 def includes_reflections hash = [] @table.columns.each do |column| hash << column.reflection.name if column.respond_to?(:reflection) end hash end
sanitize_condition(value)
click to toggle source
# File lib/active_list/generator/finder.rb, line 208 def sanitize_condition(value) # if value.is_a? Array # # if value.size==1 and value[0].is_a? String # # value[0].to_s # # else # value.inspect # # end # elsif value.is_a? CodeString # value.inspect # elsif value.is_a? String # '"' + value.gsub('"', '\"') + '"' # els if [Date, DateTime].include? value.class '"' + value.to_formatted_s(:db) + '"' elsif value.is_a? NilClass 'nil' else value.inspect end end
scope_code()
click to toggle source
# File lib/active_list/generator/finder.rb, line 136 def scope_code return nil unless scopes = @table.options[:scope] scopes = [scopes].flatten code = '' scopes.each do |scope| code << ".#{scope}" end code end
select_code()
click to toggle source
# File lib/active_list/generator/finder.rb, line 187 def select_code return nil unless @table.options[:distinct] || @table.options[:select] code = '' code << 'DISTINCT ' if @table.options[:distinct] if @table.options[:select] # code << @table.options[:select].collect { |k, v| ", #{k[0].to_s + '.' + k[1].to_s} AS #{v}" }.join code << @table.options[:select].collect do |k, v| c = if k.is_a? Array k[0].to_s + '.' + k[1].to_s else k end c += " AS #{v}" unless v.blank? c end.join(', ') else code << "#{@table.model.table_name}.*" end ('"' + code + '"').c end