Class: ActiveList::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/active_list/generator/finder.rb,
lib/active_list/generator.rb

Overview

Manage data query

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, &_block) ⇒ Generator

Returns a new instance of Generator.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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 = !!(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)
  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

Instance Attribute Details

#controllerObject

Returns the value of attribute controller.



3
4
5
# File 'lib/active_list/generator.rb', line 3

def controller
  @controller
end

#controller_method_nameObject

Returns the value of attribute controller_method_name.



3
4
5
# File 'lib/active_list/generator.rb', line 3

def controller_method_name
  @controller_method_name
end

#records_variable_nameObject

Returns the value of attribute records_variable_name.



3
4
5
# File 'lib/active_list/generator.rb', line 3

def records_variable_name
  @records_variable_name
end

#tableObject

Returns the value of attribute table.



3
4
5
# File 'lib/active_list/generator.rb', line 3

def table
  @table
end

#view_method_nameObject

Returns the value of attribute view_method_name.



3
4
5
# File 'lib/active_list/generator.rb', line 3

def view_method_name
  @view_method_name
end

Instance Method Details

#collection?Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/active_list/generator.rb', line 24

def collection?
  @collection
end

#controller_method_codeObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/active_list/generator.rb', line 36

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).send_data_code.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

#rendererObject



32
33
34
# File 'lib/active_list/generator.rb', line 32

def renderer
  ActiveList::Renderers[@table.options[:renderer]].new(self)
end

#select_data_code(options = {}) ⇒ Object

Generate select code for the table taking all parameters in account



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 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 = @table.model.name
  class_name = "(controller_name != '#{class_name.tableize}' ? 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 << ".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 << "#{var_name(:count)} = #{query_code}.count\n"

  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_codeObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/active_list/generator.rb', line 84

def session_initialization_code
  code = "options = {} unless options.is_a? Hash\n"
  code << "options.update(params)\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) ⇒ Object



28
29
30
# File 'lib/active_list/generator.rb', line 28

def var_name(name)
  "_#{name}"
end

#view_method_codeObject



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/active_list/generator.rb', line 69

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.dig
  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