query_report 1.0.23 → 1.0.24

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c09663de9764af4df12bdbe7da6cecbae1c7ca0
4
- data.tar.gz: b7e286d433248e29f8b078632f8f18ddbde73a57
3
+ metadata.gz: 38e6dd09227f6ad51d81593b879ded5928ab3c27
4
+ data.tar.gz: 72ef9413da84d9e5d0f5f802c5b7dd8e4cd4aba0
5
5
  SHA512:
6
- metadata.gz: 92ea49358da764dbd315424074025e665f933a2e8c4e7cc96fa02af0ad1b31b27bf8f926a097146d6edf85d64c127ab19ffe3cc6d8f993a73e0c245738186156
7
- data.tar.gz: c713b7bb180db57c9a55c612768d86032740152177bd802961241a047098705f11768d3b04bed3f362b307f8a8378b3007aeb7ad9ca15577bf521d435f9e2b0d
6
+ metadata.gz: aad743d74172a389cc058f6354d819b7e1263fcea268bffcecd1c4d3a2928e38c1b02563cc8f75ff2571472300ee7a2709669cd42cc02d7a8963534599a611d3
7
+ data.tar.gz: 8d5c76e9381b2df6a078f133a82d02ac459f483e93c7afa9281011a58eceb4e50fe800e33ce5add15a104a01c7f2e3da909188ae2fe5e55431c22044f1ecb209
data/README.md CHANGED
@@ -2,14 +2,50 @@
2
2
 
3
3
  [![Build Status](https://api.travis-ci.org/ashrafuzzaman/query_report.png?branch=master)](http://travis-ci.org/ashrafuzzaman/query_report)
4
4
  [![Gem Version](https://badge.fury.io/rb/query_report.png)](http://badge.fury.io/rb/query_report)
5
-
6
- Query report is a reporting tool, which does the following:
7
-
8
- * Generate paginated HTML view with filters, defined columns with sorting
9
- * Generate PDF, CSV, JSON
10
- * Provide feature to define re usable custom filter
11
-
12
- As built in filter I have used [ransack](https://github.com/ernie/ransack) and pagination with [kaminari](https://github.com/amatsuda/kaminari)
5
+ [![Code Climate](https://codeclimate.com/github/ashrafuzzaman/query_report.png)](https://codeclimate.com/github/ashrafuzzaman/query_report)
6
+ [![Code coverage](https://codeclimate.com/github/ashrafuzzaman/query_report/coverage.png)](https://codeclimate.com/github/ashrafuzzaman/query_report)
7
+
8
+ ###Write the action with a simple DSL and get a report with PDF and CSV export, gorgeous charts, out of box filters, with I18n support, etc...
9
+
10
+ Create a report in Rails
11
+ ------------------------
12
+
13
+ You would have to do the following tasks to create a report in rails,
14
+
15
+ - Create a route
16
+ - Create an action with following logic
17
+ - Logic for filters
18
+ - Logic for pagination
19
+ - Create a view
20
+ - Write code to show HTML
21
+ - Write code to generate Graph
22
+ - Generate PDF with prawn pdf and graph
23
+ - Logic to send that PDF file as email
24
+
25
+ Create a report with query report
26
+ ---------------------------------
27
+
28
+ - Create a route
29
+ - Create an action with following logic
30
+ - ~~Logic for filters~~
31
+ - ~~Logic for pagination~~
32
+ - ~~Create a view~~
33
+ - ~~Write code to show HTML~~
34
+ - ~~Write code to generate Graph~~
35
+ - ~~Generate PDF with prawn pdf and graph~~
36
+ - ~~Logic to send that PDF file as email~~
37
+
38
+ For email, you have to implement the popup once.
39
+
40
+ Features
41
+ --------
42
+
43
+ - Allow to use and reuse filters using [ransack](https://github.com/activerecord-hackery/ransack), and also with custom query
44
+ - Paginates [kaminari](https://github.com/amatsuda/kaminari)
45
+ - Supports ajax out of box
46
+ - Exports to PDF [prawn](https://github.com/prawnpdf/prawn), csv, json
47
+ - Supports to send report pdf as email
48
+ - Supports I18N
13
49
 
14
50
  For a demo see [here](http://query-report-demo.herokuapp.com)
15
51
 
@@ -45,8 +81,8 @@ class InvoicesController < ApplicationController
45
81
  column :title do |invoice|
46
82
  link_to invoice.title, invoice
47
83
  end
48
- column :total_paid
49
- column :total_charged
84
+ column :total_paid, show_total: true
85
+ column :total_charged, show_total: true
50
86
  column :paid
51
87
  end
52
88
  end
@@ -2,7 +2,7 @@
2
2
  <table class="<%= QueryReport.config.record_table_class %>" cellpadding="0" cellspacing="0">
3
3
  <thead>
4
4
  <% report.columns.each do |column| %>
5
- <th><%= column.sortable? ? sort_link(report.search, column.name, params, remote: @remote) : column.humanize %></th>
5
+ <th><%= column.sortable? ? sort_link(report.search, column.sort_link_attribute, column.humanize, params, remote: @remote) : column.humanize %></th>
6
6
  <% end %>
7
7
  </thead>
8
8
 
@@ -8,14 +8,52 @@ module QueryReport
8
8
  attr_accessor :columns
9
9
 
10
10
  # Creates a filter and adds to the filters
11
- # Params:
12
- # +column+:: the column on which the filter is done on
13
- # +options+:: Options can have the following,
14
- # options[:type] => date | text | whatever
15
- # options[:comp] => the comparators used for ransack search, [:gteq, :lteq]
16
- # options[:show_total] => set true to calculate total for that column
17
- # options[:only_on_web] => the column will appear on the web and not appear in PDF or csv if set to true
18
- # options[:rowspan] => the rows with same values in the same column will span if set to true
11
+ # @param name the column on which the filter is done on
12
+ # @option options [Symbol] :type date | text | whatever
13
+ # @option options [String] :as The title of the column, by default it fetches from the I18n column translation, Model.human_attribute_name(column_name)
14
+ # @option options [Boolean] :show_total set true to calculate total for that column. It will render the total in the footer.
15
+ # @option options [Boolean] :only_on_web the column will appear on the web and not appear in PDF, CSV or JSON if set to true
16
+ # @option options [Boolean] :sortable if set to true then sorts on that column, but if the sorting has to be on a joint table then you have to specify the column on which the sorting will happen
17
+ # @option options :rowspan the rows with same values in the same column will span if set to true
18
+ #
19
+ # @example Row span
20
+ # column :invoiced_to_name, rowspan: true
21
+ # column :invoice_title
22
+ # column :invoice_date, rowspan: :invoiced_to_name
23
+ # ┌───────────┬────────────┬─────────────────┐
24
+ # │ Name │ Invoice │ Invoiced on │
25
+ # ├───────────┼────────────┼─────────────────┤
26
+ # │ │ Invoice1 │ │
27
+ # │ Jitu ├────────────┤ 2-2-2014 │
28
+ # │ │ Invoice2 │ │
29
+ # ├───────────┼────────────┼─────────────────┤
30
+ # │ Setu │ Invoice3 │ 2-2-2014 │
31
+ # └───────────┴────────────┴─────────────────┘
32
+ #
33
+ # @example Show total
34
+ # column :invoiced_to_name, rowspan: true
35
+ # column :invoice_title
36
+ # column :total_charged, show_total: true
37
+ # ┌───────────┬────────────┬─────────────────┐
38
+ # │ Name │ Invoice │ Total charge │
39
+ # ├───────────┼────────────┼─────────────────┤
40
+ # │ │ Invoice1 │ 100 │
41
+ # │ Jitu ├────────────┼─────────────────┤
42
+ # │ │ Invoice2 │ 120 │
43
+ # ├───────────┼────────────┼─────────────────┤
44
+ # │ Setu │ Invoice3 │ 80 │
45
+ # ├───────────┴────────────┼─────────────────┤
46
+ # │ Total │ 300 │
47
+ # └────────────────────────┴─────────────────┘
48
+ #
49
+ # @example Sorting
50
+ # column :invoice_date, sortable: true
51
+ # column :invoice_to, sortable: 'users.name'
52
+ #
53
+ # If you want to sort a column which is a column of the active record model that the query returns,
54
+ # then just set true to make the column sortable.
55
+ # If the column is from another table then you have to specify the column name.
56
+ #
19
57
  def column(name, options={}, &block)
20
58
  @columns << Column.new(self, name, options, block)
21
59
  end
@@ -59,7 +97,11 @@ module QueryReport
59
97
  end
60
98
 
61
99
  def sortable?
62
- @options[:sortable] == true
100
+ @options[:sortable].present? && @options[:sortable] != false
101
+ end
102
+
103
+ def sort_link_attribute
104
+ @options[:sortable] == true ? name : @options[:sortable]
63
105
  end
64
106
 
65
107
  def rowspan?
@@ -67,12 +109,16 @@ module QueryReport
67
109
  end
68
110
 
69
111
  def rowspan_column_humanized
112
+ return @rowspan_column_humanized if @rowspan_column_humanized
70
113
  rowspan_column_name = @options[:rowspan].kind_of?(Symbol) ? @options[:rowspan] : self.name
71
114
 
72
115
  report.columns.each do |column|
73
- return column.humanize if column.name == rowspan_column_name
116
+ if column.name == rowspan_column_name
117
+ @rowspan_column_humanized = column.humanize
118
+ return @rowspan_column_humanized
119
+ end
74
120
  end
75
- return self.humanize
121
+ @rowspan_column_humanized = self.humanize
76
122
  end
77
123
 
78
124
  def humanize
@@ -104,7 +150,6 @@ module QueryReport
104
150
  end
105
151
  end
106
152
  end
107
-
108
153
  end
109
154
  end
110
155
  end
@@ -10,29 +10,38 @@ module QueryReport
10
10
  module FilterModule
11
11
  attr_accessor :filters, :search
12
12
 
13
- # Creates a filter and adds to the filters
14
- # Params:
15
- # +column+:: the column on which the filter is done on
16
- # +options+:: Options can have the following,
17
- # options[:type] => date | text | whatever
18
- # options[:comp] => the comparators used for ransack search, [:gteq, :lteq]
19
- # options[:manual] => if set to true then that filter will not be applied, only will appear and can be used for custom application
20
- # options[:default] => support default filter value, can be one value or for range filter can be array
13
+ # Creates a filter
14
+ # @param column the column on which the filter is done on, for manual filter the column name can be anything
15
+ # @option options [Symbol] :type date | text | whatever
16
+ # @option options [Array] :comp the comparators used for ransack search, [:gteq, :lteq]
17
+ # @option options [Boolean] :manual if set to true then that filter will not be applied, only will appear and can be used for custom application
18
+ # @option options :default support default filter value, can be one value or for range filter can be array
19
+ #
20
+ # @example Custom type
21
+ # filter :invoiced_to_id, type: :user
22
+ #
23
+ # # In a helper file define method
24
+ # def query_report_user_filter(name, user_id, options={})
25
+ # user = User.find(user_id)
26
+ # concat hidden_field_tag name, user_id, options
27
+ # text_field_tag "#{name}", user.name, class: 'user_search' #implement the filter, it can be autocomplete
28
+ # end
29
+ #
30
+
21
31
  def filter(column, options={}, &block)
22
32
  @filters ||= []
23
33
  @filters << Filter.new(@params, column, options, &block)
24
34
  end
25
35
 
26
- def has_filter?
27
- filters.present?
28
- end
29
-
30
36
  def apply_filters(query, http_params)
31
37
  # apply default filter
32
38
  params = load_default_values_in_param(http_params) #need for ransack filter
33
39
  @search = query.ransack(params[:q])
34
40
  query = @search.result
35
41
 
42
+ #this is to fix a bug from ransack, as for ransack when the sorting is done from a joined table it does not sort by default
43
+ query = query.order(params[:q][:s]) if params[:q][:s]
44
+
36
45
  #apply custom filter
37
46
  @filters.select(&:custom?).each do |filter|
38
47
  ordered_custom_param_values = ordered_param_value_objects(filter)
@@ -42,24 +51,6 @@ module QueryReport
42
51
  query
43
52
  end
44
53
 
45
- def ordered_param_value_objects(filter)
46
- filter.comparators.collect do |comp|
47
- comp.objectified_param_value
48
- end
49
- end
50
-
51
- def load_default_values_in_param(http_params)
52
- params = http_params.clone
53
- params = params.merge(q: {}) unless params[:q]
54
- params = params.merge(custom_search: {}) unless params[:custom_search]
55
- @filters.each do |filter|
56
- filter.comparators.each do |comparator|
57
- params[filter.params_key][comparator.search_key] ||= comparator.param_value
58
- end
59
- end
60
- params
61
- end
62
-
63
54
  class Filter
64
55
  attr_reader :params, :column, :type, :comparators, :block, :options
65
56
 
@@ -120,5 +111,27 @@ module QueryReport
120
111
  end
121
112
  end
122
113
  end
114
+
115
+ def has_filter?
116
+ filters.present?
117
+ end
118
+
119
+ def ordered_param_value_objects(filter)
120
+ filter.comparators.collect do |comp|
121
+ comp.objectified_param_value
122
+ end
123
+ end
124
+
125
+ def load_default_values_in_param(http_params)
126
+ params = http_params.clone
127
+ params = params.merge(q: {}) unless params[:q]
128
+ params = params.merge(custom_search: {}) unless params[:custom_search]
129
+ @filters.each do |filter|
130
+ filter.comparators.each do |comparator|
131
+ params[filter.params_key][comparator.search_key] ||= comparator.param_value
132
+ end
133
+ end
134
+ params
135
+ end
123
136
  end
124
137
  end
@@ -11,12 +11,10 @@ module QueryReport
11
11
  module Helper
12
12
 
13
13
  # Generates the reports
14
- # Params:
15
- # query - The base query that the reporter with start with [filters will be applied on it]
16
- # options - Options for the reports
17
- # :custom_view - by default false, if set to true then the reporter will look for the file to render
18
- # :skip_rendering - by default false, if set to true then the reporter will not render any thing, you will have to implement the rendering
19
- # :per_page - If given then overrides the default kaminari per page option
14
+ # @param query The base query that the reporter with start with [filters will be applied on it]
15
+ # @option options [Integer] :per_page If given then overrides the default kaminari per page option
16
+ # @option options [Boolean] :custom_view by default false, if set to true then the reporter will look for the file to render
17
+ # @option options [Boolean] :skip_rendering by default false, if set to true then the reporter will not render any thing, you will have to implement the rendering
20
18
  def reporter(query, options={}, &block)
21
19
  @report ||= QueryReport::Report.new(params, view_context, options)
22
20
  @report.query = query
@@ -78,7 +76,7 @@ module QueryReport
78
76
  end
79
77
 
80
78
  def send_pdf_email(email, subject, message, file_name, attachment)
81
- @user = current_user
79
+ @user = current_user if defined? current_user
82
80
  to = email.split(',')
83
81
  ReportMailer.send_report(@user, to, subject, message, file_name, attachment).deliver
84
82
  end
@@ -1,3 +1,3 @@
1
1
  module QueryReport
2
- VERSION = "1.0.23"
2
+ VERSION = "1.0.24"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: query_report
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.23
4
+ version: 1.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - A.K.M. Ashrafuzzaman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-29 00:00:00.000000000 Z
11
+ date: 2014-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -252,3 +252,4 @@ signing_key:
252
252
  specification_version: 4
253
253
  summary: Structure you reports
254
254
  test_files: []
255
+ has_rdoc: