datagrid 1.8.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +11 -1
  4. data/{Readme.markdown → README.md} +44 -29
  5. data/app/assets/stylesheets/datagrid.css +145 -0
  6. data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
  7. data/app/views/datagrid/_form.html.erb +4 -4
  8. data/app/views/datagrid/_head.html.erb +26 -3
  9. data/app/views/datagrid/_range_filter.html.erb +5 -3
  10. data/app/views/datagrid/_row.html.erb +12 -1
  11. data/app/views/datagrid/_table.html.erb +4 -4
  12. data/datagrid.gemspec +8 -7
  13. data/lib/datagrid/active_model.rb +9 -17
  14. data/lib/datagrid/base.rb +39 -0
  15. data/lib/datagrid/column_names_attribute.rb +9 -11
  16. data/lib/datagrid/columns/column.rb +155 -133
  17. data/lib/datagrid/columns.rb +325 -115
  18. data/lib/datagrid/configuration.rb +33 -4
  19. data/lib/datagrid/core.rb +89 -54
  20. data/lib/datagrid/deprecated_object.rb +20 -0
  21. data/lib/datagrid/drivers/abstract_driver.rb +12 -23
  22. data/lib/datagrid/drivers/active_record.rb +24 -26
  23. data/lib/datagrid/drivers/array.rb +22 -14
  24. data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
  25. data/lib/datagrid/drivers/mongoid.rb +15 -17
  26. data/lib/datagrid/drivers/sequel.rb +14 -19
  27. data/lib/datagrid/drivers.rb +2 -1
  28. data/lib/datagrid/engine.rb +11 -3
  29. data/lib/datagrid/filters/base_filter.rb +166 -143
  30. data/lib/datagrid/filters/boolean_filter.rb +19 -5
  31. data/lib/datagrid/filters/date_filter.rb +33 -35
  32. data/lib/datagrid/filters/date_time_filter.rb +24 -16
  33. data/lib/datagrid/filters/default_filter.rb +9 -3
  34. data/lib/datagrid/filters/dynamic_filter.rb +151 -105
  35. data/lib/datagrid/filters/enum_filter.rb +43 -19
  36. data/lib/datagrid/filters/extended_boolean_filter.rb +39 -31
  37. data/lib/datagrid/filters/float_filter.rb +15 -5
  38. data/lib/datagrid/filters/integer_filter.rb +21 -10
  39. data/lib/datagrid/filters/ranged_filter.rb +66 -45
  40. data/lib/datagrid/filters/select_options.rb +58 -49
  41. data/lib/datagrid/filters/string_filter.rb +9 -4
  42. data/lib/datagrid/filters.rb +204 -79
  43. data/lib/datagrid/form_builder.rb +116 -128
  44. data/lib/datagrid/generators/scaffold.rb +184 -0
  45. data/lib/datagrid/generators/views.rb +20 -0
  46. data/lib/datagrid/helper.rb +436 -69
  47. data/lib/datagrid/ordering.rb +26 -29
  48. data/lib/datagrid/rspec.rb +6 -10
  49. data/lib/datagrid/utils.rb +37 -30
  50. data/lib/datagrid/version.rb +3 -1
  51. data/lib/datagrid.rb +8 -28
  52. data/templates/base.rb.erb +6 -4
  53. data/templates/grid.rb.erb +1 -1
  54. metadata +17 -17
  55. data/app/assets/stylesheets/datagrid.sass +0 -134
  56. data/lib/datagrid/filters/composite_filters.rb +0 -49
  57. data/lib/datagrid/renderer.rb +0 -157
  58. data/lib/datagrid/scaffold.rb +0 -129
  59. data/lib/tasks/datagrid_tasks.rake +0 -15
  60. data/templates/controller.rb.erb +0 -6
  61. data/templates/index.html.erb +0 -5
@@ -1,49 +0,0 @@
1
- module Datagrid
2
- module Filters
3
- # @!visibility private
4
- module CompositeFilters
5
-
6
- def self.included(base)
7
- base.extend ClassMethods
8
- base.class_eval do
9
- end
10
- end
11
-
12
- # @!visibility private
13
- module ClassMethods
14
-
15
- def date_range_filters(field, from_options = {}, to_options = {})
16
- Utils.warn_once('date_range_filters is deprecated in favor of range option for date filter')
17
- from_options = normalize_composite_filter_options(from_options, field)
18
- to_options = normalize_composite_filter_options(to_options, field)
19
-
20
- filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :date, **from_options) do |date, scope, grid|
21
- grid.driver.greater_equal(scope, field, date)
22
- end
23
- filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :date, **to_options) do |date, scope, grid|
24
- grid.driver.less_equal(scope, field, date)
25
- end
26
- end
27
-
28
- def integer_range_filters(field, from_options = {}, to_options = {})
29
- Utils.warn_once('integer_range_filters is deprecated in favor of range option for integer filter')
30
- from_options = normalize_composite_filter_options(from_options, field)
31
- to_options = normalize_composite_filter_options(to_options, field)
32
- filter(from_options[:name] || :"from_#{field.to_s.tr('.', '_')}", :integer, **from_options) do |value, scope, grid|
33
- grid.driver.greater_equal(scope, field, value)
34
- end
35
- filter(to_options[:name] || :"to_#{field.to_s.tr('.', '_')}", :integer, **to_options) do |value, scope, grid|
36
- grid.driver.less_equal(scope, field, value)
37
- end
38
- end
39
-
40
- def normalize_composite_filter_options(options, field)
41
- if options.is_a?(String) || options.is_a?(Symbol)
42
- options = {name: options}
43
- end
44
- options
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,157 +0,0 @@
1
- require "action_view"
2
-
3
- module Datagrid
4
- # @!visibility private
5
- class Renderer
6
-
7
- def self.for(template)
8
- new(template)
9
- end
10
-
11
- def initialize(template)
12
- @template = template
13
- end
14
-
15
- def format_value(grid, column, asset)
16
- if column.is_a?(String) || column.is_a?(Symbol)
17
- column = grid.column_by_name(column)
18
- end
19
-
20
- value = grid.html_value(column, @template, asset)
21
-
22
- url = column.options[:url] && column.options[:url].call(asset)
23
- if url
24
- @template.link_to(value, url)
25
- else
26
- value
27
- end
28
- end
29
-
30
- def form_for(grid, options = {})
31
- options[:method] ||= :get
32
- options[:html] ||= {}
33
- options[:html][:class] ||= "datagrid-form #{@template.dom_class(grid)}"
34
- options[:as] ||= grid.param_name
35
- _render_partial('form', options[:partials], {:grid => grid, :options => options})
36
- end
37
-
38
- def table(grid, assets, **options)
39
- options[:html] ||= {}
40
- options[:html][:class] ||= "datagrid #{@template.dom_class(grid)}"
41
-
42
- _render_partial('table', options[:partials],
43
- {
44
- grid: grid,
45
- options: options,
46
- assets: assets
47
- })
48
- end
49
-
50
- def header(grid, options = {})
51
- options[:order] = true unless options.has_key?(:order)
52
-
53
- _render_partial('head', options[:partials],
54
- { :grid => grid, :options => options })
55
- end
56
-
57
- def rows(grid, assets = grid.assets, **options, &block)
58
- result = assets.map do |asset|
59
- row(grid, asset, **options, &block)
60
- end.to_a.join
61
-
62
- _safe(result)
63
- end
64
-
65
- def row(grid, asset, **options, &block)
66
- Datagrid::Helper::HtmlRow.new(self, grid, asset, options).tap do |row|
67
- if block_given?
68
- return @template.capture(row, &block)
69
- end
70
- end
71
- end
72
-
73
- def order_for(grid, column, options = {})
74
- _render_partial('order_for', options[:partials],
75
- { :grid => grid, :column => column })
76
- end
77
-
78
- def order_path(grid, column, descending, request)
79
- column = grid.column_by_name(column)
80
- query = request ? request.query_parameters : {}
81
- ActionDispatch::Http::URL.path_for(
82
- path: request ? request.path : '/',
83
- params: query.merge(grid.query_params(order: column.name, descending: descending))
84
- )
85
- end
86
-
87
- private
88
-
89
- def _safe(string)
90
- string.respond_to?(:html_safe) ? string.html_safe : string
91
- end
92
-
93
- def _render_partial(partial_name, partials_path, locals = {})
94
- @template.render({
95
- :partial => File.join(partials_path || 'datagrid', partial_name),
96
- :locals => locals
97
- })
98
- end
99
- end
100
-
101
- module Helper
102
- # Represents a datagrid row that provides access to column values for the given asset
103
- # @example
104
- # row = datagrid_row(grid, user)
105
- # row.class # => Datagrid::Helper::HtmlRow
106
- # row.first_name # => "<strong>Bogdan</strong>"
107
- # row.grid # => Grid object
108
- # row.asset # => User object
109
- # row.each do |value|
110
- # puts value
111
- # end
112
- class HtmlRow
113
-
114
- include Enumerable
115
-
116
- attr_reader :grid, :asset, :options
117
-
118
- # @!visibility private
119
- def initialize(renderer, grid, asset, options)
120
- @renderer = renderer
121
- @grid = grid
122
- @asset = asset
123
- @options = options
124
- end
125
-
126
- # @return [Object] a column value for given column name
127
- def get(column)
128
- @renderer.format_value(@grid, column, @asset)
129
- end
130
-
131
- # Iterates over all column values that are available in the row
132
- # param block [Proc] column value iterator
133
- def each(&block)
134
- (@options[:columns] || @grid.html_columns).each do |column|
135
- block.call(get(column))
136
- end
137
- end
138
-
139
- def to_s
140
- @renderer.send(:_render_partial, 'row', options[:partials], {
141
- :grid => grid,
142
- :options => options,
143
- :asset => asset
144
- })
145
- end
146
-
147
- protected
148
- def method_missing(method, *args, &blk)
149
- if column = @grid.column_by_name(method)
150
- get(column)
151
- else
152
- super
153
- end
154
- end
155
- end
156
- end
157
- end
@@ -1,129 +0,0 @@
1
- require "rails/generators"
2
-
3
- class Datagrid::Scaffold < Rails::Generators::NamedBase
4
-
5
- include Rails::Generators::ResourceHelpers
6
-
7
- check_class_collision suffix: "Grid"
8
- source_root File.expand_path(__FILE__ + "/../../../templates")
9
-
10
- def create_scaffold
11
- unless file_exists?(base_grid_file)
12
- template "base.rb.erb", base_grid_file
13
- end
14
- template "grid.rb.erb", "app/grids/#{grid_class_name.underscore}.rb"
15
- if file_exists?(grid_controller_file)
16
- inject_into_file grid_controller_file, index_action, after: %r{class .*#{grid_controller_class_name}.*\n}
17
- else
18
- template "controller.rb.erb", grid_controller_file
19
- end
20
- template "index.html.erb", view_file
21
- route(generate_routing_namespace("resources :#{grid_controller_short_name}"))
22
- unless defined?(::Kaminari) || defined?(::WillPaginate)
23
- gem 'kaminari'
24
- end
25
- in_root do
26
- {
27
- "css" => " *= require datagrid",
28
- "css.sass" => " *= require datagrid",
29
- "css.scss" => " *= require datagrid",
30
- }.each do |extension, string|
31
- file = "app/assets/stylesheets/application.#{extension}"
32
- if file_exists?(file)
33
- inject_into_file file, string + "\n", {before: %r{.*require_self}} # before all
34
- end
35
- end
36
- end
37
- end
38
-
39
- def view_file
40
- Rails.root.join("app/views").join(controller_file_path).join("index.html.erb")
41
- end
42
-
43
- def grid_class_name
44
- file_name.camelize.pluralize + "Grid"
45
- end
46
-
47
- def grid_controller_class_name
48
- controller_class_name.camelize + "Controller"
49
- end
50
-
51
- def grid_controller_file
52
- Rails.root.join("app/controllers").join("#{grid_controller_class_name.underscore}.rb")
53
- end
54
-
55
- def grid_controller_short_name
56
- controller_file_name
57
- end
58
-
59
- def grid_model_name
60
- file_name.camelize.singularize
61
- end
62
-
63
- def grid_param_name
64
- grid_class_name.underscore
65
- end
66
-
67
- def pagination_helper_code
68
- if defined?(::WillPaginate)
69
- "will_paginate(@grid.assets)"
70
- else
71
- # Kaminari is default
72
- "paginate(@grid.assets)"
73
- end
74
- end
75
-
76
- def base_grid_file
77
- "app/grids/base_grid.rb"
78
- end
79
-
80
- def grid_route_name
81
- controller_class_name.underscore.gsub("/", "_") + "_path"
82
- end
83
-
84
- def index_action
85
- indent(<<-RUBY)
86
- def index
87
- @grid = #{grid_class_name}.new(grid_params) do |scope|
88
- scope.page(params[:page])
89
- end
90
- end
91
-
92
- protected
93
-
94
- def grid_params
95
- params.fetch(:#{grid_param_name}, {}).permit!
96
- end
97
- RUBY
98
- end
99
-
100
- protected
101
- def generate_routing_namespace(code)
102
- depth = regular_class_path.length
103
- # Create 'namespace' ladder
104
- # namespace :foo do
105
- # namespace :bar do
106
- namespace_ladder = regular_class_path.each_with_index.map do |ns, i|
107
- indent("namespace :#{ns} do\n", i * 2)
108
- end.join
109
-
110
- # Create route
111
- # get 'baz/index'
112
- route = indent(code, depth * 2)
113
-
114
- # Create `end` ladder
115
- # end
116
- # end
117
- end_ladder = (1..depth).reverse_each.map do |i|
118
- indent("end\n", i * 2)
119
- end.join
120
-
121
- # Combine the 3 parts to generate complete route entry
122
- namespace_ladder + route + "\n" + end_ladder
123
- end
124
-
125
- def file_exists?(name)
126
- name = Rails.root.join(name) unless name.to_s.first == "/"
127
- File.exist?(name)
128
- end
129
- end
@@ -1,15 +0,0 @@
1
- namespace :datagrid do
2
-
3
- desc "Copy table partials into rails application"
4
- task :copy_partials do
5
- require "fileutils"
6
- views_path = "app/views/datagrid"
7
- destination_dir = (Rails.root + views_path).to_s
8
- pattern = File.expand_path(File.dirname(__FILE__) + "/../../#{views_path}") + "/*"
9
- Dir[pattern].each do |template|
10
- puts "* copy #{template} => #{destination_dir}"
11
- FileUtils.mkdir_p destination_dir
12
- FileUtils.cp template, destination_dir
13
- end
14
- end
15
- end
@@ -1,6 +0,0 @@
1
- class <%= grid_controller_class_name %> < ApplicationController
2
-
3
- <%= index_action -%>
4
-
5
- end
6
-
@@ -1,5 +0,0 @@
1
- <%%= datagrid_form_for @grid, method: :get, url: <%= grid_route_name %> %>
2
-
3
- <%%= <%=pagination_helper_code%> %>
4
- <%%= datagrid_table @grid %>
5
- <%%= <%=pagination_helper_code%> %>